2026-08-23 14:15:42 +02:00
|
|
|
|
# KeyCape service-auth consumer boundary
|
|
|
|
|
|
|
|
|
|
|
|
secrets-engine now implements the consumer half of KeyCape's accepted
|
|
|
|
|
|
`secrets-engine-openbao` service-auth contract. It performs one explicit HTTPS
|
|
|
|
|
|
`client_credentials` exchange, keeps the resulting JWT in memory, and validates
|
|
|
|
|
|
the non-cryptographic contract before any future OpenBao login:
|
|
|
|
|
|
|
|
|
|
|
|
- subject `service:secrets-engine`, audience/client `secrets-engine-openbao`;
|
2026-09-27 16:43:31 +02:00
|
|
|
|
- service principal in `tenant:platform` (platform infrastructure, tenant zero), role `secrets-engine`;
|
2026-08-23 14:15:42 +02:00
|
|
|
|
- exact `openbao:login` scope and KeyCape AAL1 client-secret assurance;
|
|
|
|
|
|
- RS256 declaration, bounded issue/expiry timestamps, maximum 15-minute life,
|
|
|
|
|
|
and renewal when no more than three minutes remain;
|
|
|
|
|
|
- no ID token, refresh token, implicit retry provider, or fallback identity.
|
|
|
|
|
|
|
2026-10-06 14:13:41 +02:00
|
|
|
|
Since 2026-10-06 (founder direction; ops-mason plan
|
|
|
|
|
|
`keycape-secrets-engine-openbao-client-custody`) the `secrets-engine-openbao`
|
|
|
|
|
|
client secret has **no consumer file**. Each command that selects
|
|
|
|
|
|
`service-jwt` reads it in memory from OpenBao (`platform/workloads/keycape/secrets-engine-openbao`,
|
|
|
|
|
|
field `CLIENT_SECRET`) through one attended `bao login -method=oidc -no-store`
|
|
|
|
|
|
on role `keycape-secrets-engine-openbao-operator-workload-kv-read`, with the
|
|
|
|
|
|
token captured from a pipe, used only in a request header, and revoked with
|
|
|
|
|
|
`revoke-self` right after the read. Ambient `BAO_TOKEN`/`VAULT_TOKEN` and the
|
|
|
|
|
|
token helper are never used, and `SECRETS_ENGINE_KEYCAPE_CLIENT_SECRET_FILE`
|
|
|
|
|
|
is refused for this profile. The value is sent only with HTTP Basic
|
|
|
|
|
|
authentication and never placed in a request body, command argument, env,
|
|
|
|
|
|
file, evidence record, or object representation.
|
|
|
|
|
|
`secrets-engine service-auth probe-openbao [--json]` runs the whole chain and
|
|
|
|
|
|
prints value-free evidence. Coordinates, first-use command and lifecycle:
|
|
|
|
|
|
[keycape-openbao-consumer-custody.md](keycape-openbao-consumer-custody.md).
|
2026-10-06 13:39:29 +02:00
|
|
|
|
|
2026-09-02 01:24:08 +02:00
|
|
|
|
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).
|
2026-08-23 14:15:42 +02:00
|
|
|
|
|
|
|
|
|
|
Canonical provider contract:
|
|
|
|
|
|
`key-cape/docs/openbao-service-auth-contract.md` (reviewed 2026-08-23).
|
2026-09-09 07:06:05 +02:00
|
|
|
|
|
|
|
|
|
|
## Approval identity is separate
|
|
|
|
|
|
|
|
|
|
|
|
[Approval service authentication](approval-service-auth.md) uses its own
|
2026-10-06 14:13:41 +02:00
|
|
|
|
client-secret file (`SECRETS_ENGINE_APPROVAL_CLIENT_SECRET_FILE`, checked by
|
|
|
|
|
|
`service-auth check-secret-file`), resource audience, exact tenant:platform and per-request
|
2026-09-09 07:06:05 +02:00
|
|
|
|
read/consume scopes. Never put that credential into the OpenBao provider.
|
|
|
|
|
|
Both providers now validate KeyCape’s actual `level`/`methods` assurance shape;
|
|
|
|
|
|
the old `aal`/`method` fixture was incompatible with the issuer.
|