7.3 KiB
Credential Request And Lease Broker
Workplan: RAILIANCE-WP-0005
Owner: railiance-platform
Status: source implementation started
This document records the Railiance credential broker ownership decision and the first implementation contract for short-lived OpenBao credential leases.
Decision
railiance-platform owns OpenBao credential request, generation, delivery,
audit, and revocation because this repo owns the platform secrets service and
the OpenBao policy surface. The broker may later split into a dedicated
service repo if the implementation grows, but the grant catalog and OpenBao
policy contracts remain platform-owned.
The broker is not a new secret store. It is a controlled request path for bounded credentials that already belong to OpenBao or adjacent platform authorities.
Boundaries
| Concern | Owner | Boundary |
|---|---|---|
| OpenBao mounts, policies, token roles, response wrapping, audit | railiance-platform |
Generates and revokes bounded credentials. |
| Human login, OIDC, MFA, IAM profile claims | key-cape |
Authenticates human and service identities. |
| Authorization decision | flex-auth |
Decides whether an actor may request a grant for a purpose, TTL, audience, and delivery mode. |
| SSH certificate signing | ops-warden |
Issues SSH certificates only. It does not vend OpenBao tokens, API keys, or provider secrets. |
| Request tracking | State Hub | Stores non-secret metadata only: request ids, actor, grant, purpose, TTL, decision id, lease accessor, status, timestamps, and audit pointers. |
| Agent/runtime consumption | llm-connect and callers |
Never place secrets in prompts. Consume credentials through local exec injection, response wrapping, service-account auth, or approved local files. |
Non-Secret Metadata Only
State Hub, workplans, docs, Git, chat, and prompts may contain:
- grant ids such as
ops-warden/warden-sign; - requested TTL and bounded max TTL;
- actor and subject ids;
- purpose strings;
- lease handles or accessors when they are not sufficient to use the secret;
- OpenBao audit request ids or timestamps;
- status values such as requested, issued, denied, revoked, or expired.
They must not contain:
- OpenBao root tokens, platform-admin tokens, or wrapped token values;
- unseal shares, recovery codes, private keys, OTP seeds, passwords, or API keys;
- raw bearer tokens in command lines, prompt text, State Hub bodies, or logs;
- screenshots or pasted command output containing secret values.
Grant Catalog
The catalog lives at:
credential-grants/catalog.yaml
Validate it with:
make credential-grants-validate
Every grant entry defines:
- a stable grant id;
- credential type and OpenBao policy set;
- grant class:
self-service,approval-required, orbreak-glass; - default and max TTL;
- allowed actor types and purpose examples;
- allowed and denied delivery modes;
- audit and revocation expectations.
The first pilot grant is ops-warden/warden-sign, which creates a short-lived
OpenBao token with only the warden-sign policy.
OpenBao Token Roles
OpenBao-token grants are configured from source with:
- an issuer policy under
openbao/policies/; - an
auth/token/roles/<role>token role with allowed policies, disallowed admin policies, non-renewable TTL bounds, no default policy, and orphan token issuance; - verification that reads the issuer policy, token role, and target workload policy before any smoke token is minted.
Dry-run the current grant configuration with:
make openbao-token-grants-dry-run
make openbao-verify-token-grants-dry-run
Live application uses an operator-approved OpenBao token from
OPENBAO_TOKEN_FILE or an interactive hidden prompt. The token is passed to the
OpenBao pod through stdin, never through argv:
OPENBAO_TOKEN_FILE=~/.local/openbao/platform-admin.token make openbao-configure-token-grants
OPENBAO_TOKEN_FILE=~/.local/openbao/platform-admin.token make openbao-verify-token-grants
The smoke verifier can mint a short-lived child token, confirm that it can list
ssh/roles, confirm that it cannot list unrelated secret engines, and revoke
the token by accessor:
OPENBAO_TOKEN_FILE=~/.local/openbao/platform-admin.token make openbao-verify-token-grants-smoke
Delivery Modes
exec-env is the preferred local path. The helper obtains a lease, injects
the credential only into a child process environment, redacts output, and then
revokes or lets the credential expire.
response-wrap is for attended handoff. The broker returns a single-use
OpenBao wrapping token instead of the raw credential. The recipient unwraps it
once; a second unwrap must fail.
local-token-file is for tools that cannot consume environment variables
cleanly. Files must be mode 0600, stored under .local/credential-leases/,
and removed when the lease is revoked or expires. That directory is ignored by
Git.
kubernetes-auth is for in-cluster workloads. Workloads should authenticate
with service-account-bound auth instead of receiving manually handed tokens.
The denied modes are absolute unless a later ADR updates the catalog:
chatstate-hub-bodygitcommand-line-token-argumentllm-prompt
Pilot Flow
The target ops-warden smoke path is:
credential exec --grant ops-warden/warden-sign --ttl 15m -- \
SMOKE_VAULT=1 /home/worsch/ops-warden/scripts/policy_gate_production_smoke.sh
The source helper MVP lives at scripts/credential.py until this flow graduates
into a packaged command. It supports the same core shape:
scripts/credential.py request --grant ops-warden/warden-sign --purpose flex-auth-openbao-smoke
scripts/credential.py exec --grant ops-warden/warden-sign --purpose flex-auth-openbao-smoke -- \
SMOKE_VAULT=1 /home/worsch/ops-warden/scripts/policy_gate_production_smoke.sh
scripts/credential.py status <lease-accessor>
scripts/credential.py revoke <lease-accessor>
request defaults to local-token-file: the raw child token is written only to
.local/credential-leases/ with mode 0600, and stdout contains the lease
handle/accessor plus metadata. --delivery response-wrap returns an OpenBao
wrapping token for attended handoff, not the raw child token.
exec mints a bounded child token, injects it as VAULT_TOKEN only into the
child process environment, redacts token-looking output, and revokes the token
by accessor when the child exits. The helper rejects caller-supplied
VAULT_TOKEN/BAO_TOKEN env assignments and unsafe OpenBao debug/trace log
settings.
Dry-run all helper paths with:
make credential-helper-dry-run
The child process receives VAULT_TOKEN in its environment. The token is not
printed, written to shell history, sent to State Hub, or placed in an LLM
prompt.
Implementation Sequence
- Validate and maintain the non-secret grant catalog.
- Add bounded OpenBao token role configuration for each OpenBao-token grant.
- Build a small helper that supports
request,exec,status, andrevoke. - Add optional flex-auth preflight and State Hub request lifecycle metadata.
- Update ops-warden routing so OpenBao token needs point here, while SSH certificate issuance remains in ops-warden.
Live token issuance requires an approved operator path to create or use the non-root issuer capability. Source-only validation and dry-run helper behavior must remain useful without a live token.