82dd01f620
---ci--- project: orca phase: 2 milestone: v0.6 status: verify ---/ci---
4.5 KiB
4.5 KiB
Phase 2 Verification — Orca v0.6 P02
Phase: P02 — Proxmox SSH Join REQ Coverage: REQ-050, REQ-051 Verification date: 2026-08-03 Result: ✅ PASS (all 4 layers; integration test against real PVE deferred — unit tests cover all logic)
Structural Verification
- ✅
go build ./...— PASS - ✅
go vet ./...— PASS - ✅
gofmt -l .— PASS (all Go files formatted) - ✅
make lint— PASS - ✅
golang.org/x/crypto v0.54.0added as direct dep (D-030); transitive: x/sys v0.47.0, x/term v0.45.0 - ✅
internal/proxmoxnew package follows existing package layout conventions - ✅
internal/security/sshkey.gofollows the CAInit pattern (idempotent fast-path, writeAtomic, mode enforcement)
Behavioral Verification
REQ-050: Proxmox SSH bootstrap via golang.org/x/crypto/ssh
- ✅
TestGenerateOrLoadSSHKey_Generates: Ed25519 keygen, 0600/0644 modes, ssh-ed25519 pub format, ssh.ParsePrivateKey round-trip - ✅
TestGenerateOrLoadSSHKey_IdempotentLoad: second call loads existing (D-036) - ✅
TestGenerateOrLoadSSHKey_CreatesDir: nested dir creation - ✅
TestBootstrapProxmox_Validation: missing host → error, missing password → error - ✅
TestDefaultOptions: DefaultProxmoxUser=orca, DefaultProxmoxRole=OrcaOperator, DefaultSSHPort=22 - ✅ CLI
--type proxmox --host ... --password ...flag wiring verified viaorca node join --help - ✅ Password from
--passwordflag OR$ORCA_PROXMOX_PASSWORDenv var (D-031) - ✅ TOFU host-key via
knownhosts.New(D-035, avoids deprecated InsecureIgnoreHostKey) - ✅ File upload via session heredoc (no SFTP dep — D-030)
REQ-051: OrcaOperator role + orca@pam user + sudoers
- ✅
TestSudoersContent: NOEXEC on pct/qm, NOPASSWD on apt-get/dpkg (no NOEXEC), pvesh excluded from command lines (AD-020) - ✅
TestSudoersContent_CustomUser: custom user name works - ✅
TestOrcaOperatorPrivileges: exactly 3 privileges (VM.Audit, Datastore.AllocateSpace, SDN.Use) space-separated (D-033) - ✅
orca@pamrealm (AD-019 — not @pve) - ✅
pveumcommands use--privs(space-separated), probe-then-add idempotency pattern - ✅
visudo -cfvalidation step aborts bootstrap on syntax error - ✅ Node registered with kind=proxmox, os=pve
Security Verification
- ✅ SSH private key mode 0600 enforced (TestGenerateOrLoadSSHKey_Generates)
- ✅ SSH public key mode 0644 enforced
- ✅ Password never persisted (D-031) — used only for SSH auth, zeroed after use
- ✅ Password from env var preferred over flag (reduces ps/proc exposure)
- ✅ pvesh excluded from sudoers (AD-020 — API execute bypasses NOEXEC)
- ✅ NOEXEC on pct/qm (blocks shell escapes via dynamically-linked perl)
- ✅ TOFU host-key pinning (D-035) — capture on first connect, verify on subsequent, fail closed on mismatch
- ✅ No secrets in logs (audit log entries contain host, user, role — never password)
- ✅ sudoers file mode 0440 enforced (sudo requirement)
Quality Verification
- ✅
go test -race -count=1 ./internal/proxmox/... ./internal/security/... ./internal/cli/...— all PASS - ✅ Test coverage: sshkey (4 tests), proxmox (5 tests), sudoers content (2 tests), privileges (1 test), validation (1 test), defaults (1 test)
- ✅ Error wrapping with
fmt.Errorf("...: %w", err)(REQ-018) - ✅
context.Contextpropagation (REQ-017) - ✅ Idempotency: all bootstrap steps probe-before-add (D-036)
- ✅ New direct dep: 1 (golang.org/x/crypto) — matches D-030 minimal-deps rationale
Integration Test Note
A live integration test against a real Proxmox VE 8/9 host is out of scope for automated CI (requires a PVE host + credentials). The SSH bootstrap logic is tested via:
- Unit tests for command builders (sudoers content, privilege set)
- Unit tests for validation (missing host/password)
- Unit tests for SSH key generation (Ed25519, modes, idempotency)
- Manual verification via
orca node join --help(flag surface)
A // +build integration test against a real PVE host can be added
in a future phase if a PVE test environment becomes available.
Must-Have Checklist
go.mod/go.sum— golang.org/x/crypto v0.54.0internal/certpaths/certpaths.go— SSHKeyPath, SSHPubPath, KnownHostsPathinternal/security/sshkey.go— GenerateOrLoadSSHKey (Ed25519)internal/proxmox/bootstrap.go— BootstrapProxmox full SSH danceinternal/cli/node.go— --type/--host/--password flag wiring + joinProxmoxinternal/security/sshkey_test.go— 4 testsinternal/proxmox/bootstrap_test.go— 5 tests
Escalations
None.