test(validation): preserve sandbox access across SSH hardening

secharden-ssh intentionally replaces authorized_keys with the managed
production key set, which locks out the bootstrap/dev key the validation
harness uses to drive the VM. After the first deploy that reaches SSH
hardening, the harness could no longer connect to fetch logs or run the
test suite, breaking the iteration loop.

Add restore_vm_access(): after each deploy, if SSH is unreachable, it
re-injects the validation pubkey OUT OF BAND via the Proxmox guest agent
(qm guest exec runs as root inside the VM and does not depend on SSH).
The injected payload is prefixed with a newline to avoid key
concatenation when the managed file lacks a trailing newline.

Config: ACCESS_PUBKEY (default ~/.ssh/id_ed25519.pub), RESTORE_ACCESS=1.
Disable with RESTORE_ACCESS=0.

🤖 Generated with [Crush](https://github.com/charmassociates/crush)

Assisted-by: GLM-5 via Crush <crush@charm.land>
This commit is contained in:
2026-07-27 10:13:04 -05:00
parent 5f26f7dca1
commit 6d77775bd6
+38
View File
@@ -54,6 +54,11 @@ VM_ID="${VM_ID:-}"
REPO_URL="${REPO_URL:-https://git.knownelement.com/KNEL/KNELServerBuild.git}"
REMOTE_REPO="${REMOTE_REPO:-KNELServerBuild}"
SNAP_PREFIX="${SNAP_PREFIX:-pre-knel-deploy}"
ACCESS_PUBKEY="${ACCESS_PUBKEY:-$HOME/.ssh/id_ed25519.pub}"
# Re-inject the validation pubkey after each deploy (secharden-ssh replaces
# authorized_keys with the managed production key set, locking out the
# bootstrap/dev key). Set RESTORE_ACCESS=0 to disable.
RESTORE_ACCESS="${RESTORE_ACCESS:-1}"
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_SRC="$(cd "$HERE/.." && pwd)"
@@ -99,6 +104,34 @@ resolve_remote_repo() {
vm "cd ~/${REMOTE_REPO} 2>/dev/null && pwd"
}
# Re-inject the validation pubkey into ~$VM_USER/.ssh/authorized_keys OUT OF
# BAND via the Proxmox guest agent (qm guest exec runs as root inside the VM
# and does not depend on SSH). This is necessary because secharden-ssh replaces
# authorized_keys with the managed production key set, which would otherwise
# lock out the bootstrap key used to drive validation. No-op if SSH still works.
restore_vm_access() {
[[ "$RESTORE_ACCESS" = "1" ]] || { log "RESTORE_ACCESS=0; skipping access restore."; return 0; }
[[ -f "$ACCESS_PUBKEY" ]] || { log "WARN: ACCESS_PUBKEY not found ($ACCESS_PUBKEY); cannot restore access."; return 0; }
if vm 'true' >/dev/null 2>&1; then
log "SSH access already works; no need to restore."
return 0
fi
log "SSH access lost (expected after secharden-ssh). Restoring via Proxmox guest agent..."
local payload_b64
# Leading newline guards against the managed authorized_keys lacking a
# trailing newline (which would otherwise concatenate two keys into one).
payload_b64="$(printf '\n%s' "$(cat "$ACCESS_PUBKEY")" | base64 -w0)"
prox "qm guest exec $VM_ID -- /bin/sh -c 'echo $payload_b64 | base64 -d >> /home/${VM_USER}/.ssh/authorized_keys'" \
>/dev/null 2>&1 || { log "WARN: guest-agent key append failed."; return 0; }
prox "qm guest exec $VM_ID -- /bin/sh -c 'chown ${VM_USER}:${VM_USER} /home/${VM_USER}/.ssh/authorized_keys; chmod 600 /home/${VM_USER}/.ssh/authorized_keys'" \
>/dev/null 2>&1 || true
if vm 'true' >/dev/null 2>&1; then
log "Access restored."
else
log "WARN: access still not working after restore. Check the deployed sshd_config."
fi
}
# ---------------------------------------------------------------------------
# Commands
# ---------------------------------------------------------------------------
@@ -211,6 +244,11 @@ cmd_deploy() {
runner_abs="$(vm "cd ~/${REMOTE_REPO}/Project-Tests/.run && pwd")/remote-setup-runner.sh"
vmroot "bash '$runner_abs' '$repo_abs'" 2>&1 | tee -a "$LOCAL_LOG" || true
# secharden-ssh (run near the end of setup) replaces authorized_keys with the
# managed production key set, locking out the bootstrap key. Restore the
# validation key out-of-band BEFORE we try to fetch the log over SSH.
restore_vm_access
# Fetch the remote log for full fidelity (strip ANSI color codes).
vm "sed -r 's/\\x1B\\[[0-9;]*[mK]//g' /tmp/knel-setup.log 2>/dev/null || cat /tmp/knel-setup.log" \
> "$LOCAL_LOG_DIR/setup-output-${STAMP}.log" 2>/dev/null || true