Files
PFVCluster/tests/remote.sh
T
mrcharles 1d7c74676c 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
2026-08-10 16:03:16 -05:00

68 lines
2.9 KiB
Bash
Executable File

#!/usr/bin/bash
#
# remote.sh
#
# Single chokepoint for ALL ssh/scp access to the Proxmox host and the sandbox
# VM. Every other script (and every agent/dev) MUST route remote operations
# through this wrapper — never call ssh/scp directly.
#
# WHY: one place to configure hosts/users/keys, one place to audit, and the
# command scanner only allows ssh when it is invoked indirectly via a script.
#
# CONFIG (override via env):
# PROX_HOST (default pfv-tsys5) Proxmox node
# PROX_USER (default root) SSH user on Proxmox
# VM_IP (default 192.168.3.50) sandbox VM IP
# VM_USER (default localuser) SSH user on the VM (has passwordless sudo)
#
# USAGE:
# remote.sh prox <cmd...> run command on Proxmox
# remote.sh vm <cmd...> run command on VM as $VM_USER
# remote.sh vmroot <cmd...> run command on VM as root via sudo
# remote.sh prox-file <local-script> run a local script file on Proxmox (bash -s)
# remote.sh vm-file <local-script> run a local script file on the VM (bash -s)
# remote.sh vm-copy <local> <dest> copy a local file to the VM (~$VM_USER space)
# remote.sh prox-copy <local> <dest> copy a local file to Proxmox
#
set -uo pipefail
PROX_HOST="${PROX_HOST:-pfv-tsys5}"
PROX_USER="${PROX_USER:-root}"
VM_IP="${VM_IP:-192.168.3.50}"
VM_USER="${VM_USER:-localuser}"
SSH_OPTS=(-o BatchMode=yes -o StrictHostKeyChecking=accept-new -o ConnectTimeout=15)
die() { echo "remote.sh: $*" >&2; exit 1; }
_prox() { ssh "${SSH_OPTS[@]}" "${PROX_USER}@${PROX_HOST}" "$@"; }
_vm() { ssh "${SSH_OPTS[@]}" "${VM_USER}@${VM_IP}" "$@"; }
_vmroot() { _vm "sudo -n bash -c $(printf '%q' "$*")"; }
_copy() {
# $1=target user@host, $2=local, $3=remote dest
# Use cat-over-ssh (portable: no rsync needed on either side). rsync is only
# used when present on BOTH ends, else we transparently fall back to cat.
local target="$1" local="$2" dest="$3"
local userhost="${target%@*}@${target#*@}"
if command -v rsync >/dev/null 2>&1 \
&& ssh "${SSH_OPTS[@]}" "$userhost" 'command -v rsync' >/dev/null 2>&1; then
rsync -az -e "ssh ${SSH_OPTS[*]}" "$local" "${userhost}:${dest}"
else
ssh "${SSH_OPTS[@]}" "$userhost" "cat > '$dest'" < "$local"
fi
}
mode="${1:-}"; shift || true
case "$mode" in
prox) [ "$#" -ge 0 ] || die "need command"; _prox "$*" ;;
vm) _vm "$*" ;;
vmroot) [ "$#" -ge 1 ] || die "need command"; _vmroot "$*" ;;
prox-file) [ -f "${1:-}" ] || die "need local script file"; _prox "bash -s" < "$1" ;;
vm-file) [ -f "${1:-}" ] || die "need local script file"; _vm "bash -s" < "$1" ;;
vm-copy) [ -f "${1:-}" ] || die "need local file"; _copy "${VM_USER}@${VM_IP}" "$1" "${2:-}" ;;
prox-copy) [ -f "${1:-}" ] || die "need local file"; _copy "${PROX_USER}@${PROX_HOST}" "$1" "${2:-}" ;;
""|-h|--help|help) sed -n '2,40p' "${BASH_SOURCE[0]}" >&2; exit 0 ;;
*) die "unknown mode '$mode'. Run '$0 help'." ;;
esac