6.3 KiB
| id | demand_source | consumer_repo | credential_type | status | approved_by | approved_at | created | updated |
|---|---|---|---|---|---|---|---|---|
| user-engine-openbao-runtime-custody | net-kingdom/workplans/NK-WP-0023-T05 | net-kingdom | openbao-approle-kv | built | Bernd Worsch | 2026-07-30 | 2026-07-30 | 2026-07-30 |
Construction plan: user-engine OpenBao runtime custody
1. Demand
The live portal edge marker and identity-provisioner service token are
bootstrap Kubernetes Secrets without an authoritative rotation source.
user-engine and identity-provisioner need the same runtime behavior with
OpenBao as authority and External Secrets Operator as delivery mechanism.
2. Existing-structure survey
Secret/user-engine-runtimein namespaceuser-enginecontains onlyproxy-secret.Secret/identity-provisioner-clientin namespaceuser-engineandSecret/identity-provisioner-tokenin namespacessocarry the two copies of the provisioner service token.- The applications already consume only Secret references; no code or Deployment interface change is required.
- The established
rapp-qontobridge proves that railiance01 External Secrets must currently use AppRole against the OpenBao instance on CoulombCore; railiance01 service-account tokens cannot use that instance's Kubernetes auth mount. - Existing activity-core stores and policies are unrelated and must not be widened or reused across this identity boundary.
3. Proposed changes
| # | Action | Object | Rationale |
|---|---|---|---|
| 1 | create | KV path platform/workloads/user-engine/runtime |
One authoritative workload path with fields PROXY_SECRET and PROVISIONER_TOKEN |
| 2 | create | policy workload-kv-read-user-engine-runtime |
Read and metadata access only to the exact KV v2 path |
| 3 | create | AppRoles external-secrets-user-engine and external-secrets-sso-user-engine |
Separate revocable bootstrap identities for the two consuming namespaces |
| 4 | deliver | AppRole bootstrap Secrets in external-secrets |
Write-only Mason delivery; 15-minute tokens, 30-minute maximum, eight uses |
| 5 | create | namespace-restricted ClusterSecretStores for user-engine and sso |
Prevent either identity from becoming a general cross-namespace store |
| 6 | create | three ExternalSecrets targeting the existing Secret names | Preserve application interfaces while changing authority |
| 7 | migrate | existing values into the KV path through a wrapped platform-admin process | Read source and write destination in one process; never return either value |
| 8 | verify | metadata, rollout, positive/negative authentication, and rotation rehearsal | Record field names, readiness, denial, and rollout only |
| 9 | retire | manual Secret-copy/bootstrap procedure | ExternalSecret becomes the sole writer and rotation path |
The migration does not mint a new application capability. It moves two existing values into governed custody. Same-cluster Kubernetes auth remains the target after OpenBao moves to reef-railiance.
4. Review and optimization
- Separate AppRoles avoid widening one namespace identity across
ssoanduser-engine. - Both policies resolve to one exact path, avoiding duplicate values and divergent rotation.
- Existing Secret names and keys remain stable, limiting rollout risk.
- A wrapped migration process is required because printing, downloading, or staging either value would create a new disclosure path.
- Reversal deletes the ExternalSecrets/stores/AppRoles and restores the protected pre-migration Secret snapshots during the bounded rollback window.
- Rotation changes the OpenBao fields, waits for all three ExternalSecrets, and rolls the provisioner and portal together; failed synchronization stops before either Deployment changes.
5. Executive summary
One-line ask: approve moving the existing user-engine edge marker and provisioner token into one exact OpenBao workload path, delivered by two namespace-specific, revocable External Secrets AppRoles.
Who gets access: only External Secrets through
external-secrets-user-engine and external-secrets-sso-user-engine.
Application pods continue to receive only their existing namespaced Secrets.
To what: read-only access to exactly
platform/workloads/user-engine/runtime; no sibling workload or tenant path.
For how long: each AppRole login receives a 15-minute token with a 30-minute maximum and eight uses. AppRole secret IDs persist for ESO continuity until rotated or same-cluster Kubernetes auth replaces the bridge.
Blast radius: compromise permits impersonating the internal provisioner client and/or the portal trusted marker, but grants no direct OpenBao sibling read, directory administrator password, user password, MFA seed, or platform role. Revoke both AppRole secret IDs, rotate both runtime values, and roll the two workloads.
Cost to reverse: delete three ExternalSecrets, two stores, two AppRoles, their bootstrap Secrets, and one exact policy/path; restore the protected pre-migration Kubernetes Secret snapshots. No database or identity record changes.
Decision needed: approve as proposed, reject, or return with changes. Approval authorizes custody migration and bounded rotation rehearsal, never printing or otherwise disclosing either value.
6. Build result
Built on 2026-07-30 exactly as approved:
- created KV path
platform/workloads/user-engine/runtime; - created policy
workload-kv-read-user-engine-runtime; - created AppRoles
external-secrets-user-engineandexternal-secrets-sso-user-engine; - delivered each bootstrap identity directly into its Kubernetes Secret;
- created two namespace-restricted ClusterSecretStores and three ExternalSecrets while preserving existing application Secret names;
- migrated the two existing values in a wrapped process without printing or staging them;
- rehearsed coordinated rotation, waited for all three derived Secrets, and returned both dependent Deployments to Ready;
- verified exact-path
read, sibling-pathdeny, matching derived provisioner tokens, and a live post-rotation identity reconciliation.
No new secret value requires founder paste-once provisioning. No credential
value was written to Git, logs, State Hub, or chat. The two executor audit
records are in audit/build-log.jsonl; no ops-warden catalog entry is needed
because this is an OpenBao/External Secrets runtime lane rather than an SSH
certificate route.