ops-mason/plans/audit-core-openbao-runtime-custody.md
tegwick 8e41f85121 Build audit-core AppRole lane after founder approval
reuse_policy leaves external-secrets-audit-core intact so database
leases keep working. AppRole delivered to Kubernetes; interim static
ESO token retired.
2026-08-13 10:42:59 +02:00

7.7 KiB
Raw Blame History

id demand_source consumer_repo credential_type status approved_by approved_at created updated
audit-core-openbao-runtime-custody audit-core/workplans/AUDIT-WP-0005-T02 audit-core openbao-approle-kv built Bernd Worsch 2026-08-13 2026-08-13 2026-08-13

Construction plan: audit-core OpenBao runtime custody

1. Demand

audit-core on railiance01 needs durable PostgreSQL custody and a sender registry without the founder typing OpenBao tokens or running bao kv put. The founders remaining acts are: approve this plan, and unseal OpenBao if it is sealed. Mechanics belong to ops-mason (structure) and ops-warden (routing / founder desk), not to an ad-hoc terminal session.

2. Existing-structure survey

Checked 2026-08-13 against live railiance01 and the routing catalog:

  • Database leases already exist. rapp-postgres provisioned audit_core with audit_core_app / audit_core_migrate, and OpenBao already vends database/creds/audit-core-runtime and database/creds/audit-core-migration through railiance-platform grants rapp-postgres/audit-core-runtime and rapp-postgres/audit-core-migration. warden route show database-dynamic-credentials points at that playbook. Do not create a second database engine or a KV copy of a rotating lease.
  • ESO token already exists. external-secrets/openbao-audit-core-eso-token was minted 2026-08-13 with policy external-secrets-audit-core (read on the two database cred paths and on platform/data/workloads/audit-core/senders). ClusterSecretStore YAML is drafted; it is not yet applied.
  • KV senders path does not exist. A founder bao kv put against platform/workloads/audit-core/senders 403d because the workstation ~/.vault-token is not an operator identity. That is the failure this plan exists to retire.
  • Catalog. database-dynamic-credentials already covers the lease. There is no audit-core-senders entry. openbao-api-key is the generic template and must not become the concrete lane.
  • Auth topology. Same as user-engine / rapp-qonto: railiance01 ESO cannot use CoulombCore Kubernetes auth. AppRole is the transitional bridge; same-cluster Kubernetes auth remains the target.
  • Does an existing lane already satisfy this? The database half, yes — bind to the existing OpenBao database roles. The sender-registry half, no — there is no path, no AppRole, and no catalog entry. Reuse the email-connect / user-engine shape (namespace-limited store, 15m tokens, eight uses), do not widen those identities.

3. Proposed changes

# Action Object Reuse-vs-new rationale
1 reuse OpenBao roles audit-core-runtime / audit-core-migration Already vended; a KV copy of a lease recreates the delivery gap
2 reuse policy external-secrets-audit-core Already written; covers database creds + senders read
3 create AppRole external-secrets-audit-core Replace the long-lived ESO token with the same 15m/30m/8-use bridge as user-engine and rapp-qonto
4 deliver Secret external-secrets/openbao-audit-core-approle Mason write-only delivery of role_id/secret_id; never logged
5 create ClusterSecretStore openbao-audit-core Namespace-limited to audit-core; AppRole auth (token store is the interim until this builds)
6 reuse ClusterSecretStore openbao-audit-core-database + ExternalSecret Namespaced VaultDynamicSecret cannot read the ESO token in external-secrets; CSS can. One dataFrom extract per lease. Applied 2026-08-13, SecretSynced
7 create empty KV path platform/workloads/audit-core/senders Structure only. Values are not founder-pasted: first deploy mints sender tokens in-cluster into Secret audit-core-senders. A later wrap-migrate (user-engine pattern) can move them into this path without printing
8 propose ops-warden catalog audit-core-senders Pointer, warden_executes: false, starts draft
9 retire founder bao kv put / token-prompt as the T02 delivery path That is the error-prone interaction this demand forbids

No sibling workload path is readable. Mason does not print, log, or return sender tokens or database passwords.

4. Review notes

  • Naming: external-secrets-audit-core / openbao-audit-core matches email-connect and user-engine. Database grant names stay with rapp-postgres.
  • TTL/scoping: 15-minute tokens, 30-minute max, eight uses. Store condition is audit-core only.
  • Redundancy: does not create a second database role or a KV cache of the lease. Does not widen openbao-email-connect or openbao-user-engine-runtime.
  • Compaction: retires the attended bao kv put path as the way T02 completes. The already-minted static ESO token is interim and is revoked after the AppRole store is Ready.
  • Secret values: sender tokens are generated by us, not imported from a vendor. Founder paste-once is the wrong desk for them. Generate in-cluster; optional later wrap-migrate into the empty KV path.
  • Founder remaining acts: approve this plan; unseal OpenBao if sealed. No token paste, no bao command review.

5. Executive summary

One-line ask: approve letting ops-mason finish audit-cores OpenBao lane (AppRole + namespace-limited store + empty senders path + catalog pointer) so the receiver can run without you typing OpenBao tokens.

Who gets access: only External Secrets, through AppRole external-secrets-audit-core. Application pods keep seeing mounted files and AUDIT_CORE_SENDERS. Nothing else gains a new identity.

To what: read database/creds/audit-core-runtime, database/creds/audit-core-migration, and (later) platform/workloads/audit-core/senders. No sibling workload or tenant path.

For how long: each AppRole login is 15 minutes, 30 minutes maximum, eight uses. The AppRole secret ID lasts until rotated or replaced by same-cluster Kubernetes auth.

Blast radius if the credential leaks: append to the audit trail and read the sender registry; cannot rewrite or delete stored events (append-only trigger). Revoke the AppRole secret ID, rotate sender tokens overlap-first, and roll the receiver. Database leases expire on their own.

Cost to reverse: delete the AppRole, its bootstrap Secret, the ClusterSecretStore, and the empty KV path. Database roles and the audit_core database stay (owned by rapp-postgres). No other consumer is on this identity.

Decision: approve, reject, or send back to phase 1. Approval authorizes Mason build of structure and in-cluster sender minting. It does not authorize printing any secret value.

6. Build result

Built 2026-08-13 after founder approve, via ops_mason.executor.build_approle_kv_lane with reuse_policy=True so the existing external-secrets-audit-core policy (database creds + senders read) was not rewritten.

  • reused policy external-secrets-audit-core;
  • created AppRole external-secrets-audit-core (15m / 30m / 8 uses);
  • delivered role-id/secret-id into Secret external-secrets/openbao-audit-core-approle; local delivery dir shredded;
  • switched ClusterSecretStores openbao-audit-core and openbao-audit-core-database to AppRole auth; both Valid;
  • ExternalSecrets remain SecretSynced; receiver /readyz still custody_class=archive;
  • deleted interim Secret external-secrets/openbao-audit-core-eso-token;
  • catalog entry audit-core-senders already drafted in ops-warden (warden route find "audit-core senders" --all).

Empty KV path platform/workloads/audit-core/senders was not written: mason does not put values, and senders already live in-cluster. A later wrap-migrate can create that path without a founder paste.

No secret value was printed, committed, or logged. The 15-minute platform-admin child used for the build was revoked.