5.7 KiB
| id | demand_source | consumer_repo | credential_type | status | approved_by | approved_at | created | updated |
|---|---|---|---|---|---|---|---|---|
| rapp-qonto-openbao-kubernetes-lane | reef-railiance/workplans/REEF-RAILIANCE-WP-0003-T01 | rapp-qonto | openbao-kubernetes-kv | reviewed | null | null | 2026-07-27 | 2026-07-27 |
Construction plan: rapp-qonto OpenBao Kubernetes lane
1. Demand
rapp-qonto needs non-interactive, read-only delivery of the existing Binky
Qonto API credential from tenants/binky/qonto-api into its dedicated
Kubernetes namespace. External Secrets Operator should authenticate to OpenBao
with Kubernetes workload identity; neither the application nor a
ClusterSecretStore should hold a long-lived OpenBao token.
2. Existing-structure survey
Live OpenBao state was checked on 2026-07-27:
- auth mounts include
kubernetes/; its configured API endpoint is the cluster-localhttps://10.43.0.1:443; - existing Kubernetes roles are
external-secrets-activity-core,external-secrets-issue-core, andexternal-secrets-reuse-surface; - policy
workload-kv-read-binky-qonto-apialready exists and is scoped to the existing tenant credential; - the
tenants/KV v2 mount andtenants/binky/qonto-apivalue already exist; this plan does not create or read the value; - existing cluster stores use an interim static-token pattern, despite the Kubernetes roles existing;
CCR-2026-0009proposed a duplicateworkload-kv-read-qonto-assistantpolicy and the transitionalqonto-assistantnamespace/name.
The existing read policy satisfies the requested data scope exactly. Reuse it; do not create the duplicate policy from CCR-2026-0009. A new authentication role is still required because no existing role should gain Qonto access and no existing Qonto lane is workload-authenticated.
3. Proposed changes
| # | Action | Object | Reuse-vs-new rationale |
|---|---|---|---|
| 1 | reuse | policy workload-kv-read-binky-qonto-api |
Already grants the exact required read scope; a second equivalent policy adds drift without isolation |
| 2 | create | Kubernetes auth role external-secrets-rapp-qonto |
New identity binding only; bound to service account external-secrets in namespace external-secrets, policy #1, token TTL 15 minutes |
| 3 | create | ClusterSecretStore/openbao-rapp-qonto |
Uses Vault Kubernetes auth role #2 and the tenants KV v2 mount; namespace condition permits only rapp-qonto |
| 4 | modify | rapp-qonto ExternalSecret |
Map remote fields API_USER -> QONTO_LOGIN and API_KEY -> QONTO_SECRET_KEY; no values enter Git or logs |
| 5 | retire | proposed openbao-qonto-assistant static-token store |
Superseded before deployment; avoids a long-lived OpenBao token in a Kubernetes Secret |
| 6 | propose | ops-warden catalog entry rapp-qonto-workload-kv |
Pointer to the built Kubernetes-auth lane, warden_executes: false, initially draft |
No underlying Qonto secret is created, changed, printed, or rotated.
4. Review notes
- Naming: steady-state
rapp-qontonames replace the migration-onlyqonto-assistantnames. - TTL/scoping: 15-minute tokens match existing External Secrets roles. The role binds only the ESO service account; the ClusterSecretStore condition restricts consumers to one namespace.
- Redundancy: reuses the exact existing policy. This removes the duplicate policy proposed by CCR-2026-0009.
- Compaction: the draft static-token Qonto store is retired before it is deployed. Existing unrelated stores are untouched.
- Consumer usability: External Secrets performs authentication and delivery. The application consumes only a namespaced Kubernetes Secret.
- Posture: the lane accesses a high-risk bank credential, but it is read-only and the runtime exposes no financial write operation. Production still requires egress, audit, revocation, and failure-domain gates.
- Build executor extension: ops-mason currently builds AppRole lanes only. Phase 4 must add a narrowly tested Kubernetes-role operation with the same approval refusal and metadata-only audit guarantees before applying this plan.
5. Executive summary
One-line ask: allow External Secrets on railiance01 to deliver the existing
Binky Qonto read credential to rapp-qonto without storing a long-lived
OpenBao token in Kubernetes.
Who/what gets access: a new OpenBao Kubernetes role named
external-secrets-rapp-qonto, usable only by the existing
external-secrets service account in the external-secrets namespace. No
application pod, human role, or unrelated service account receives OpenBao
login rights.
To what: read-only access through the existing
workload-kv-read-binky-qonto-api policy to exactly
tenants/binky/qonto-api. Store use is limited to ExternalSecret resources in
the rapp-qonto namespace.
For how long: each Kubernetes-auth login receives a 15-minute OpenBao token. There is no delivered AppRole secret ID and no long-lived OpenBao token stored in Kubernetes. The Kubernetes service-account identity remains valid while the ESO deployment and role binding exist.
Blast radius if the identity is abused: an attacker able to act as the ESO service account and use this role could read the Binky Qonto API credential. The OpenBao policy cannot read any sibling tenant secret. The downstream Qonto key remains high-risk and must be rotated if exposed.
Cost to reverse: delete one Kubernetes auth role, one ClusterSecretStore,
and the rapp-qonto ExternalSecret/derived Secret. The existing human Qonto
lane and underlying credential remain intact; no unrelated consumer changes.
Decision needed: approve as proposed, reject, or send back to phase 1 with changes. Approval authorizes the structural access lane only, never disclosure or modification of the Qonto credential value.