This repository has been archived on 2026-07-08. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
net-kingdom/history/2026-07-02-openbao-greenfield-init-unseal-proof.md
tegwick 85a781b7a4 NET-WP-0020 finished: attended-ceremony + auto-unseal-transit profiles, greenfield init/unseal proof
T2: greenfield live proof against a fresh uninitialized OpenBao 2.5.5 —
caught and fixed 'bao operator unseal -' not reading stdin (now
'bao write sys/unseal key=-'); init and reseal-replay paths proven.
T3: attended-ceremony selectable — runbook, non-secret ceremony-record
template + validator, and a lab/production deployment profile that blocks
sops-held-automation in console selection, gates, and the init script.
T4: console gate + evidence flags for auto-unseal-transit (Helm seal stanza
prepared in railiance-platform).
Also: SCOPE.md refreshed to current repo state; adhoc fix for the broken
check-secrets Make target (unescaped $).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 22:08:33 +02:00

41 lines
2.0 KiB
Markdown

# OpenBao greenfield init/unseal proof (NET-WP-0020 T2)
Date: 2026-07-02
Scope: `sso-mfa/bootstrap/openbao-init-unseal.sh` proven live against a
genuinely uninitialized OpenBao 2.5.5 instance.
## Method
A fresh local `bao server` (file storage, throwaway scratchpad dir) was started
uninitialized and sealed. A `kubectl` shim forwarded the script's
`kubectl -n openbao exec openbao-0 -- bao …` calls to the local instance, so
the script ran byte-for-byte unmodified logic against real OpenBao. Console
metadata lived in a scratch file with `sops-held-automation` selected.
This substitutes for the "rebuild slate" run: it exercises the exact
init/unseal/verify code paths on a greenfield instance. The first 3-node
rebuild will re-run the same script through `creds-bootstrap-agent.sh`
Phase 7b.
## Results
1. **Custody gate refusal** — with no model selected, the script refused
(`unseal custody model is 'unselected'`). Matches earlier negative tests.
2. **Bug found and fixed**`bao operator unseal -` does **not** read the
share from stdin (OpenBao treats `-` as the literal key: *"'key' must be a
valid hex or base64 string"*; without an argument it demands a TTY). The
live cluster never hit this because it was already unsealed. Fixed to
`bao write sys/unseal key=-`, which reads the value from stdin — shares
still never touch argv or logs.
3. **Greenfield init path** — uninitialized → `operator init` (3 shares,
threshold 2) → init.json written 0600 into the age-custody secrets dir →
share replay stopped at threshold (share 2 of 3) → post-unseal verified.
Evidence: `openbao_did_init_this_run=true`, `openbao_initialized=true`,
`openbao_post_unseal_verified=true`.
4. **Restart/reseal path** — server restarted (initialized + sealed) →
script skipped init, replayed SOPS-held shares to threshold → verified.
Evidence: `openbao_did_init_this_run=false`, both flags true.
Test server, storage, and init material were destroyed after the proof
(init.json shredded).