secrets-engine/docs/warden-sign-auth-capability.md
tegwick 6382139890 feat: add auth-capability lanes and pilot closeout
Add the warden-sign auth-capability lane, AppRole handoff, verification guards, docs, and tests.

Point the whynot-design pilot at the canonical decision and add the real publish closeout preflight/runbook.
2026-06-29 16:58:16 +02:00

142 lines
4.4 KiB
Markdown

# warden-sign auth-capability lane
`warden-sign` is a non-KV secrets-engine lane for SECRETS-WP-0004. It creates an
OpenBao ACL policy plus AppRole that lets ops-warden run `warden sign` over the
HTTP API for the FLEX-WP-0007 T4 production smoke.
No token value, AppRole `secret_id`, or SSH private material belongs in Git,
State Hub, chat, prompts, workplans, or normal logs. State Hub gets pointers
only; the operator receives `role_id` and `secret_id` out-of-band.
## Non-secret pointers
| Pointer | Value |
| --- | --- |
| OpenBao address | `https://bao.coulomb.social` |
| SSH mount | `ssh` |
| Policy | `warden-sign` |
| AppRole | `warden-sign` |
| Token TTL | `15m` |
| Secret ID TTL | `30m` |
| Secret ID uses | `1` |
| Allowed paths | `ssh/sign/agt-role`, `ssh/sign/adm-role`, `ssh/sign/atm-role` |
| Denied probes | `ssh/sign/unlisted-role`, `ssh/roles/agt-role`, `ssh/config/ca`, `sys/policies/acl/warden-sign`, `auth/token/create`, `identity/entity/id` |
## Plan and apply
Preview without mutation:
```bash
SECRETS_ENGINE_HUB_URL="" secrets-engine apply warden-sign --stage prod --dry-run
```
Live apply requires an approved decision/workplan and a short-lived bootstrap
token file outside any repo:
```bash
BAO_ADDR=https://bao.coulomb.social \
secrets-engine apply warden-sign --stage prod \
--bootstrap-token-file ~/.secrets-engine/bootstrap/prod-warden-sign.token
```
The bootstrap token file must be mode `0600`, revocable, and tracked in
[hardening-backlog.md](hardening-backlog.md) H0 until revoked and shredded.
## Handoff
Mint a fresh single-use AppRole `secret_id` and write both handoff values to
mode-0600 files outside any Git worktree:
```bash
install -m 700 -d ~/.secrets-engine/handoff
BAO_ADDR=https://bao.coulomb.social \
secrets-engine handoff warden-sign --stage prod \
--bootstrap-token-file ~/.secrets-engine/bootstrap/prod-warden-sign.token \
--role-id-file ~/.secrets-engine/handoff/warden-sign.role_id \
--secret-id-file ~/.secrets-engine/handoff/warden-sign.secret_id
```
The command prints only file paths and TTL metadata. It does not print the
`secret_id`.
On CoulombCore, the operator can authenticate without the `bao` CLI by posting
the file contents to AppRole login and capturing the returned token into process
state only:
```bash
ROLE_ID="$(cat ~/.secrets-engine/handoff/warden-sign.role_id)"
SECRET_ID="$(cat ~/.secrets-engine/handoff/warden-sign.secret_id)"
VAULT_TOKEN="$(
printf '{"role_id":"%s","secret_id":"%s"}' "${ROLE_ID}" "${SECRET_ID}" \
| curl -fsS \
--request POST \
--header 'Content-Type: application/json' \
--data @- \
https://bao.coulomb.social/v1/auth/approle/login \
| jq -r '.auth.client_token'
)"
unset ROLE_ID SECRET_ID
```
Run the smoke with the scoped token:
```bash
FLEX_AUTH_EXTERNAL=1 SMOKE_VAULT=1 VAULT_TOKEN="${VAULT_TOKEN}" \
~/ops-warden/scripts/policy_gate_production_smoke.sh
```
## Verification
After live apply and handoff, verify the scoped AppRole token shape without
printing the token:
```bash
BAO_ADDR=https://bao.coulomb.social \
secrets-engine verify warden-sign --positive --negative \
--bootstrap-token-file ~/.secrets-engine/bootstrap/prod-warden-sign.token
```
Positive verification checks `update` on the three allowlisted `ssh/sign` paths.
Negative verification checks the denial probes lack `update`, `sudo`, and `root`.
## State Hub pointer payload
Post only non-secret pointers, for example:
```json
{
"catalog_id": "warden-sign",
"kind": "auth-capability",
"addr": "https://bao.coulomb.social",
"mount": "ssh",
"policy": "warden-sign",
"approle": "warden-sign",
"token_ttl": "15m",
"secret_id_ttl": "30m",
"secret_id_num_uses": 1,
"allowed_paths": ["ssh/sign/agt-role", "ssh/sign/adm-role", "ssh/sign/atm-role"],
"status": "applied-and-handoff-ready"
}
```
Do not include `role_id`, `secret_id`, `VAULT_TOKEN`, token accessors, raw curl
responses, or smoke logs containing token material.
## Revocation and cleanup
After the smoke, revoke the scoped token by accessor if available, then remove
handoff files:
```bash
bao token revoke -accessor <accessor>
shred -u ~/.secrets-engine/handoff/warden-sign.role_id
shred -u ~/.secrets-engine/handoff/warden-sign.secret_id
```
To retire the lane metadata itself:
```bash
BAO_ADDR=https://bao.coulomb.social \
secrets-engine revoke warden-sign \
--bootstrap-token-file ~/.secrets-engine/bootstrap/prod-warden-sign.token
```