b6dd86fdf3
- 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---
149 lines
4.8 KiB
Markdown
149 lines
4.8 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
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)
|
|
|
|
```bash
|
|
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)
|
|
|
|
```bash
|
|
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)
|
|
|
|
```bash
|
|
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)
|
|
|
|
```bash
|
|
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)
|
|
|
|
```bash
|
|
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)
|
|
|
|
```bash
|
|
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)
|
|
|
|
```bash
|
|
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.
|