--- id: backup-object-storage demand_source: resource-control/workplans/RESOURCE-WP-0002-T04 consumer_repo: rapp-postgres credential_type: openbao-kv-founder-provision status: built approved_by: "Bernd Worsch" approved_at: "2026-08-14" created: "2026-08-14" updated: "2026-08-14" --- # Construction plan: resource-control scoped backup key ## 1. Demand `RESOURCE-WP-0002` T04 needs a Scaleway API key for **backup object storage in general**, not a Barman-only identity. Founder uses IAM application `resource-control` and binds policy / API-key `Scoped backup access` on the project that owns the backup bucket. The key lives in OpenBao. External Secrets later projects it into consumer Secrets (first: `platform-pg-backup-s3` in `databases`). The bootstrap key cannot create IAM. ops-mason builds the empty lane. Values never appear in git or chat. ## 2. Existing-structure survey Checked 2026-08-14, retargeted the same day: - **KV path exists (version 1, 2026-08-14).** Founder put `ACCESS_KEY`, `SECRET_KEY`, `DEFAULT_ORGANIZATION_ID`, `DEFAULT_PROJECT_ID`. Not placeholders. No `APPLICATION_ID`. The earlier draft path `…/backup/platform-pg-backup-s3` was not built and must not be used. - **CCR-2026-0012** now reserves `platform/workloads/railiance/backup/object-storage`. Reuse it. - **CCR-2026-0011** is the bootstrap key (`platform/workloads/railiance/scaleway/bootstrap`). Different purpose. Do not reuse those values. Do not hang that key on application `resource-control`. - **CCR-2026-0004** is Nextcloud/age offsite. Different provider. - **Catalog.** No `backup-object-storage` lane. - **Auth.** First delivery is External Secrets into `databases`. Kubernetes auth role `external-secrets-backup-object-storage` is the CCR-declared steady state. railiance01 may need the interim AppRole/token pattern; that apply is after placeholders are replaced. - **Does an existing lane already satisfy this?** No live secret. ## 3. Proposed changes | # | Action | Object | Reuse-vs-new rationale | |---|---|---|---| | 1 | reuse | CCR-2026-0012 path | Already reserved after retarget | | 2 | create | policy `workload-kv-read-backup-object-storage` | File already written; apply after approval | | 3 | create | empty KV v2 path (placeholders `xxx`) | Paste-once / UI replace has a home | | 4 | defer | Kubernetes auth role / AppRole / ESO store | After real values exist | | 5 | defer | catalog `backup-object-storage` | Pointer only; `warden_executes: false` until verified | | 6 | defer | Scaleway bucket policy principal | Needs `APPLICATION_ID` of `resource-control` | No new rail. Scaleway operates S3. No second IAM application. ## 4. Review notes - **Naming:** path is `…/backup/object-storage`. IAM application is `resource-control`. Policy and key label are `Scoped backup access`. - **IAM fact:** policies attach to the application, not one key. Only backup-scoped keys belong on `resource-control`. - **TTL/scoping:** the Scaleway key is long-lived until rotated. The OpenBao reader is ESO, 15m Kubernetes auth TTL in the CCR. - **Redundancy:** does not reuse the bootstrap path or the Nextcloud offsite lane. Supersedes the Barman-named draft of the same CCR. - **Secret values:** mason does not read, write, or log them. Founder uses the OpenBao UI or `railiance-platform/docs/put-backup-object-storage.md`. - **Founder remaining acts:** approve this plan and CCR-2026-0012; create or reuse application `resource-control`; bind policy and key `Scoped backup access`; replace `xxx`; say “the backup key is in bao.” ## 5. Executive summary **One-line ask:** approve an OpenBao home for the resource-control backup key so first consumer `rapp-postgres` (and later backup consumers) can receive a projected Secret without putting keys in git or chat. **Who gets access:** you (founder) to write the three fields; later, External Secrets, first bound to namespace `databases`. **To what:** only `platform/workloads/railiance/backup/object-storage` (`ACCESS_KEY_ID`, `ACCESS_SECRET_KEY`, `APPLICATION_ID`). Not the bootstrap path. **For how long:** until you rotate or revoke the Scaleway key. **Blast radius if the credential leaks:** read/write/delete objects on the backup bucket. Revoke the key in the Scaleway console, delete the KV version, rotate. **Cost to reverse:** delete the KV path, policy, and unused drafts. WAL is not enabled yet, so there is no production archive to migrate. **Decision:** approved in chat 2026-08-14 (“Lets go”). ## 6. Build result Built 2026-08-14: - policy `workload-kv-read-backup-object-storage` (read on the KV data and metadata paths only) - AppRole `external-secrets-backup-object-storage` (15m/30m, 8 uses) - Kubernetes Secret `external-secrets/openbao-backup-object-storage-approle` delivered; local files shredded - ClusterSecretStore `openbao-backup-object-storage` Valid - ExternalSecret synced `databases/platform-pg-backup-s3` (two keys, values not read) Did not write Scaleway secret values. Did not enable WAL.