Archived
proxmox: add IPA sudo and local backdoor scripts, update bootstrap notes
Secret Scan / Scan for secrets and sensitive config (push) Failing after 3s
Secret Scan / Scan for secrets and sensitive config (push) Failing after 3s
- setup-ipa-sudo.sh: grants %admins group NOPASSWD sudo after ipa-client-install; writes admins-proxmox (pvesh/qm/pct) only when those binaries are present, so the same script works on PBS/PDM as well as PVE hosts - create-local-backdoor.sh: creates a local 'pveadmin' account with SSH key and NOPASSWD sudo as an emergency fallback when IPA/SSSD is unavailable; password set via BACKDOOR_PASS env var or prompted interactively - bootstrap.sh: appended post-IPA-enrollment reminder to the final checklist Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -65,3 +65,9 @@ fi
|
|||||||
echo " - ${SCRIPT_DIR}/create-admin-user.sh <username> (PVE web UI account)"
|
echo " - ${SCRIPT_DIR}/create-admin-user.sh <username> (PVE web UI account)"
|
||||||
echo " - Enable 2FA/TOTP for that user and root@pam via the web UI"
|
echo " - Enable 2FA/TOTP for that user and root@pam via the web UI"
|
||||||
echo " - ${SCRIPT_DIR}/audit.sh (verify everything above)"
|
echo " - ${SCRIPT_DIR}/audit.sh (verify everything above)"
|
||||||
|
echo
|
||||||
|
echo " If this host will be enrolled in FreeIPA:"
|
||||||
|
echo " ipa-client-install --domain=sweet.home --realm=SWEET.HOME \\"
|
||||||
|
echo " --server=domain-controller.sweet.home --mkhomedir --ssh-trust-dns --no-ntp"
|
||||||
|
echo " ${SCRIPT_DIR}/setup-ipa-sudo.sh (NOPASSWD sudo for IPA admins group)"
|
||||||
|
echo " ${SCRIPT_DIR}/create-local-backdoor.sh <ssh-pubkey> (emergency local account)"
|
||||||
|
|||||||
Executable
+84
@@ -0,0 +1,84 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Create a local 'pveadmin' account as an emergency backdoor for when
|
||||||
|
# IPA/SSSD is unavailable. The account authenticates by SSH key only
|
||||||
|
# (password auth is disabled by harden-ssh.sh); the password set here
|
||||||
|
# is for physical console access only.
|
||||||
|
#
|
||||||
|
# Idempotent - safe to re-run. If the account already exists, the SSH key
|
||||||
|
# is refreshed but the password and account are left unchanged. Run as root.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./create-local-backdoor.sh <ssh-public-key>
|
||||||
|
# ./create-local-backdoor.sh --key-file <path-to-.pub>
|
||||||
|
#
|
||||||
|
# Set BACKDOOR_PASS env var to supply the console password non-interactively;
|
||||||
|
# otherwise you will be prompted.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
# shellcheck source=lib/common.sh
|
||||||
|
source "${SCRIPT_DIR}/lib/common.sh"
|
||||||
|
require_root
|
||||||
|
|
||||||
|
USERNAME="pveadmin"
|
||||||
|
|
||||||
|
SSH_KEY=""
|
||||||
|
if [ "${1:-}" = "--key-file" ]; then
|
||||||
|
KEY_FILE="${2:-}"
|
||||||
|
[ -z "$KEY_FILE" ] && { echo "ERROR: --key-file requires a path." >&2; exit 1; }
|
||||||
|
[ -f "$KEY_FILE" ] || { echo "ERROR: key file not found: $KEY_FILE" >&2; exit 1; }
|
||||||
|
SSH_KEY="$(cat "$KEY_FILE")"
|
||||||
|
else
|
||||||
|
SSH_KEY="${1:-}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$SSH_KEY" ]; then
|
||||||
|
echo "Usage: $0 <ssh-public-key>" >&2
|
||||||
|
echo " $0 --key-file <path-to-.pub>" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! echo "$SSH_KEY" | grep -qE '^(ssh-rsa|ssh-ed25519|ecdsa-sha2-nistp[0-9]+) [A-Za-z0-9+/=]'; then
|
||||||
|
echo "ERROR: argument doesn't look like a valid SSH public key." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if id "$USERNAME" >/dev/null 2>&1; then
|
||||||
|
echo "User '${USERNAME}' already exists -- not modifying account or password."
|
||||||
|
else
|
||||||
|
useradd --create-home --shell /bin/bash "$USERNAME"
|
||||||
|
echo "Created Linux user '${USERNAME}'."
|
||||||
|
|
||||||
|
if [ -n "${BACKDOOR_PASS:-}" ]; then
|
||||||
|
printf '%s:%s\n' "$USERNAME" "$BACKDOOR_PASS" | chpasswd
|
||||||
|
echo "Console password set."
|
||||||
|
else
|
||||||
|
echo "Set a console password for '${USERNAME}' (used for physical console access only):"
|
||||||
|
passwd "$USERNAME"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
HOME_DIR="$(getent passwd "$USERNAME" | cut -d: -f6)"
|
||||||
|
SSH_DIR="${HOME_DIR}/.ssh"
|
||||||
|
AUTH_FILE="${SSH_DIR}/authorized_keys"
|
||||||
|
|
||||||
|
mkdir -p "$SSH_DIR"
|
||||||
|
chmod 700 "$SSH_DIR"
|
||||||
|
chown "${USERNAME}:${USERNAME}" "$SSH_DIR"
|
||||||
|
|
||||||
|
if grep -qF "$SSH_KEY" "$AUTH_FILE" 2>/dev/null; then
|
||||||
|
echo "SSH key already present in ${AUTH_FILE}."
|
||||||
|
else
|
||||||
|
printf '%s\n' "$SSH_KEY" >> "$AUTH_FILE"
|
||||||
|
echo "Installed SSH key in ${AUTH_FILE}."
|
||||||
|
fi
|
||||||
|
chmod 600 "$AUTH_FILE"
|
||||||
|
chown "${USERNAME}:${USERNAME}" "$AUTH_FILE"
|
||||||
|
|
||||||
|
SUDOERS_FILE="/etc/sudoers.d/${USERNAME}-nopasswd"
|
||||||
|
write_if_changed "$SUDOERS_FILE" "${USERNAME} ALL=(root) NOPASSWD: ALL"
|
||||||
|
chmod 0440 "$SUDOERS_FILE"
|
||||||
|
visudo -c >/dev/null
|
||||||
|
echo "Sudoers rule for '${USERNAME}' is valid."
|
||||||
|
echo
|
||||||
|
echo "'${USERNAME}' is ready: SSH key login, NOPASSWD sudo, console password set."
|
||||||
Executable
+45
@@ -0,0 +1,45 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Grant the IPA 'admins' group passwordless sudo on this host.
|
||||||
|
#
|
||||||
|
# Writes two files:
|
||||||
|
# /etc/sudoers.d/admins-nopasswd -- NOPASSWD: ALL for general shell use
|
||||||
|
# /etc/sudoers.d/admins-proxmox -- NOPASSWD for pvesh/qm/pct (PVE only;
|
||||||
|
# skipped silently if those binaries
|
||||||
|
# aren't present, e.g. on PBS/PDM)
|
||||||
|
#
|
||||||
|
# Idempotent - safe to re-run. Run as root on the target host after
|
||||||
|
# ipa-client-install has been completed and SSSD is active.
|
||||||
|
#
|
||||||
|
# Usage: ./setup-ipa-sudo.sh
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
# shellcheck source=lib/common.sh
|
||||||
|
source "${SCRIPT_DIR}/lib/common.sh"
|
||||||
|
require_root
|
||||||
|
|
||||||
|
if [ ! -f /etc/ipa/default.conf ]; then
|
||||||
|
echo "ERROR: /etc/ipa/default.conf not found -- is this host enrolled in FreeIPA?" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
write_if_changed /etc/sudoers.d/admins-nopasswd '%admins ALL=(root) NOPASSWD: ALL'
|
||||||
|
chmod 0440 /etc/sudoers.d/admins-nopasswd
|
||||||
|
|
||||||
|
# PVE-specific tools -- pvesh moved from /usr/sbin to /usr/bin in PVE 8.x;
|
||||||
|
# resolve at script time so the path in the sudoers rule is always correct.
|
||||||
|
PVESH="$(command -v pvesh 2>/dev/null || true)"
|
||||||
|
QM="$(command -v qm 2>/dev/null || true)"
|
||||||
|
PCT="$(command -v pct 2>/dev/null || true)"
|
||||||
|
|
||||||
|
if [ -n "$PVESH" ] && [ -n "$QM" ] && [ -n "$PCT" ]; then
|
||||||
|
write_if_changed /etc/sudoers.d/admins-proxmox \
|
||||||
|
"%admins ALL=(root) NOPASSWD: ${PVESH}, ${QM}, ${PCT}"
|
||||||
|
chmod 0440 /etc/sudoers.d/admins-proxmox
|
||||||
|
echo "Proxmox tools found -- wrote admins-proxmox."
|
||||||
|
else
|
||||||
|
echo "pvesh/qm/pct not found -- skipping admins-proxmox (not a PVE host)."
|
||||||
|
fi
|
||||||
|
|
||||||
|
visudo -c >/dev/null
|
||||||
|
echo "All sudoers files valid. IPA admins group has sudo on this host."
|
||||||
Reference in New Issue
Block a user