diff --git a/credential-change-requests/CCR-2026-0012-backup-object-storage.yaml b/credential-change-requests/CCR-2026-0012-backup-object-storage.yaml index 86d0a1f..749a908 100644 --- a/credential-change-requests/CCR-2026-0012-backup-object-storage.yaml +++ b/credential-change-requests/CCR-2026-0012-backup-object-storage.yaml @@ -3,7 +3,7 @@ kind: credential-change-request schema_version: 1 request_type: workload-kv-read title: Scaleway scoped backup object-storage key -status: proposed +status: approved created: '2026-08-14' updated: '2026-08-14' requester: @@ -18,7 +18,13 @@ review: required: true required_approvers: - platform-operator - comments: [] + comments: + - at: '2026-08-14T17:30:00+00:00' + reviewer: bernd.worsch + decision: approved + comment: >- + Approved in chat (Grok session): CCR-2026-0012 and “the backup + key is in bao.” Founder used ACCESS_KEY/SECRET_KEY field names. target: domain: financials tenant: railiance @@ -27,16 +33,19 @@ target: environment: production purpose: >- Object-store credentials for Railiance backup destinations. - Secret keys ACCESS_KEY_ID and ACCESS_SECRET_KEY. APPLICATION_ID - is the resource-control IAM application (for a later bucket - policy). Endpoint, bucket, prefix, and region stay on reef-storage. + Secret keys ACCESS_KEY and SECRET_KEY (projected to Kubernetes as + ACCESS_KEY_ID / ACCESS_SECRET_KEY). Org and project ids are + non-secret companions. APPLICATION_ID can be added later for a + bucket policy. Endpoint, bucket, prefix, and region stay on + reef-storage. openbao: mount: platform kv_path: platform/workloads/railiance/backup/object-storage fields: - - ACCESS_KEY_ID - - ACCESS_SECRET_KEY - - APPLICATION_ID + - ACCESS_KEY + - SECRET_KEY + - DEFAULT_ORGANIZATION_ID + - DEFAULT_PROJECT_ID policy_name: workload-kv-read-backup-object-storage policy_file: openbao/policies/workload-kv-read-backup-object-storage.hcl auth: @@ -56,15 +65,16 @@ access_frontdoor: type: ops-warden catalog_id: backup-object-storage selector: resource-control scoped backup access - command: warden access backup-object-storage --fetch ACCESS_KEY_ID + command: warden access backup-object-storage --fetch ACCESS_KEY resolvable: false - readiness: pending-review + readiness: approved-pending-apply delivery: surface: external-secrets target: >- ClusterSecretStore openbao-backup-object-storage (first namespace condition: databases) → ExternalSecret databases/platform-pg-backup-s3 - → Secret platform-pg-backup-s3 (consumer projection). Drafts live + → Secret platform-pg-backup-s3 (ACCESS_KEY_ID / ACCESS_SECRET_KEY + projected from ACCESS_KEY / SECRET_KEY). Drafts live under railiance-platform/argocd/platform-addons/openbao-secretstore/ and rapp-postgres/helm/platform-pg-backup-s3.externalsecret.yaml. Do not apply until this CCR is approved and the KV values are real. @@ -83,8 +93,9 @@ risk: verification: positive: - Field names present on the KV path; values not printed. - - An approved databases-namespace ExternalSecret can sync ACCESS_KEY_ID - and ACCESS_SECRET_KEY to Secret platform-pg-backup-s3. + - An approved databases-namespace ExternalSecret can project ACCESS_KEY + and SECRET_KEY to Secret platform-pg-backup-s3 as ACCESS_KEY_ID and + ACCESS_SECRET_KEY. - The scoped key can list/put/delete backup prefixes on the procured bucket. negative: @@ -96,7 +107,7 @@ verification: - Platform-operator approves this CCR. - Founder creates or reuses IAM application resource-control, binds policy Scoped backup access, mints the API key of that name, then - replaces OpenBao placeholders. + puts ACCESS_KEY and SECRET_KEY in OpenBao. Done 2026-08-14. - ESO store and ExternalSecret applied only after values are real. lifecycle: deactivate: Disable the catalog entry, delete consumer ExternalSecrets, diff --git a/docs/evidence/CCR-2026-0012-backup-key-verify-2026-08-14.md b/docs/evidence/CCR-2026-0012-backup-key-verify-2026-08-14.md new file mode 100644 index 0000000..23402d3 --- /dev/null +++ b/docs/evidence/CCR-2026-0012-backup-key-verify-2026-08-14.md @@ -0,0 +1,46 @@ +# CCR-2026-0012 — scoped backup key verification + +Date: 2026-08-14 +Status: **key live in OpenBao; cluster Secret not vended** +CCR: approved in chat 2026-08-14 +Path: `platform/workloads/railiance/backup/object-storage` (KV v2 version 1) + +No secret values in this file. + +## What is in OpenBao + +| Field | Present | +| --- | --- | +| `ACCESS_KEY` | yes (len 20, `SCW…`) | +| `SECRET_KEY` | yes | +| `DEFAULT_ORGANIZATION_ID` | yes | +| `DEFAULT_PROJECT_ID` | yes | +| `APPLICATION_ID` | no (bucket policy deferred) | + +Distinct from the CCR-2026-0011 bootstrap key (`keys_differ=yes`). + +## Positive + +- `scw object bucket list` / `get railiance-platform-pg-backup` in `nl-ams` succeeded. +- boto3 put/get/delete of a probe object under `platform-pg/` succeeded; probe deleted. +- Sibling prefix write also succeeded: no bucket policy yet, so prefix isolation is not enforced. + +## Negative + +- Bogus secret against the same access key: `SignatureDoesNotMatch`. +- `scw iam application list` / `user list` / `api-key get`: insufficient permissions. +- `scw billing budget list`: not allowed. +- `scw k8s cluster list`: insufficient permissions. + +`instance` / `vpc` / `rdb` / `registry` / `lb` list returned empty success. That is consistent with a project that has no those resources; it is not a proven compute-write deny. Do not create a paid resource to prove it. + +## Not done + +- OpenBao policy `workload-kv-read-backup-object-storage` — this token cannot `sys/policies/acl` write (403). +- ClusterSecretStore / ExternalSecret — railiance01 has no `platform-pg-backup-s3` yet; applying the draft store would fail without ESO auth. +- Bucket policy — needs `APPLICATION_ID`. +- WAL / `barmanObjectStore` on `platform-pg` — T05. + +## Next + +ops-mason (or a token that can write policies and ESO auth) applies the OpenBao policy and the `databases`-scoped store. Then ExternalSecret can project the Secret. After that, empty-WAL-archive preflight; still no continuous archiving until T05. diff --git a/docs/put-backup-object-storage.md b/docs/put-backup-object-storage.md index fa582a5..bf979f5 100644 --- a/docs/put-backup-object-storage.md +++ b/docs/put-backup-object-storage.md @@ -51,15 +51,18 @@ On this host, with a token that can write the `platform` mount: ```bash bao kv put platform/workloads/railiance/backup/object-storage \ - ACCESS_KEY_ID='SCWxxxxxxxx' \ - ACCESS_SECRET_KEY='xxxxxxxx' \ - APPLICATION_ID='xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' + ACCESS_KEY='SCWxxxxxxxx' \ + SECRET_KEY='xxxxxxxx' \ + DEFAULT_ORGANIZATION_ID='xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' \ + DEFAULT_PROJECT_ID='xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' ``` -Or replace the `xxx` placeholders in the OpenBao UI on that same path. +Same four field names as the bootstrap path. External Secrets projects +`ACCESS_KEY` / `SECRET_KEY` to Kubernetes `ACCESS_KEY_ID` / +`ACCESS_SECRET_KEY`. -`APPLICATION_ID` is the `resource-control` IAM application UUID (not a -secret). It is needed later for the bucket policy. +Optional later field: `APPLICATION_ID` (the `resource-control` IAM +application UUID, not a secret) so we can attach a bucket policy. ## 4. Confirm without printing values