Add response-wrapped operator handoff
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

secrets-engine wrap writes a single-use OpenBao wrap token to a mode-0600
out-of-repo file and never prints it. KV reads and AppRole secret_ids are
wrapped with a 15m TTL cap. Unwrapped secret payloads fail closed.
Production wrap remains fail-closed.

Assistant: grok
Assistant-Session: 01a05f07-ae72-7781-9fcb-19efd61add00
This commit is contained in:
tegwick 2026-09-02 08:12:42 +02:00
parent 2278cefbb3
commit afd1c8e593
12 changed files with 387 additions and 8 deletions

View file

@ -43,8 +43,8 @@ delivery_auth:
The current native implementation supports AppRole. An entry that declares
`exec-env`, `exec-file`, `npm-config`, `read-check`, or `wrapped` must therefore
declare delivery auth. `exec-file` and `wrapped` remain reserved schema modes;
they are not implemented by `secrets-engine exec` yet.
declare delivery auth. `exec-file` remains a reserved exec schema mode.
`wrapped` operator handoff is `secrets-engine wrap`; it is not an exec adapter.
Engine-managed AppRoles may bound `token_ttl`, `token_max_ttl`,
`secret_id_ttl`, `secret_id_num_uses`, and `token_num_uses`. The admitted

View file

@ -55,6 +55,7 @@ secrets-engine apply <ref> --stage <stage> [--dry-run] [--bootstrap-token-file F
secrets-engine provision <catalog-id> --stage <stage> --field NAME (--from-file F | --generate)
secrets-engine verify <catalog-id> [--field NAME] [--positive] [--negative] [--negative-token-file F]
secrets-engine handoff <catalog-id> --stage <stage> --role-id-file F --secret-id-file F
secrets-engine wrap <catalog-id> --out F [--ttl 15m]
secrets-engine exec --catalog <catalog-id> [--field NAME] [--mode auto|npm-config|exec-env] -- CMD...
secrets-engine policy publication <catalog-id>
secrets-engine route <catalog-id> [--json]
@ -80,6 +81,10 @@ local decision is accepted for a prod-labeled lane only with
`SECRETS_ENGINE_UNSAFE_DEMO=1`, an empty Hub URL, and loopback OpenBao; the demo
scripts set those three conditions themselves.
`wrap` writes a single-use OpenBao response-wrap token to `--out` (mode 0600,
outside Git) and never prints it. KV lanes wrap a path read; auth-capability
lanes wrap a secret_id. TTL max 15m. Production live wrap stays fail-closed.
`handoff` is for `kind: auth-capability` lanes such as `warden-sign`. It mints a
fresh AppRole `secret_id` and writes `role_id` plus `secret_id` to caller-chosen
mode-0600 files outside Git worktrees. It never prints the `secret_id`; use the

View file

@ -46,8 +46,12 @@ contents in this repo.
## H2 — Response-wrapped handoff
- Add a `wrapped` delivery mode using OpenBao response wrapping for operator
handoff flows where exec-time injection does not fit.
- Implemented: `secrets-engine wrap <catalog-id> --out F [--ttl 15m]` writes a
single-use wrap token to a mode-0600 out-of-repo file. KV lanes wrap a read;
auth-capability lanes wrap a secret_id. The wrap token is never printed.
Evidence is wrap-handle fingerprint, ttl, and path only. TTL max 15m.
Unwrapped secret payloads fail closed. Production remains fail-closed.
- `exec --mode wrapped` is still not an exec adapter; this is operator handoff.
## H3 — Production dual-control