diff --git a/Project-Tests/vm-validation.sh b/Project-Tests/vm-validation.sh index db55399..b6d924e 100755 --- a/Project-Tests/vm-validation.sh +++ b/Project-Tests/vm-validation.sh @@ -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