120 lines
4.9 KiB
Markdown
120 lines
4.9 KiB
Markdown
---
|
|
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.
|