- 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---
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 loginhas 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+qmwith NOEXECapt-get/dpkgexcluded (or NOEXEC'd)pveshEXCLUDED (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:8443and:80 → 127.0.0.1:8080present - rate-limit meter present
/etc/nftables.d/orca.nftparses
Incident Response
- Revoke the compromised identity (OIDC user/group or SPIFFE SVID).
- Rotate the master key (
orca secrets rotate-master). - Review the audit log (
orca doctor auditverifies the hash chain;orca audit listshows entries). - Check file modes (
orca doctor modesdetects permission drift). - If the master key is compromised, all historical secrets are compromised (no forward secrecy — documented residual risk).
- 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.