net-kingdom/docs/openbao-unseal-custody-models.md
tegwick d9557ba90e
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Harden remaining bootstrap custody callers and prepare isolated recovery
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a13eab-1e6a-7b33-9c37-372e90ada3a2
2026-10-15 22:57:14 +02:00

5.6 KiB
Raw Blame History

OpenBao Unseal Custody Models

Date: 2026-06-17 (updated 2026-07-02)
Status: all three models implemented — automation path proven greenfield; production models gated by deployment profile and evidence

NetKingdom bootstrap must support three OpenBao init/unseal custody models. Development starts with maximum automation for fast test cycles, then adds human custody gates as production trust increases.

This is separate from king custody mode (temporary-single-king, two-of-three-planned, two-of-three-ready) which governs who holds platform recovery authority. Unseal custody models govern how init/unseal executes during bootstrap and rebuild.


Models

Model ID Label Custody strength Automation Status
sops-held-automation SOPS-held unseal Lab / fast iteration High Implemented (console + creds agent path; greenfield-proven 2026-07-02)
attended-ceremony Attended ceremony Production Low Implemented (runbook + ceremony-record validator)
auto-unseal-transit Auto-unseal (transit/KMS) Production HA High Implemented (Helm seal stanza prepared; gate blocked until seal configured + verified)

sops-held-automation (default for greenfield dev)

  • Init/unseal material lives in SOPS/age custody bundle (not Git plaintext).
  • Applied by sso-mfa/bootstrap/openbao-init-unseal.sh (make openbao-init-unseal, NET-WP-0020 T2) after cluster + OpenBao pod exist. The helper enforces the console custody-model gate, initializes only when uninitialized (init JSON written straight into the age-custody secrets dir), replays unseal shares stdin-to-stdin, verifies post-unseal state, and emits non-secret openbao_initialized / openbao_post_unseal_verified evidence. The current adapter additionally requires an explicit lab profile, an owner-admitted KUBECONFIG, OPENBAO_EXPECTED_CLUSTER_UID, and owned private custody paths. Existing init files are never replaced; diagnostics and shares remain contained. --dry-run is a non-mutating plan without cluster reads. Platform configuration is a separate owner operation; OPENBAO_RUN_CONFIGURE_INITIAL=1 is refused. The July greenfield receipt is historical, not execution proof for this October revision.
  • Enables unattended rebuild test cycles on a 3-node slate.
  • Not production trust posture — use to prove S1→S3→SSH engine automation, then graduate to stronger models.

attended-ceremony (production)

  • Human-attended bao operator init, out-of-band unseal share escrow, root token retirement — runbook: docs/openbao-attended-ceremony-runbook.md (command detail in railiance-platform/docs/openbao.md).
  • Matches first successful NetKingdom bootstrap (NET-WP-0015–0017).
  • Console keeps the refuse-live-init boundary; the ceremony is evidenced by a non-secret record validated with validate-openbao-ceremony-record (make security-bootstrap-validate-openbao-ceremony-record).

auto-unseal-transit (production HA)

  • OpenBao seal configuration uses transit or cloud KMS auto-unseal.
  • Pod restart without manual unseal threshold ceremony.
  • Seal stanza prepared (disabled by default) in railiance-platform/helm/openbao-values.yaml; enable + migrate per railiance-platform/docs/openbao.md "Auto-Unseal via Transit Seal".
  • Console init gate stays blocked until openbao_transit_seal_configured and openbao_auto_unseal_verified are set in the non-secret metadata.

Deployment profile

The console metadata carries a deployment_profile (lab default, production). The production profile blocks sops-held-automation — its SOPS bundle holds root token and unseal shares together, which is lab posture only. Selection, status gates, and openbao-init-unseal.sh all enforce the block:

make security-bootstrap-select-deployment-profile PROFILE=production

Each model is selectable in the security bootstrap console; gates express what evidence is still missing for the selected model.


Console integration

# List models and implementation status
python3 tools/security-bootstrap-console/security_bootstrap_console.py \
  openbao-unseal-custody-models

# Select active model (only implemented models succeed)
python3 tools/security-bootstrap-console/security_bootstrap_console.py \
  select-openbao-unseal-custody-model \
  --model sops-held-automation \
  --metadata .local/security-bootstrap.json

# Status shows gate: "OpenBao unseal custody model"
make security-bootstrap-console   # or: ... status --metadata .local/...

Metadata field: openbao_unseal_custody_model


Automation chain (after model selected)

Step Owner Target
S1 OS baseline railiance-infra 3 nodes
S2 k3s HA railiance-cluster ThreePhoenix
S3 OpenBao deploy railiance-platform make openbao-deploy
Init/unseal apply net-kingdom make openbao-init-unseal (sops-held)
Platform config railiance-platform openbao-configure-initial
SSH engine railiance-platform openbao-configure-ssh (planned)
Host CA trust railiance-infra bootstrap-ssh-ca (planned)
Sign smoke ops-warden warden sign (WP-0008 T2)

  • docs/smooth-bootstrap-guide.md — Step 5 (OpenBao init/unseal)
  • docs/platform-root-custody.md — king / quorum custody
  • railiance-platform/docs/openbao.md — deploy and ceremony
  • ops-warden/wiki/OpenBaoSshEngineChecklist.md — SSH engine verify
  • ops-warden/history/2026-06-17-openbao-production-verify.md — current blockers