From a274938232079ef7858a2dac7a1c277b63569860 Mon Sep 17 00:00:00 2001 From: codex Date: Mon, 2 Nov 2026 02:28:28 +0100 Subject: [PATCH] Prepare the draft MAS evidence publisher grant. CCR-2026-0062 names the prefix reader for platform-pg/application-archives/mas/. It is not approved, and this change creates no IAM application, OpenBao value, ServiceAccount, or node file. Assistant: grok Assistant-Session: 01a198fa-fd27-7e41-a0a2-57355c3e4efd --- .../CCR-2026-0062-mas-backup-primary.yaml | 141 ++++++++++++++++++ .../mas-evidence-backup-grant-2026-11-02.md | 50 +++++++ openbao/backup-primary-serviceaccounts.yaml | 12 ++ .../workload-kv-read-mas-backup-primary.hcl | 11 ++ scripts/application_backup_credentials.py | 1 + .../RPF-WP-0070-mas-evidence-recovery.md | 15 +- 6 files changed, 227 insertions(+), 3 deletions(-) create mode 100644 credential-change-requests/CCR-2026-0062-mas-backup-primary.yaml create mode 100644 docs/credential-lane-designs/mas-evidence-backup-grant-2026-11-02.md create mode 100644 openbao/policies/workload-kv-read-mas-backup-primary.hcl diff --git a/credential-change-requests/CCR-2026-0062-mas-backup-primary.yaml b/credential-change-requests/CCR-2026-0062-mas-backup-primary.yaml new file mode 100644 index 0000000..bf6f923 --- /dev/null +++ b/credential-change-requests/CCR-2026-0062-mas-backup-primary.yaml @@ -0,0 +1,141 @@ +{ + "id": "CCR-2026-0062", + "kind": "credential-change-request", + "schema_version": 1, + "request_type": "workload-kv-read", + "title": "MAS evidence archive node-delivery reader", + "status": "draft", + "created": "2026-11-02", + "updated": "2026-11-02", + "requester": { + "agent": "grok", + "reason": "Founder asked to prepare the MAS prefix publisher under RPF-WP-0070. Preparation is not a live grant." + }, + "review": { + "required": true, + "required_approvers": [ + "platform-owner", + "mas-owner" + ], + "comments": [] + }, + "target": { + "domain": "communication", + "tenant": "platform", + "workload": "mas", + "environment": "production", + "purpose": "Read one MAS evidence publisher key pair into the admitted node delivery process. No other workload credential, sibling prefix, or age identity." + }, + "openbao": { + "mount": "platform", + "kv_path": "platform/workloads/mas/backup-primary", + "fields": [ + "AWS_ACCESS_KEY_ID", + "AWS_SECRET_ACCESS_KEY" + ], + "policy_name": "workload-kv-read-mas-backup-primary", + "policy_file": "openbao/policies/workload-kv-read-mas-backup-primary.hcl", + "metadata_read": false, + "token_self_lifecycle": true, + "auth": { + "method": "kubernetes", + "mount": "kubernetes", + "role": "mas-backup-primary-workload-kv-read", + "audience": "openbao", + "ttl": "5m", + "token_max_ttl": "5m", + "token_explicit_max_ttl": "5m", + "token_no_default_policy": true, + "token_num_uses": 4, + "token_type": "service", + "policies": [ + "workload-kv-read-mas-backup-primary" + ], + "bound_claims": { + "service_account_names": [ + "backup-primary-delivery" + ], + "service_account_namespaces": [ + "mas" + ] + }, + "bound_claims_confirmed": false + } + }, + "access_frontdoor": { + "type": "platform-owner", + "catalog_id": "mas-backup-primary-delivery", + "readiness": "pending-review", + "resolvable": false + }, + "delivery": { + "surface": "node-private-file", + "host": "railiance01", + "cluster_uid": "a553c742-0115-43d4-99a4-a5ca56fe0786", + "target": "/etc/mas-backup/primary.env", + "owner": "root:root", + "mode": "0600", + "directory_mode": "0700", + "procedure": "scripts/application_backup_credentials.py", + "admission": { + "node_executor_approved": false, + "provider_scope_verified": false, + "reader_boundary_verified": false, + "source_ref": "" + } + }, + "provider": { + "endpoint": "https://s3.nl-ams.scw.cloud", + "bucket": "railiance-platform-pg-backup", + "prefix": "platform-pg/application-archives/mas/", + "identity": "not created; proposed IAM application mas-evidence-backup-primary is not provisioned and is not a key on an existing application", + "retained_delete": false + }, + "risk": { + "classification": "high", + "notes": [ + "Once admitted, node root may request the dedicated ServiceAccount JWT. This account has no RoleBinding and no mounted token. Namespace writers and node administrators are inside this credential boundary.", + "The TokenRequest JWT and the five-minute, four-use OpenBao token stay in process memory. Only the provider pair would be delivered at rest, and only after admission.", + "No worker receives IAM or bucket administration, sibling archive access, TEM or SMTP credentials, or the age decryption identity.", + "This draft does not seed values or activate capture, timers, retention, deletion, or a production restore. The 2026-11-02 local capture stays on the node and is not an offsite publication." + ] + }, + "verification": { + "positive": [ + "After admission, the exact namespace, ServiceAccount, and audience authenticate with this one policy, no default or identity policy, a five-minute maximum TTL, and a four-use bound.", + "One own-path KV read followed by self-revocation yields only these two fields at one pinned KV version.", + "Node delivery produces a root-owned 0600 file in a 0700 directory, with contained readback equality and a metadata-only receipt.", + "The provider caller can conditionally publish a multipart object and read it back by version inside platform-pg/application-archives/mas/ only." + ], + "negative": [ + "Wrong namespace, ServiceAccount, and audience cannot log in.", + "Sibling application data GET, parent LIST, metadata GET, any KV write, and platform admin endpoints are denied.", + "The provider denies sibling and native prefixes, retained object or version deletion, and IAM or bucket administration.", + "Draft, unconfirmed, or source-changed contracts, the wrong cluster, symlinks, hard links, insecure modes, a changed KV version, unconfirmed token revocation, and a different existing file refuse delivery." + ], + "evidence": [], + "activation_conditions": [ + "Platform-owner and mas-owner reviews, confirmed native reader bindings, and an applied policy and role with live positive and negative evidence.", + "A separate IAM application limited to platform-pg/application-archives/mas/, with a bucket policy that denies sibling prefixes. Project-wide object-storage IAM is not a prefix grant. An independent mirror project remains a founder choice and is not created by this draft.", + "Atomic pair provision under an explicit platform custody act, initial KV CAS=0. The single-field paste desk is unsuitable. This reader does not create or rotate values.", + "Delivery admission booleans and a source_ref recorded only after those proofs. Pin the reviewed CCR SHA256 before any node file is created.", + "Age-identity escrow, independent receipt custody, retention, the first offsite capture, and any timer remain separate gates. This draft does not move the workstation age identity or publish the 2026-11-02 capture." + ] + }, + "lifecycle": { + "deactivate": "After admission, the owner detaches this Kubernetes role first, revokes tokens, and removes only the admitted local delivery through an explicit withdrawal record. Do not delete retained archives.", + "rotate": "A separate owner-approved CAS rotation and atomic host replacement are required. The helper refuses different existing bytes. Retain the old provider identity until the new publication is accepted, then revoke the predecessor at the provider.", + "compromised": "Fence the worker and disable its provider identity first. The owner revokes reader tokens, withdraws the reader, rotates the pair, and reviews retained-object access. No automated archive deletion." + }, + "state_hub": { + "workplan_id": "RPF-WP-0070", + "task_id": "RPF-WP-0070-T01" + }, + "related": { + "workplan": "RPF-WP-0070", + "design": "docs/credential-lane-designs/mas-evidence-backup-grant-2026-11-02.md", + "local_capture": "docs/evidence/mas-evidence-local-capture-2026-11-02.json", + "sibling_reader": "CCR-2026-0037", + "excluded": "Age-identity escrow and the email-connect publisher pair stay outside this request." + } +} diff --git a/docs/credential-lane-designs/mas-evidence-backup-grant-2026-11-02.md b/docs/credential-lane-designs/mas-evidence-backup-grant-2026-11-02.md new file mode 100644 index 0000000..59cce8e --- /dev/null +++ b/docs/credential-lane-designs/mas-evidence-backup-grant-2026-11-02.md @@ -0,0 +1,50 @@ +# MAS evidence publisher grant — 2026-11-02 + +Prepared for RPF-WP-0070. CCR-2026-0062 is a **draft**. Its Kubernetes binding +is unconfirmed and its delivery admission is false. This packet creates no +provider identity, OpenBao policy, role, or value, ServiceAccount, node file, +offsite upload, or timer. + +The accepted shape is the email-connect ledger reader, CCR-2026-0037. The MAS +prefix is `platform-pg/application-archives/mas/` in bucket +`railiance-platform-pg-backup` (`https://s3.nl-ams.scw.cloud`). The archive +profile already names that prefix. The 2026-11-02 quiesced capture remains +local. It is not an offsite object. + +| Item | Prepared value | Live state | +| --- | --- | --- | +| Reader request | CCR-2026-0062 | draft, not approved | +| KV path | platform/workloads/mas/backup-primary | no value written | +| Fields | AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY | absent | +| Policy | workload-kv-read-mas-backup-primary | source only | +| Role | mas-backup-primary-workload-kv-read | not created | +| ServiceAccount | backup-primary-delivery in namespace mas | source list only; automount false; no RoleBinding | +| Node file | /etc/mas-backup/primary.env, root:root 0600, directory 0700 | not created | +| Provider identity | proposed application mas-evidence-backup-primary | not created | + +Do not reuse the email-connect publisher or its node file. Object-storage IAM +is not prefix-scoped inside a project, so a later admission needs its own IAM +application and a bucket policy that denies sibling prefixes. An independent +mirror project, as used for the email-connect ledger, stays a founder choice +and is not created here. + +## Still required before any offsite copy + +1. Founder reviews as platform-owner and mas-owner, with the namespace, + ServiceAccount, and audience confirmed. +2. Create the separate IAM application and prove the prefix boundary, including + denial of sibling prefixes, retained delete, and IAM or bucket administration. +3. Apply the policy and role through the delegated metadata applier. Ops-mason + remains survey-only. +4. Provision the pair atomically with KV CAS=0 under an explicit platform + custody act. The single-field paste desk is unsuitable. Pair-custody and + slot-preparation lists stay closed to coulomb-social and email-connect until + that act. +5. Record positive reader proof and negative denials, then set delivery + admission. Export the admitted CCR and pin its SHA256 before creating the + node file. + +Age-identity escrow is a separate custody act. This grant does not move the +workstation private key, and the node must not hold it. TEM and SMTP +credentials stay out of the backup worker. The MAS facility is not scaled, +its image is not rolled, and namespace `mas` is not deleted. diff --git a/openbao/backup-primary-serviceaccounts.yaml b/openbao/backup-primary-serviceaccounts.yaml index 3e45c2c..91c3bb9 100644 --- a/openbao/backup-primary-serviceaccounts.yaml +++ b/openbao/backup-primary-serviceaccounts.yaml @@ -25,6 +25,18 @@ } }, "automountServiceAccountToken": false + }, + { + "apiVersion": "v1", + "kind": "ServiceAccount", + "metadata": { + "name": "backup-primary-delivery", + "namespace": "mas", + "labels": { + "app.kubernetes.io/managed-by": "railiance-platform" + } + }, + "automountServiceAccountToken": false } ] } diff --git a/openbao/policies/workload-kv-read-mas-backup-primary.hcl b/openbao/policies/workload-kv-read-mas-backup-primary.hcl new file mode 100644 index 0000000..70d400f --- /dev/null +++ b/openbao/policies/workload-kv-read-mas-backup-primary.hcl @@ -0,0 +1,11 @@ +path "platform/data/workloads/mas/backup-primary" { + capabilities = ["read"] +} + +path "auth/token/lookup-self" { + capabilities = ["read"] +} + +path "auth/token/revoke-self" { + capabilities = ["update"] +} diff --git a/scripts/application_backup_credentials.py b/scripts/application_backup_credentials.py index fc94b37..f38f2b5 100644 --- a/scripts/application_backup_credentials.py +++ b/scripts/application_backup_credentials.py @@ -31,6 +31,7 @@ SA = "backup-primary-delivery" PROFILES = { "coulomb-social": {"ccr": "CCR-2026-0036", "directory": "/etc/coulomb-social-backup"}, "email-connect": {"ccr": "CCR-2026-0037", "directory": "/etc/email-connect-backup"}, + "mas": {"ccr": "CCR-2026-0062", "directory": "/etc/mas-backup"}, } diff --git a/workplans/RPF-WP-0070-mas-evidence-recovery.md b/workplans/RPF-WP-0070-mas-evidence-recovery.md index bb29bb3..920c25c 100644 --- a/workplans/RPF-WP-0070-mas-evidence-recovery.md +++ b/workplans/RPF-WP-0070-mas-evidence-recovery.md @@ -40,7 +40,7 @@ status: progress priority: medium needs_human: true depends_on: [RPF-WP-0053-T05] -intervention_note: "Local quiesced capture and restore rehearsal are done. Prefix-scoped publisher custody and age-identity escrow are still required before offsite publication." +intervention_note: "Draft CCR-2026-0062 prepares the MAS prefix publisher. It is not approved or applied. Age-identity escrow is still required before offsite publication." state_hub_task_id: "4f6484fb-8303-5dd5-94cb-b2622e1322c8" ``` @@ -59,5 +59,14 @@ facility or send mail. Receipt: `docs/evidence/mas-evidence-local-capture-2026-11-02.json`. The age identity is only on the operator workstation. It is not escrowed, and nothing was published to `platform-pg/application-archives/mas/`. -That prefix still needs its own publisher grant. The profile is now -accepted by `scripts/primary_application_archive.py`. +The profile is accepted by `scripts/primary_application_archive.py`. + +2026-11-02: the prefix publisher is prepared as draft `CCR-2026-0062`. +It names `platform/workloads/mas/backup-primary`, policy +`workload-kv-read-mas-backup-primary`, ServiceAccount +`backup-primary-delivery` in namespace `mas`, and delivery at +`/etc/mas-backup/primary.env`. Bindings are unconfirmed and delivery +admission is false. The IAM application, OpenBao value, live +ServiceAccount, and node file are not created. Pair-custody and +slot-preparation lists still name only coulomb-social and email-connect. +Design: `docs/credential-lane-designs/mas-evidence-backup-grant-2026-11-02.md`.