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