NK-WP-0055-T13: OpenBao break-glass ceremony with SSO down; RPF-WP-0064-T10 drill plan
Some checks failed
CCR intake gate / gate (push) Successful in 1m11s
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Has been cancelled

Adds the docs/openbao.md section: unseal, value-free held-token check,
generate-root with in-memory OTP decode, minimal action, revoke-self with
verification, post-event review record. Records that production's listener
has unauthenticated generate-root disabled (OpenBao 2.5.4 default) and the
owner decision this needs. Commands tested against a mock API.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4515@bnt-lap001
Assistant-Session: 0bf96127-6e04-41be-bfda-d11717c3f354
This commit is contained in:
codex 2026-10-27 23:31:58 +01:00
parent e3bc1ab32b
commit 8016f56f18
3 changed files with 319 additions and 0 deletions

View file

@ -583,3 +583,92 @@ Named residuals:
None of these blocks T15's OpenBao line. R1/R2 close in phase B. This is not owner acceptance of the full T15
packet or of the other three services.
## T10 — Break-glass drill: generate-root ceremony and held root-token check (NK-WP-0055-T13)
```task
id: RPF-WP-0064-T10
status: todo
priority: high
depends_on: [RPF-WP-0064-T08]
```
Source: NetKingdom NK-WP-0055-T13. The ceremony is written in `docs/openbao.md`, section "Break-glass:
OpenBao with SSO down". The founder runs this drill against an **isolated restored OpenBao only, never
production**. KeyCape and Authelia are not used, which simulates SSO being down.
**Drill mode (new adapter mode; the phase A path keeps its current behaviour).**
The drill runs as a separate `--mode break-glass-drill` with its own signed admission
(`drill: "break-glass"`, attempt id `RPF-WP-0064-T10-<id>`). It does the phase A restore and unseal, then:
1. **Held root-token check.** A hidden prompt takes the founder's held initial root token. The drill calls
`auth/token/lookup-self` with it and records only `valid`, `policies`, `ttl == 0`, `expire_time == null`
and `orphan`. It never revokes or otherwise uses the held token.
2. **Fresh ceremony.** A `sys/generate-root/attempt` is started with a server-generated OTP. The founder
enters two shares **again** at hidden prompts, so the unseal shares are not reused silently as in phase A.
The token is decoded in memory and `lookup-self` must show `["root"]`.
3. **Minimal action.** One read-only action: `sys/auth` metadata.
4. **Revoke.** `revoke-self` must return 204, and a follow-up `lookup-self` must return 403.
5. **Cancelled attempt.** Start an attempt and cancel it (`DELETE sys/generate-root/attempt`), so the
cancel step is drilled too.
**What the adapter must allow.**
- **The isolated listener.** The adapter keeps `disable_unauthed_generate_root_endpoints = false` on the
`--network none` loopback listener only, as it does today.
- **`ALLOWED_WRITES`.** `sys/generate-root/attempt` needs both PUT and DELETE, and a second
`sys/generate-root/update` sequence must be allowed.
- **`ALLOWED_READS`.** `GET sys/generate-root/attempt` (status) must be added. `auth/token/lookup-self`
must be allowed with the held token and with the generated token.
- **Prompts.** One extra hidden prompt each for the held token and for the two re-entered shares.
- **Deadline.** Everything stays inside the 45 minute deadline, with the same teardown.
- **Unchanged rules.** No network, no KV `/data/` reads, no change to production.
**Receipt fields (all free of secret values).** The drill writes a receipt v2 extension with:
- `drill: "break-glass"`
- `held_root_token`: `valid`, `policies`, `ttl_zero` and `expire_time_null`
- `generate_root`: `started`, `shares_entered: 2`, `complete`, `otp_decode_ok`, `policies: ["root"]`,
`minimal_action_path` and `minimal_action_ok`
- `revocation`: `revoke_status: 204` and `post_revoke_lookup: 403`
- `cancel_drill`: `started_then_cancelled`
- `claims_not_made`, which additionally lists:
- `production_root_token_validity`: the result is valid only as of the snapshot. Name the snapshot (the
2026-10-14 snapshot or a newer RPF-WP-0066 scheduled one) and its plaintext sha256.
- `production_generate_root_availability`
- `sso_down_access_path`
The verifier gets matching adversarial fixtures that reject token, accessor, OTP, nonce, encoded-token and
share shapes. Offline tests and a native rehearsal use synthetic material and a fake held token.
**Founder-run SSO-down walk (production, read-only).** Over `k3s-api-railiance01` with the admin kubeconfig,
the founder runs:
- `kubectl -n openbao get pod openbao-0`
- `bao status` (a seal check)
- a `kubectl port-forward` reachability check
There is no unseal and no generate-root on production. Record the result in the NK-WP-0055-T13 post-event
review record.
**Owner decision for rapp-openbao.** The production listener has unauthenticated generate-root disabled
(OpenBao 2.5.4 default). This decision is a precondition for the ceremony to work on production without a
valid token. The choices are:
- **(a)** an incident-time ConfigMap edit plus a restart
- **(b)** a standing loopback-only listener (`127.0.0.1:8210`) reachable only through `kubectl
port-forward` or `exec`
**Follow-up (founder decision).** If the held initial root token is valid, revoke it on production after
the ceremony drill succeeds, or record why it is kept.
**Done when:**
- the drill mode is implemented and reviewed, with tests
- the native rehearsal passes
- a founder-signed admission exists for the window
- the founder has run the drill and the independent verifier passes on the receipt
- NetKingdom has a value-free post-event review record and the rapp-openbao listener decision
No live run is part of the source preparation.