Dotfiles/setup/tools/passwordless-sudo.sh

105 lines
3.4 KiB
Bash
Executable File

#!/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