144 lines
6.2 KiB
Markdown
144 lines
6.2 KiB
Markdown
---
|
|
id: reef-storage-scaleway-bootstrap
|
|
demand_source: resource-control/workplans/RESOURCE-WP-0002-T03
|
|
consumer_repo: reef-storage
|
|
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: Scaleway bootstrap key for reef-storage
|
|
|
|
## 1. Demand
|
|
|
|
We need to create a private Scaleway Multi-AZ bucket in `nl-ams` for
|
|
postgres backup (`RESOURCE-WP-0002`). The founder has a new Scaleway
|
|
account and an API key in the usual Terraform snippet shape
|
|
(`access_key`, `secret_key`, `organization_id`, `project_id` in
|
|
`scaleway.auto.tfvars`). Those four values must live in OpenBao, not in
|
|
git or chat. ops-mason builds the empty lane. The founder pastes the
|
|
values once (desk or local tfvars ingest). reef-storage then creates the
|
|
bucket by reading OpenBao and never printing the keys.
|
|
|
|
## 2. Existing-structure survey
|
|
|
|
Checked 2026-08-14:
|
|
|
|
- **KV path does not exist.**
|
|
`platform/metadata/workloads/railiance/scaleway/bootstrap` is 404.
|
|
Same for the later backup path
|
|
`platform/workloads/railiance/backup/object-storage`.
|
|
- **CCR already reserved the path.**
|
|
`railiance-platform` `CCR-2026-0011` names
|
|
`platform/workloads/railiance/scaleway/bootstrap` and the four fields.
|
|
Reuse that path. Do not invent a second one.
|
|
- **CCR-2026-0004** is Nextcloud/age offsite backup
|
|
(`platform/workloads/railiance/backup/offsite-lane`). Different
|
|
provider, different fields. Do not merge.
|
|
- **Catalog.** No `scaleway` / `s3-backup` lane. `openbao-api-key` is the
|
|
generic template and must not become this concrete key.
|
|
- **Auth.** This is an operator-workstation bootstrap key for a one-shot
|
|
(or rare) `scw` create, not an in-cluster ESO consumer. No AppRole.
|
|
Founder paste-once / local tfvars ingest is the right desk. The later
|
|
scoped Barman key (T04) is a different path and may get a workload
|
|
CCR then.
|
|
- **Does an existing lane already satisfy this?** No live secret. The
|
|
reserved CCR path is the one to build.
|
|
|
|
Terraform snippet → OpenBao fields (same four facts, scw-native names):
|
|
|
|
| Terraform (`scaleway.auto.tfvars`) | OpenBao field |
|
|
| --- | --- |
|
|
| `access_key` | `ACCESS_KEY` |
|
|
| `secret_key` | `SECRET_KEY` |
|
|
| `organization_id` | `DEFAULT_ORGANIZATION_ID` |
|
|
| `project_id` | `DEFAULT_PROJECT_ID` |
|
|
|
|
## 3. Proposed changes
|
|
|
|
| # | Action | Object | Reuse-vs-new rationale |
|
|
|---|---|---|---|
|
|
| 1 | reuse | CCR-2026-0011 path `platform/workloads/railiance/scaleway/bootstrap` | Already reserved; do not fork |
|
|
| 2 | create | empty KV v2 path (metadata only, no secret data) | Structure so paste-once / ingest has a home |
|
|
| 3 | create | policy `operator-kv-scaleway-bootstrap` (read/write that path only) | Founder desk and the bucket-create script; no sibling paths |
|
|
| 4 | reuse | founder paste-once desk + optional local tfvars ingest | ops-mason never sees values; four fields, four desk pastes or one founder-run ingest |
|
|
| 5 | propose | catalog `scaleway-bootstrap` (draft) + playbook | Pointer only; `warden_executes: false` |
|
|
| 6 | defer | AppRole / ESO / scoped backup key | T04 / CCR for `backup/object-storage`; not this plan |
|
|
|
|
No new rail. Scaleway operates S3.
|
|
|
|
## 4. Review notes
|
|
|
|
- **Naming:** path follows `platform/workloads/railiance/…`. Policy
|
|
`operator-kv-scaleway-bootstrap` matches “operator workstation, not
|
|
workload ESO.”
|
|
- **TTL/scoping:** no AppRole token. The *downstream* Scaleway key is
|
|
long-lived until the founder deletes it after the scoped key exists.
|
|
- **Redundancy:** does not reuse Nextcloud offsite-lane. Does not put
|
|
org-admin keys in the Barman runtime path.
|
|
- **Compaction:** none. This is the first Scaleway lane.
|
|
- **Secret values:** mason does not read, write, or log them. Founder
|
|
uses `warden desk --act paste_once_provision` four times, or
|
|
`reef-storage/tools/ingest-scaleway-tfvars.sh` on a local 0600
|
|
`scaleway.auto.tfvars` they already have.
|
|
- **Founder remaining acts:** approve this plan; paste four fields (or
|
|
run ingest once); say “bootstrap is in OpenBao.”
|
|
|
|
## 5. Executive summary
|
|
|
|
**One-line ask:** approve an OpenBao home for the four Scaleway Terraform
|
|
variables so we can create the backup bucket without putting keys in git
|
|
or chat.
|
|
|
|
**Who gets access:** you (founder / operator token) to write the four
|
|
fields; the bucket-create script, using that same operator token, to
|
|
read them once. No new AppRole. No cluster workload. Nothing else gains
|
|
a path.
|
|
|
|
**To what:** only
|
|
`platform/workloads/railiance/scaleway/bootstrap`
|
|
(`ACCESS_KEY`, `SECRET_KEY`, `DEFAULT_ORGANIZATION_ID`,
|
|
`DEFAULT_PROJECT_ID`). Not the later Barman key path. Not other
|
|
`platform/workloads/railiance/backup/*` secrets.
|
|
|
|
**For how long:** the KV version stays until you rotate or delete it.
|
|
This bootstrap key should be revoked at Scaleway after the scoped bucket
|
|
key works (T04).
|
|
|
|
**Blast radius if the credential leaks:** create/list/delete Object
|
|
Storage (and whatever else that API key can do in the project). Revoke
|
|
the key in the Scaleway console, delete the KV version, rotate to a
|
|
scoped bucket-only key.
|
|
|
|
**Cost to reverse:** delete the KV path, draft catalog entry, and
|
|
policy. No other consumer is bound. The bucket, once created, stays
|
|
until you empty and delete it.
|
|
|
|
**Decision:** approve, reject, or send back to phase 1.
|
|
Approval authorizes structure (empty path, policy, catalog draft) and
|
|
your paste-once / tfvars ingest. It does not authorize ops-mason to
|
|
handle the Terraform secret values.
|
|
|
|
## 6. Build result
|
|
|
|
Executed 2026-08-14 after founder asked to bootstrap with example
|
|
data and replace values in the OpenBao UI.
|
|
|
|
Created (structure + placeholders only; values are the string `xxx`):
|
|
|
|
- policy `operator-kv-scaleway-bootstrap` (read/write that one path)
|
|
- KV v2 `platform/workloads/railiance/scaleway/bootstrap` version 1
|
|
fields `ACCESS_KEY`, `SECRET_KEY`, `DEFAULT_ORGANIZATION_ID`,
|
|
`DEFAULT_PROJECT_ID`
|
|
- custom_metadata `placeholder=true`, `ccr=CCR-2026-0011`,
|
|
`replace_in_ui=true`
|
|
|
|
Catalog draft `scaleway-bootstrap` already proposed.
|
|
|
|
**Founder next:** OpenBao UI → secret
|
|
`platform/workloads/railiance/scaleway/bootstrap` → create version 2
|
|
with the real Terraform values. Then say “bootstrap is in OpenBao.”
|
|
The bucket-create script refuses `xxx` placeholders.
|