fix(access): ban guest-agent as access channel — SSH only [#403]
Previous sessions used `qm guest exec` to back-door SSH keys into ~30 VMs, bypassing sshd's audit trail in an ITAR/CMMC environment. Wire the ban deep so it cannot recur: - tests/remote.sh: remove the vm-guest mode + qm-guest-exec path entirely - scripts/check-rules.sh: rule #11 fails on any `qm guest exec` / `vm-guest` pattern in code (scans .sh/.bash/.py; docs may describe the ban freely) - AGENTS.md: codify "Access-channel policy: SSH only" as non-negotiable; add "Questions" rule banning harness question tools (use questions-v1.md) - tests/vm-validation.sh: drop guest-agent key re-injection; SSH-only - proxmox/perf/scripts/perf-matrix.sh + deploy-tuned-guests.sh: convert guest-agent execution to SSH (vmroot) now that VMs have key + sudo - bootstrap-all.sh: re-target the 8 remaining locked-out systems with correct users/methods; print a console one-liner for publickey-only Pis Guest-agent remains installable/checkable for Proxmox state visibility — never as an execution or key-delivery path. 💘 Generated with Crush Assisted-by: Crush:glm-5.2
This commit is contained in:
+39
-30
@@ -1,14 +1,17 @@
|
||||
#!/usr/bin/bash
|
||||
# bootstrap-all.sh — push agent key + sudo to every remaining NO-KEY system.
|
||||
# bootstrap-all.sh — push agent SSH key + passwordless sudo to remaining systems.
|
||||
#
|
||||
# SSH is the ONLY approved access channel (see AGENTS.md "Access-channel
|
||||
# policy: SSH only"). This script reaches systems that still allow password
|
||||
# auth over sshd. Systems that reject password auth (publickey-only) cannot
|
||||
# be reached this way — see the CONSOLE-ONLY section printed at the end.
|
||||
#
|
||||
# Two escalation methods:
|
||||
# sudo → Ubuntu systems (no root password, localuser has sudo)
|
||||
# su → Debian systems (root has a password)
|
||||
# sudo → Ubuntu-style systems (no root pw; localuser has sudo)
|
||||
# su → Debian-style systems (root has a password)
|
||||
#
|
||||
# Passes AGENT_USER so agent-bootstrap.sh pushes the key + sudo to the
|
||||
# correct unprivileged user per system type.
|
||||
#
|
||||
# You'll enter passwords interactively. Idempotent: safe to re-run.
|
||||
# Passes AGENT_USER so agent-bootstrap.sh targets the correct unprivileged
|
||||
# user. You enter passwords interactively. Idempotent: safe to re-run.
|
||||
set -u
|
||||
cd "$(dirname "$0")" || exit 1
|
||||
|
||||
@@ -39,35 +42,41 @@ run_with_su() {
|
||||
echo
|
||||
}
|
||||
|
||||
# === Ubuntu: localuser + sudo ===
|
||||
echo "### Ubuntu (localuser + sudo) ###"
|
||||
# === localuser + sudo (password auth confirmed on) ===
|
||||
echo "### localuser + sudo ###"
|
||||
echo
|
||||
run_with_sudo tsys-siem 100.72.35.113 localuser
|
||||
run_with_sudo sectestbed-cloudron 100.97.140.105 localuser
|
||||
run_with_sudo kali-tsys 100.82.30.115 localuser
|
||||
run_with_sudo pfvsvrpi 100.91.151.113 localuser
|
||||
run_with_sudo tsys-siem 100.72.35.113 localuser
|
||||
run_with_sudo sectestbed-cloudron 100.97.140.105 localuser
|
||||
|
||||
# === Debian: subodev + su ===
|
||||
echo "### Debian: subodev + su ###"
|
||||
# === subodev/ultixfield + su (password auth confirmed on) ===
|
||||
echo "### subodev/ultixfield + su ###"
|
||||
echo
|
||||
run_with_su subopi3 100.93.17.77 subodev subodev
|
||||
run_with_su subopi-dev-3 100.64.231.65 subodev subodev
|
||||
run_with_su subopi-dev-4 100.65.224.85 subodev subodev
|
||||
|
||||
# === Debian: ultixfield + su ===
|
||||
echo "### Debian: ultixfield + su ###"
|
||||
echo
|
||||
run_with_su ultix-field 100.115.233.124 ultixfield ultixfield
|
||||
run_with_su subopi-dev-3 100.64.231.65 subodev subodev
|
||||
run_with_su ultix-field 100.115.233.124 ultixfield ultixfield
|
||||
|
||||
echo "========================================"
|
||||
echo "Done. Tell the agent to re-run access-matrix.sh to verify."
|
||||
echo "Done. Re-run access-matrix.sh to verify."
|
||||
echo "========================================"
|
||||
echo "Blocked — need console work (separate ticket):"
|
||||
echo " stlpc-3dscanner — bring online + rename [#417]"
|
||||
echo
|
||||
echo "CONSOLE-ONLY — sshd rejects password auth (publickey-only)."
|
||||
echo "Log in at the physical console (as root, or user then su/sudo)"
|
||||
echo "and paste this ONE line:"
|
||||
echo
|
||||
cat <<'ONELINER'
|
||||
KEY='ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIWms/uCXnjjo4KyxHBcYI2TDHe8OZ2wle6W/0hSRQLu reachableceo@ultix-streaming'; for u in root localuser subodev ultixfield; do getent passwd "$u">/dev/null||continue; H=$(getent passwd "$u"|cut -d: -f6); mkdir -p "$H/.ssh"; chmod 700 "$H/.ssh"; AK="$H/.ssh/authorized_keys"; touch "$AK"; chmod 600 "$AK"; grep -qF "$KEY" "$AK"||echo "$KEY">>"$AK"; chown -R "$u": "$H/.ssh"; done; for u in localuser subodev ultixfield; do getent passwd "$u">/dev/null&&[ -d /etc/sudoers.d ]&&{ echo "$u ALL=(ALL) NOPASSWD:ALL">/etc/sudoers.d/010-agent; chmod 440 /etc/sudoers.d/010-agent; }; done; echo DONE
|
||||
ONELINER
|
||||
echo
|
||||
echo " pfvsvrpi (localuser) — Raspberry Pi"
|
||||
echo " subopi3 (subodev) — Raspberry Pi"
|
||||
echo " subopi-dev-4 (subodev) — Raspberry Pi"
|
||||
echo "========================================"
|
||||
echo "Excluded (managed via API, not SSH):"
|
||||
echo " tsys-ucs-01, tsys-ucs-02"
|
||||
echo "Deferred (separate ticket):"
|
||||
echo " stlp-3dscanner — rename + bring online first [#417]"
|
||||
echo "========================================"
|
||||
echo "2FA by design (leave alone):"
|
||||
echo " sectestbed-sandbox"
|
||||
echo "By design (leave alone):"
|
||||
echo " sectestbed-sandbox — 2FA enforced"
|
||||
echo "========================================"
|
||||
echo "Excluded by policy (no SSH access):"
|
||||
echo " pfv-bms (API), tsys-cloudron (prod revenue),"
|
||||
echo " tsys-ucs-01/02 (API-managed), tsys-umbrel (treasury)"
|
||||
echo "========================================"
|
||||
|
||||
Reference in New Issue
Block a user