From 3157454b848b21bfb164efa4ac3293adde774904 Mon Sep 17 00:00:00 2001 From: tegwick Date: Wed, 4 Nov 2026 02:05:18 +0100 Subject: [PATCH] AUDIT-WP-0018-T04: align seed with settled CCR-2026-0063 (railiance-platform f3b0c4f) - sso delivery is ExternalSecret/Secret sso/bounded-executor-tokens key audit-core (the Secret the rapp run Job already mounts), not nk-bind-executor-audit/audit-token. - CCR check now also pins the new reader shape (audience openbao, explicit max TTL 15m, token_self_lifecycle) and that the CCR names this script as its custody procedure and the bounded-executor-tokens delivery. - Docs/workplan: this script is the single seeder; railiance-platform fences the boundary (nk_bind_executor_custody.py fence) and owns manifests/nk-bind-executor-eso.yaml. Co-Authored-By: Claude Opus 5.5 Assistant: claude-code Assistant-Model: opus Assistant-Process: 523928@bnt-lap001 Assistant-Session: 6c737afb-9c14-4152-9f02-477214b9c350 --- docs/bounded-executor-receipts.md | 30 ++++++++++++------- scripts/seed-nk-bounded-executor-sender.py | 23 ++++++++++---- tests/test_seed_nk_bounded_executor_sender.py | 12 ++++++++ ...P-0018-bounded-executor-receipt-custody.md | 11 ++++--- 4 files changed, 56 insertions(+), 20 deletions(-) diff --git a/docs/bounded-executor-receipts.md b/docs/bounded-executor-receipts.md index a4f9830..b1aa8af 100644 --- a/docs/bounded-executor-receipts.md +++ b/docs/bounded-executor-receipts.md @@ -266,8 +266,9 @@ How the token reaches both sides. One founder-run process, - tenant `tenant:platform` gets 403; - another source gets 403. An unknown bearer gets 401. -7. It force-syncs `sso/nk-bind-executor-audit` and compares `audit-token` by - hash, but only if that ExternalSecret exists. +7. It force-syncs `sso/bounded-executor-tokens` and compares key `audit-core` + by hash, but only if that ExternalSecret exists. That is the Secret the + rapp run Job already mounts. The script is silent. The receipt holds versions, booleans and a 12-hex fingerprint. A rerun reuses its own custody and writes nothing new. It refuses @@ -277,24 +278,30 @@ collision and a concurrent registry write. Tests: The script refuses before any write unless all of the following hold: -- CCR-2026-0063 is `approved` or later, with all three owner reviews; +- CCR-2026-0063 is `approved` or later, with all three owner reviews. Its + reader shape must be audience `openbao`, explicit max TTL and token self-lifecycle. + Its delivery must be `sso/bounded-executor-tokens` key `audit-core`, and it must + name this script as its custody procedure; - the cluster is railiance01 (kube-system UID); - the receiver runs the pinned image; - the live scope ConfigMap matches; - the ingress policy exists; - the coding-agent boundary already denies the custody data and metadata paths. -It does not create the reader policy, the role or the boundary -(railiance-platform). It also does not create the `sso` ClusterSecretStore and -ExternalSecret, which belong to the rapp-bounded-executor package (CCR-2026-0063 -`delivery.target`). +CCR-2026-0063 (railiance-platform f3b0c4f) names this script as its single +seeder. The script does not create the reader policy, the role or the boundary. +railiance-platform owns those: its credential-change applier creates the +policy and role, and `scripts/nk_bind_executor_custody.py fence` creates the +boundary. Nor does it create ClusterSecretStore `openbao-nk-bind-executor-audit` +or ExternalSecret `sso/bounded-executor-tokens`, which are railiance-platform's +`manifests/nk-bind-executor-eso.yaml`. ## Founder runbook — nk-bounded-executor sender Run these in order. Steps 1 and 2 can run now. Step 3 depends on CCR-2026-0063: railiance-platform must have it approved by platform-owner, audit-core-owner and -net-kingdom-owner, and must have applied its reader policy, role and -coding-agent boundary entries. +net-kingdom-owner, must have applied its reader policy and role, and must have +run `nk_bind_executor_custody.py fence` for the coding-agent boundary entries. **1. Ingress (NK-WP-0056-T16).** This applies exactly one object. Run the server dry-run first, then the apply: @@ -335,8 +342,9 @@ KUBECONFIG=/home/worsch/.kube/config-railiance01 kubectl -n audit-core get netwo ``` The expected status is `seeded_pending_sso_delivery`, or `seeded_and_delivered` -once the rapp package's ExternalSecret exists. The expected probe is +once railiance-platform's ExternalSecret `sso/bounded-executor-tokens` exists. The expected probe is `{"read": 403, "own_tenant": 200, "other_tenant": 403, "other_source": 403}`. -After the rapp package applies `sso/nk-bind-executor-audit`, rerun step 3 with +If railiance-platform applies `manifests/nk-bind-executor-eso.yaml` after the +seed, rerun step 3 with `-r2.json`. It writes no custody or registry and confirms the `sso` copy by hash. diff --git a/scripts/seed-nk-bounded-executor-sender.py b/scripts/seed-nk-bounded-executor-sender.py index a3b612c..336d08c 100755 --- a/scripts/seed-nk-bounded-executor-sender.py +++ b/scripts/seed-nk-bounded-executor-sender.py @@ -12,7 +12,8 @@ contract. One process mints one bearer and writes it to the two places that need It then syncs ExternalSecret audit-core/audit-core-senders, restarts the receiver, and proves without writing an event that the live receiver knows the bearer with the exact registered scope. If railiance-platform's ExternalSecret -sso/nk-bind-executor-audit exists, the script syncs it and compares the token by hash. +sso/bounded-executor-tokens exists (manifests/nk-bind-executor-eso.yaml), the +script syncs it and compares key audit-core by hash. This script is silent. The wrapper discards stdout and stderr, so `warden access --exec` fails closed on any output. The token is never printed, never passed on a command line @@ -25,10 +26,15 @@ entry is not rewritten. Anything else refuses and changes nothing: a sender without custody, a drifted entry, another request's custody, a token collision or a concurrent registry write. +CCR-2026-0063 names this script as its custody procedure (railiance-platform +f3b0c4f). It is the only seeder; railiance-platform's nk_bind_executor_custody.py +fences the coding-agent boundary first and verifies afterwards. + Founder-run only. The exact command is in docs/bounded-executor-receipts.md, section "Founder runbook". The script does not create OpenBao policies or roles, the coding-agent boundary, the ClusterSecretStore or the ExternalSecret in sso. Those belong to -railiance-platform and the rapp-bounded-executor package. +railiance-platform (credential-change applier, nk_bind_executor_custody.py fence, +manifests/nk-bind-executor-eso.yaml). """ from __future__ import annotations @@ -61,8 +67,8 @@ CUSTODY_META = "platform/metadata/workloads/net-kingdom/bounded-executor/audit-s BOUNDARY = "sys/policies/acl/agent-high-risk-boundary" CLUSTER_UID = "a553c742-0115-43d4-99a4-a5ca56fe0786" # railiance01 kube-system -SSO_SECRET = "nk-bind-executor-audit" -SSO_KEY = "audit-token" +SSO_SECRET = "bounded-executor-tokens" # ExternalSecret and Secret name (CCR-2026-0063 delivery) +SSO_KEY = "audit-core" # the key the rapp run Job mounts TOKEN_SHAPE = re.compile(r"[A-Za-z0-9_-]{64}") # Runs inside the receiver pod. The bearer arrives on stdin and leaves only as @@ -133,8 +139,15 @@ def check_ccr(doc: dict) -> None: ob = doc.get("openbao") or {} require(ob.get("kv_path") == CUSTODY_KV and ob.get("fields") == ["AUDIT_TOKEN", "CUSTODY_REQUEST"] and ob.get("metadata_read") is False, "ccr_custody_contract_mismatch") + auth = ob.get("auth") or {} + require(auth.get("audience") == "openbao" and auth.get("token_explicit_max_ttl") == "15m" + and ob.get("token_self_lifecycle") is True, "ccr_reader_shape_mismatch") delivery = doc.get("delivery") or {} - require(delivery.get("namespace") == "sso", "ccr_delivery_mismatch") + target = str(delivery.get("target", "")) + require(delivery.get("namespace") == "sso" + and f"sso/{SSO_SECRET}" in target and f"key {SSO_KEY}" in target + and "seed-nk-bounded-executor-sender" in str(delivery.get("custody_procedure", "")), + "ccr_delivery_mismatch") def load_ccr(path: Path = CCR_FILE) -> tuple[dict, str]: diff --git a/tests/test_seed_nk_bounded_executor_sender.py b/tests/test_seed_nk_bounded_executor_sender.py index 8b468ed..bdca39f 100644 --- a/tests/test_seed_nk_bounded_executor_sender.py +++ b/tests/test_seed_nk_bounded_executor_sender.py @@ -192,6 +192,18 @@ def test_ccr_contract_as_drafted_matches_and_refuses_until_approved(): moved["openbao"]["kv_path"] = "platform/workloads/net-kingdom/other" with pytest.raises(SEED.Refused, match="ccr_custody_contract_mismatch"): SEED.check_ccr(moved) + old_reader = approved_ccr() + del old_reader["openbao"]["auth"]["audience"] + with pytest.raises(SEED.Refused, match="ccr_reader_shape_mismatch"): + SEED.check_ccr(old_reader) + old_delivery = approved_ccr() + old_delivery["delivery"]["target"] = "Secret sso/nk-bind-executor-audit, key audit-token" + with pytest.raises(SEED.Refused, match="ccr_delivery_mismatch"): + SEED.check_ccr(old_delivery) + + +def test_sso_delivery_is_the_secret_the_run_job_mounts(): + assert (SEED.SSO_SECRET, SEED.SSO_KEY) == ("bounded-executor-tokens", "audit-core") def test_wrong_confirmation_refuses_before_any_call(tmp_path, monkeypatch): diff --git a/workplans/AUDIT-WP-0018-bounded-executor-receipt-custody.md b/workplans/AUDIT-WP-0018-bounded-executor-receipt-custody.md index 68e92db..df0295f 100644 --- a/workplans/AUDIT-WP-0018-bounded-executor-receipt-custody.md +++ b/workplans/AUDIT-WP-0018-bounded-executor-receipt-custody.md @@ -141,7 +141,9 @@ state_hub_task_id: "66b495ba-b54a-59db-b5b4-b9c17649b413" NK-WP-0056-T15 needs a bearer for `nk-bounded-executor`. Audit-core's registry must hold the bearer, and so must railiance-platform's CCR-2026-0063 custody path `platform/workloads/net-kingdom/bounded-executor/audit-sender` (`AUDIT_TOKEN`). -ESO projects that path to `sso/nk-bind-executor-audit:audit-token`. +ESO projects that path to `sso/bounded-executor-tokens:audit-core`, the Secret the rapp +run Job already mounts. CCR-2026-0063 was settled in railiance-platform f3b0c4f, +and it names this script as the single seeder. Done 2026-11-04. The script `scripts/seed-nk-bounded-executor-sender.py` has a silent wrapper, @@ -182,9 +184,10 @@ Run the runbook steps in order: the role and the coding-agent boundary entries. 4. **Verify from the receipt.** -`sso` delivery is complete only when rapp-bounded-executor carries the -ClusterSecretStore and the ExternalSecret `nk-bind-executor-audit`, and mounts -key `audit-token`. Today it mounts `bounded-executor-tokens:audit-core`. +`sso` delivery is complete when railiance-platform has applied +`manifests/nk-bind-executor-eso.yaml`. That creates ExternalSecret +`sso/bounded-executor-tokens`, key `audit-core`, which the rapp Job already mounts. +Before step 3, railiance-platform also runs `nk_bind_executor_custody.py fence`. ## Founder decision 2026-10-31