Add named engine auth and accessor-file session revoke
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Select service-jwt, bootstrap, or env exclusively: JWT login uses a JSON
file, self-revokes, and never falls back to bootstrap or BAO_TOKEN. The
platform JWT mount/role is still unpublished, so auto keeps named
bootstrap/env providers.

session revoke --accessor-file revokes an already-issued token with
fingerprint-only evidence. Production remains fail-closed.

Assistant: grok
Assistant-Session: 01a05f07-ae72-7781-9fcb-19efd61add00
This commit is contained in:
tegwick 2026-09-02 01:24:08 +02:00
parent a94003de4f
commit 3abee434df
18 changed files with 698 additions and 135 deletions

View file

@ -34,11 +34,15 @@ secrets-engine --version
| Var | Default | Purpose |
| --- | --- | --- |
| `BAO_ADDR` | `http://127.0.0.1:8200` | OpenBao address |
| `BAO_TOKEN` | _(unset)_ | OpenBao token (or use `--bootstrap-token-file`) |
| `BAO_TOKEN` | _(unset)_ | Named `env` OpenBao token; never a fallback from `service-jwt` |
| `SECRETS_ENGINE_HUB_URL` | `http://127.0.0.1:8000` | State Hub for decisions + evidence (empty to disable) |
| `SECRETS_ENGINE_CATALOG` | `./catalog` | catalog directory |
| `SECRETS_ENGINE_EVIDENCE` | `./.evidence` | local non-secret evidence log |
| `SECRETS_ENGINE_UNSAFE_DEMO` | _(unset)_ | allow a prod-labeled lane only when Hub is disabled and OpenBao is loopback; throwaway demos only |
| `SECRETS_ENGINE_KEYCAPE_TOKEN_URL` | _(unset)_ | KeyCape token endpoint for `service-jwt` |
| `SECRETS_ENGINE_KEYCAPE_ISSUER` | _(unset)_ | KeyCape issuer; must match the JWT login contract |
| `SECRETS_ENGINE_KEYCAPE_CLIENT_SECRET_FILE` | _(unset)_ | mode-0600 out-of-repo client secret |
| `SECRETS_ENGINE_OPENBAO_JWT_LOGIN` | _(unset)_ | platform JWT mount/role contract YAML |
## Commands
@ -55,6 +59,7 @@ secrets-engine exec --catalog <catalog-id> [--field NAME] [--mode auto|npm-confi
secrets-engine policy publication <catalog-id>
secrets-engine route <catalog-id> [--json]
secrets-engine revoke <catalog-id> [--dry-run]
secrets-engine session revoke --accessor-file F [--stage stage]
secrets-engine lifecycle suspend <catalog-id> [--dry-run]
secrets-engine lifecycle deactivate <catalog-id> [--dry-run]
secrets-engine lifecycle destroy <catalog-id> [--dry-run] [--confirm-destroy <catalog-id>]

View file

@ -34,11 +34,15 @@ contents in this repo.
- Implemented consumer scaffold: exact KeyCape client-credentials exchange,
claim/lifetime preflight, strict client-secret file input, renewal boundary,
and no implicit fallback.
- Implemented named providers (`service-jwt`, `bootstrap`, `env`) with no
JWT→bootstrap/env fallback. JWT login uses a JSON file, never argv, and
self-revokes the issued OpenBao token.
- Remaining: railiance-platform stands up the exact-bound OpenBao JWT auth
mount/role and publishes its non-secret connection contract.
- secrets-engine logs in via that method instead of reading a token file.
- Remove `--bootstrap-token-file` from the steady-state path (keep only for true
break-glass, heavily audited).
mount/role and publishes its non-secret connection contract
(`SECRETS_ENGINE_OPENBAO_JWT_LOGIN`). Until then `--auth service-jwt`
fail-closes and `--auth auto` keeps named bootstrap/env providers.
- `--bootstrap-token-file` is a named break-glass provider with distinct
evidence, not an implicit fallback.
## H2 — Response-wrapped handoff
@ -67,9 +71,10 @@ contents in this repo.
## H4a — Known-accessor operator command
- Delivery sessions already self-revoke in `finally` (`SECRETS-WP-0007-T05`).
- Residual from T03: no general CLI to revoke an already-issued token or
lease by a non-secret accessor the operator already holds.
- Do not print accessors. Prefer fingerprint-only evidence.
- Implemented: `secrets-engine session revoke --accessor-file F` reads a
mode-0600 out-of-repo accessor, calls `token revoke -accessor`, and records
only a fingerprint. Production remains fail-closed. Lease-id revoke is still
outstanding.
## H5 — Audit report command

23
docs/openbao-jwt-login.md Normal file
View file

@ -0,0 +1,23 @@
# OpenBao JWT login contract (engine consumer)
Steady-state engine authentication is the reviewed KeyCape
`secrets-engine-openbao` identity plus a **platform-owned** OpenBao JWT auth
mount and exact-bound role. This repository does not invent that mount.
Point `SECRETS_ENGINE_OPENBAO_JWT_LOGIN` at a mode-normal YAML file outside
the need to hold a standing OpenBao token:
```yaml
mount: jwt
role: secrets-engine
bound_issuer: https://<keycape-issuer>
```
`bound_issuer` must equal `SECRETS_ENGINE_KEYCAPE_ISSUER`. The JWT is sent
through a temporary JSON file, never argv. The resulting OpenBao token is
revoked at the end of the command (`token revoke -self`). Evidence records
the provider name and an accessor fingerprint only.
Until railiance-platform publishes that file, `--auth auto` keeps the named
bootstrap-file and `BAO_TOKEN` providers. `--auth service-jwt` fail-closes.
A service-jwt selection never reads `--bootstrap-token-file` or `BAO_TOKEN`.

View file

@ -17,12 +17,17 @@ outside every Git worktree. It is sent with HTTP Basic authentication and never
placed in a request body, command argument, evidence record, or object
representation.
This is a scaffold, not a live OpenBao authentication path. JWT payload parsing
does not prove a signature. railiance-platform still owns the exact OpenBao JWT
auth mount/role, issuer keys, claim bindings, token policy, TTL/use limits, and
cryptographic verification. Until that contract is materialized, the provider
is not selected by the CLI and bootstrap/AppRole behavior is not used as an
implicit fallback.
JWT payload parsing does not prove a signature. OpenBao must verify RS256
against the configured issuer before issuing a token. railiance-platform owns
the exact OpenBao JWT auth mount/role, issuer keys, claim bindings, token
policy, TTL/use limits, and cryptographic verification.
When `SECRETS_ENGINE_OPENBAO_JWT_LOGIN` names that contract, the CLI selects
`service-jwt` and logs in for one command, then self-revokes the OpenBao
token. Failure of that path never falls back to `--bootstrap-token-file`,
`BAO_TOKEN`, or AppRole. Until the contract is published, `--auth auto` keeps
those named providers and `--auth service-jwt` fail-closes. See
[openbao-jwt-login.md](openbao-jwt-login.md).
Canonical provider contract:
`key-cape/docs/openbao-service-auth-contract.md` (reviewed 2026-08-23).