Files
orca/docs/security-runbook.md
Jon Chery b6dd86fdf3 docs(P11): doc drift round 2 — README, cli.md, CHANGELOG, verify-reqs (REQ-160)
- README: status banner v0.12+v0.13, latest tag v0.12.10, subcommand
  table expanded (auth/nft/peer-setup/secrets rotate-master), "mTLS by
  default" corrected to "SSH-push canonical", docs table updated
- docs/cli.md: complete rewrite (521->1465 lines), all ~40 subcommands
- CHANGELOG: regenerated from git log (v0.11.29..HEAD)
- help text: job run HCL->markdown, job stop daemon->SSH-push
- docs/security-runbook.md: expanded to match P05 reality (seal/unseal,
  doctor audit/modes/oidc, incident response)
- docs/webauthn.md: added auth register (P06)
- docs/namespace.md: added inherit + set-constraint
- internal/proxmox/bootstrap.go: comments password->key auth
- internal/cli/status.go: deprecation warning
- scripts/verify-docs.sh + make verify-docs: cli.md <-> orca --help
- cmd/verify-reqs/main.go: fix bold-format regex (was bypassing v0.12)
  + case-insensitive status matching
- .ciagent/REQUIREMENTS.md: v0.12 REQs marked complete
- .ciagent/ROADMAP.md: v0.12 bolded COMPLETE

---ci---
project: orca
phase: 11
milestone: v0.13
status: complete
requirements:
  covered: [160]
---/ci---
2026-08-10 14:18:27 +00:00

4.8 KiB

Security Runbook (v0.13)

This runbook documents the operational security procedures for orca's zero-trust identity model (R-021): human identity is exclusively external (OIDC), machine identity is exclusively mTLS/SPIFFE, and no passwords / Orca-issued tokens / CA-key passphrases exist anywhere in the system. The v0.12 milestone shipped these capabilities; the v0.13 milestone wired them operationally (R-023).

Master Key Seal/Unseal (REQ-147, P05)

The cluster master key (ClusterDir()/master.key, mode 0600) encrypts all namespace .env.secrets via per-namespace HKDF-SHA256 sub-keys (AES-256-GCM). The master key can be sealed (encrypted at rest) and unsealed (unwrapped into memory for use).

Seal

orca cluster seal

Encrypts the raw master key with a key derived from either:

  • the OIDC ID token subject (if orca auth login has been run), or
  • the cluster CA fingerprint (mTLS-only offline path, D-241).

The sealed blob is written to ClusterDir()/master.key.sealed (0600). Five Shamir shards (3-of-5 recovery) are printed to stdout — store them offline. The raw master key is then deleted from disk so the cluster is sealed at rest.

Unseal

orca cluster unseal

Reads the sealed blob and unwraps the master key using the OIDC ID token subject or the cluster CA fingerprint. The unwrapped key is written back to ClusterDir()/master.key (0600) and zeroed from memory on process exit.

Recovery (IdP lost)

orca cluster unseal --recovery

If the IdP is permanently lost, the operator is prompted for 3 of the 5 Shamir shards printed at seal time. With quorum, the master key is reconstructed and written back to disk. If quorum is unavailable, the cluster is unrecoverable by design (C-35: no backdoor).

Master Key Rotation (REQ-129, C-30)

orca secrets rotate-master [--dry-run]

Generates a new master key, re-encrypts every namespace's .env.secrets under the new key, and re-seals the master key to OIDC. With --dry-run, reports affected namespaces without writing.

  • Atomic per-namespace: each namespace is re-encrypted independently.
  • Automatic rollback: on any namespace failure, the old sealed key is restored (C-30).
  • No passphrase (R-021): the master key is sealed to OIDC, not to a human-typed passphrase.

File-Mode Audit (REQ-033, REQ-130, F13)

orca doctor modes

Verifies file modes on security-sensitive files across ORCA_HOME:

  • private keys / secrets: 0600
  • certs / public keys: 0644

Exits 0 if all files have correct modes; exits 1 if any violation is found. Missing files are not counted as violations.

Checks: SSH key, master key (sealed blob), server cert/key, known_hosts, acl.json, OIDC client secret.

Audit Log Tamper-Evidence (REQ-125, F2)

orca doctor audit

Verifies the audit log hash chain. Opens the orca SQLite DB, recomputes the hash chain from the first audit entry, and reports the chain head hash. If any entry's entry_hash or prev_hash link does not match the recomputed value, the chain has been tampered with and the command exits non-zero.

The audit log is append-only (SQLite trigger blocks UPDATE/DELETE). Each entry's actor field carries the OIDC sub or SPIFFE SVID. Run this after any suspected intrusion or as part of a regular audit cadence.

Sudoers Audit (REQ-134, F22)

orca doctor proxmox

Audits the /etc/sudoers.d/orca file against the expected allowlist:

  • pct + qm with NOEXEC
  • apt-get / dpkg excluded (or NOEXEC'd)
  • pvesh EXCLUDED (AD-020: pvesh can bypass NOEXEC via the API execute endpoint)

nft Audit (REQ-133, F21)

orca doctor nft

Audits the live nftables ingress ruleset against the on-disk /etc/nftables.d/orca.nft hash (recorded at the latest applied txn). Reports drift if the live ruleset does not match. Also verifies:

  • table exists
  • DNAT :443 → 127.0.0.1:8443 and :80 → 127.0.0.1:8080 present
  • rate-limit meter present
  • /etc/nftables.d/orca.nft parses

Incident Response

  1. Revoke the compromised identity (OIDC user/group or SPIFFE SVID).
  2. Rotate the master key (orca secrets rotate-master).
  3. Review the audit log (orca doctor audit verifies the hash chain; orca audit list shows entries).
  4. Check file modes (orca doctor modes detects permission drift).
  5. If the master key is compromised, all historical secrets are compromised (no forward secrecy — documented residual risk).
  6. Re-seal the master key after rotation (orca cluster seal).

OIDC Provider Health (P06)

orca doctor oidc

Checks the bundled Dex OIDC provider health. Verifies the Dex systemd unit is running and the /.well-known/openid-configuration endpoint responds. Run after orca auth init-idp or after a Dex config change.