Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a092fe-13b1-7f12-ac74-7d258af4d79c
6.8 KiB
NetKingdom credential custody contract
Historical resolver lanes: draft / blocked.
KeyCape factor service lane: active, established and verified 2026-09-13 (below).
Incident: KEYCAPE-EXPOSURE-20260823-01
Consumer procedure: NetKingdom NK-WP-0033, resolver reconciliation revision
eec7007 / checkout f2e578c
This document defines the Railiance-side contract without containing or deriving any credential value. It is not an authorization to fetch, export, apply, or rotate a secret.
Ownership
railiance-platformowns OpenBao custody, policy, delivery, rotation metadata, and revocation evidence.net-kingdomowns the privacyIDEA resolver contract and attended consumer reconciliation.ops-wardenroutes the lane only; it does not fetch or proxy either value.
Required OpenBao metadata (owner must fill, never guess)
| Lane | Canonical path | Field | Delivery | Status |
|---|---|---|---|---|
net-kingdom-lldap-bind-credential |
REQUIRED_FROM_OPENBAO_OWNER |
REQUIRED_FROM_OPENBAO_OWNER |
protected attended input to NetKingdom resolver helper | blocked |
net-kingdom-privacyidea-admin-token |
REQUIRED_FROM_OPENBAO_OWNER |
REQUIRED_FROM_OPENBAO_OWNER |
protected attended input to provider-admin helper | blocked |
The owner receipt must also identify the KV mount/version semantics, the least-privilege read/update policy, the authentication method, the expiry or rotation behavior, and the approved attended handoff. No value belongs in this file, State Hub, Git, chat, argv, or ordinary logs.
Consumer handoff
Once the OpenBao owner supplies the metadata above, Railiance-platform records
the receipt identifier and passes only protected input to the pinned
NetKingdom procedure. The resolver repair must use the minimal two-input
--reconcile flow; audit proofs (lookup, MFA, predecessor denial) remain a
separate read-only operation.
Current gate
The routing lane is registered but remains resolvable: false. No
warden access --fetch, proxy execution, resolver retry, or predecessor
restoration is authorized until the OpenBao owner publishes the missing
metadata and the attended handoff is approved.
KeyCape factor service lane — authorized setup, 2026-09-13
RPF-WP-0040 / CCR-2026-0023 establish a new dedicated service lane. The user, acting as platform operator, authorized establishing storage/delivery and performed attended OpenBao authentication. This is separate from the historical resolver repair lanes above; their incident receipts are not retroactively completed.
| Purpose | KV v2 CLI path | Fields | Consumer |
|---|---|---|---|
| Scoped provider JWT | platform/workloads/net-kingdom/keycape-factor-read | TOKEN, EXPIRES_AT, REQUEST | KeyCape via namespace-scoped ESO and adminTokenFile |
| Renewable service login | platform/workloads/net-kingdom/keycape-factor-issuer | USERNAME, PASSWORD, REQUEST | Owner bootstrap, then dedicated renewal worker; never KeyCape |
Provider identity: keycape-factor-reader (local privacyIDEA service admin). Effective permission: tokenlist for realm coulomb only. Preserve the existing no-admin-policy baseline for other administrators using an explicit fallback that excludes this service identity. Only the two reviewed named policies may be introduced; unexpected existing admin policies abort setup.
Generate the service password in owner-process memory and persist with KV CAS=0 before provider creation, allowing interrupted setup to resume. The attended worker passes values through stdin/captured pipes only, never argv or receipts. Only explicit KV absence permits creation. Existing request provenance and policy definitions must match; retries do not rotate an existing identity.
Reader policy: workload-kv-read-keycape-factor-read, role
keycape-factor-workload-kv-read, bound sso/keycape-factor-eso, audience openbao,
15-minute maximum OpenBao session, no default policy. Metadata apply/readback
passed via the attended owner envelope. Provider issuance, native ESO delivery,
KeyCape mounted-file activation, per-user lookup and rotation without restart
passed. The reader can inspect and revoke only its own OpenBao session in
addition to reading the exact JWT data/metadata paths. See the acceptance record
docs/evidence/2026-09-13-keycape-factor-custody.md.
Provider JWTs expire independently of OpenBao sessions. Require 5 minutes to 2 hours remaining lifetime at issuance; renew well before expiry. Disable the service's tokenlist policy (while retaining fallback exclusion) to withdraw its factor access; do not rotate privacyIDEA's global signing key as routine renewal. Verify expiry/permission refusal separately from OpenBao self-revocation.
Renewal: sso/keycape-factor-renewer runs every ten minutes under its own
service account, with a five-minute maximum OpenBao session. Its separate policy
reads the issuer password and reads/writes only the delivered JWT path. The
worker verifies provider identity, expiry, factor lookup and denied policy
administration before a CAS write and readback, then revokes its session.
ESO refreshes once per minute. KeyCape mounts only admin-token, mode 0440,
through fsGroup 65534; the issuer password never enters its namespace Secret.
Operations: make keycape-factor-tests runs offline failure/retry and config
preservation tests. make keycape-factor-live-acceptance creates bounded Jobs
that verify native delivery scope and a second renewal reaching the mounted
file. The runner emits booleans and resource identifiers only. CronJob failures
and ExternalSecret Ready=False are the native degraded-state signals. A failed
renewal leaves the last verified token in custody; expiry causes authentication
to fail closed. Restore provider/custody connectivity and launch a renewal Job
from the CronJob; verify SecretSynced and repeat live acceptance.
Attended setup is reproducible through openbao-attended-exec.py with
keycape_factor_metadata.py --apply --receipt <new-file>,
keycape_factor_bootstrap.py --receipt <new-file> and
keycape_factor_renewal_metadata.py --receipt <new-file> in that order, followed
by the custody manifest and guarded keycape_factor_activate.py --apply.
Use unique receipt paths. Existing mismatched policies/roles/provenance fail
closed; never replace an unknown owner credential. The separate
keycape_factor_eso_metadata.py records the migration from initial read-only
metadata to ESO's self-session permissions; fresh setup uses the final policy.
Outstanding acceptance is explicit in RPF-WP-0040-T04: genuine provider JWT expiry and provider-policy revocation/recovery drills. A newly issued JWT does not itself revoke its predecessor. Native mounted rotation has passed, but it is not evidence of predecessor revocation. Optional MFA rollout and lost-factor recovery remain KEY-WP-0035 / USER-WP-0030, not completed by this service lane.