feat(setup/tools): add passwordless-sudo.sh toggle script
For sessions that need to run a string of sudo commands with nothing around to answer a password prompt (unattended VM builds, agent-driven scripting). Drops a validated sudoers.d NOPASSWD entry for the current user on enable, removes it on disable. Off by default, not part of the regular install/update flow. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TLz6HWsXCwzQ97LrLt2em6main
parent
716902f8e1
commit
682e3769f6
|
|
@ -0,0 +1,104 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# =============================================================================
|
||||||
|
# passwordless-sudo.sh — toggle temporary NOPASSWD sudo for the current user
|
||||||
|
# =============================================================================
|
||||||
|
# Some workflows (unattended VM builds, agent-driven scripting sessions) need
|
||||||
|
# to run a string of `sudo` commands with nothing around to answer a password
|
||||||
|
# prompt. This drops a single sudoers.d file granting the invoking user full
|
||||||
|
# NOPASSWD sudo, and removes it again just as easily.
|
||||||
|
#
|
||||||
|
# This is a deliberate, temporary reduction in local security — anything
|
||||||
|
# running as your user can become root without a password while it's active.
|
||||||
|
# Turn it off (`disable`) as soon as whatever needed it is done. It does NOT
|
||||||
|
# persist across the dotfiles install/update flow — it's a manual toggle you
|
||||||
|
# reach for and put back, not a permanent config.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# passwordless-sudo.sh enable [--yes] Grant NOPASSWD sudo to $USER
|
||||||
|
# passwordless-sudo.sh disable Revoke it
|
||||||
|
# passwordless-sudo.sh status Report whether it's currently active
|
||||||
|
#
|
||||||
|
# The drop-in is validated with `visudo -c` before being installed, so a typo
|
||||||
|
# here can't corrupt sudo for the whole system.
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
# lib/logging.sh lives at setup/modules/lib/, two levels up from setup/tools/.
|
||||||
|
source "$SCRIPT_DIR/../modules/lib/logging.sh"
|
||||||
|
|
||||||
|
TARGET_USER="$(id -un)"
|
||||||
|
SUDOERS_FILE="/etc/sudoers.d/90-${TARGET_USER}-temp-nopasswd"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
printf 'Usage: %s {enable|disable|status} [--yes]\n' "$(basename "$0")" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
[[ $# -ge 1 ]] || usage
|
||||||
|
ACTION="$1"; shift || true
|
||||||
|
ASSUME_YES=0
|
||||||
|
for arg in "$@"; do
|
||||||
|
case "$arg" in
|
||||||
|
-y|--yes) ASSUME_YES=1 ;;
|
||||||
|
*) usage ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
is_enabled() { [[ -f "$SUDOERS_FILE" ]]; }
|
||||||
|
|
||||||
|
cmd_status() {
|
||||||
|
if is_enabled; then
|
||||||
|
log "Passwordless sudo is ENABLED for $TARGET_USER ($SUDOERS_FILE)"
|
||||||
|
else
|
||||||
|
skip "Passwordless sudo is disabled for $TARGET_USER"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_enable() {
|
||||||
|
if is_enabled; then
|
||||||
|
skip "Already enabled — nothing to do."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
warn "This grants $TARGET_USER full root access with NO password prompt,"
|
||||||
|
warn "system-wide, until you run: $(basename "$0") disable"
|
||||||
|
if [[ $ASSUME_YES -ne 1 ]]; then
|
||||||
|
read -rp "Proceed? [y/N] " _ans
|
||||||
|
[[ "${_ans,,}" == "y" ]] || { skip "Aborted."; exit 0; }
|
||||||
|
fi
|
||||||
|
|
||||||
|
local tmp
|
||||||
|
tmp="$(mktemp)"
|
||||||
|
printf '%s ALL=(ALL) NOPASSWD: ALL\n' "$TARGET_USER" > "$tmp"
|
||||||
|
|
||||||
|
# Validate the drop-in in isolation before it ever touches /etc/sudoers.d —
|
||||||
|
# visudo -c checks syntax without requiring the file to be in place first.
|
||||||
|
if ! sudo visudo -c -f "$tmp" >/dev/null; then
|
||||||
|
err "Generated sudoers snippet failed validation — not installing it."
|
||||||
|
rm -f "$tmp"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
sudo install -m 0440 -o root -g root "$tmp" "$SUDOERS_FILE"
|
||||||
|
rm -f "$tmp"
|
||||||
|
log "Passwordless sudo enabled for $TARGET_USER."
|
||||||
|
warn "Remember to run: $(basename "$0") disable"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_disable() {
|
||||||
|
if ! is_enabled; then
|
||||||
|
skip "Already disabled — nothing to do."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
sudo rm -f "$SUDOERS_FILE"
|
||||||
|
log "Passwordless sudo disabled for $TARGET_USER."
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$ACTION" in
|
||||||
|
enable) cmd_enable ;;
|
||||||
|
disable) cmd_disable ;;
|
||||||
|
status) cmd_status ;;
|
||||||
|
*) usage ;;
|
||||||
|
esac
|
||||||
Loading…
Reference in New Issue