From e84b68db018357e0062e616d468351caa71d04ce Mon Sep 17 00:00:00 2001 From: tegwick Date: Sun, 4 Oct 2026 23:21:55 +0200 Subject: [PATCH] Record native ESO result and prepare scoped self-token amendment Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a10780-6d41-7952-9718-dfbc1f41236f --- credential-change-requests/CCR-2026-0032.yaml | 13 ++++- .../2026-10-04-requester-delivery.json | 25 ++++++++ .../informed-decision/checklist.md | 58 ++++++++----------- ...nformed-decision-sitting-requester-eso.hcl | 8 +++ .../informed_decision_requester_metadata.py | 12 ++-- ...st_informed_decision_requester_metadata.py | 18 ++++++ ...ed-decision-requester-workload-delivery.md | 18 +++++- 7 files changed, 111 insertions(+), 41 deletions(-) create mode 100644 docs/evidence/2026-10-04-requester-delivery.json diff --git a/credential-change-requests/CCR-2026-0032.yaml b/credential-change-requests/CCR-2026-0032.yaml index ffa5fe6..747834c 100644 --- a/credential-change-requests/CCR-2026-0032.yaml +++ b/credential-change-requests/CCR-2026-0032.yaml @@ -3,7 +3,7 @@ kind: credential-change-request schema_version: 1 request_type: workload-kv-read title: Informed Decision create-only requester workload read -status: approved +status: proposed created: '2026-10-04' updated: '2026-10-04' requester: @@ -46,6 +46,16 @@ review: approval. Attended OpenBao OIDC/MFA and native verification remain required; broader lifecycle cutover and separate issuer rotation are not approved by this record.' + - at: '2026-10-04T21:21:12.702154+00:00' + reviewer: codex + decision: amendment_proposed + comment: Prior approved metadata was applied and verified by attended helper exit + 0. ArgoCD delivered the three objects, but native ESO validation receives 403 + at auth/token/lookup-self. Propose adding only lookup-self read and revoke-self + update, as required by existing ESO reader pattern. Exact KV path, bound identity, + audience, TTL and no-default-policy remain unchanged. This amendment requires + founder approval and attended administration; prior approval is retained in + history. target: domain: financials tenant: platform @@ -78,6 +88,7 @@ openbao: service_account_namespaces: - informed-decision bound_claims_confirmed: true + token_self_lifecycle: true access_frontdoor: type: external-secrets catalog_id: informed-decision-sitting-requester-eso diff --git a/docs/evidence/2026-10-04-requester-delivery.json b/docs/evidence/2026-10-04-requester-delivery.json new file mode 100644 index 0000000..d2638ff --- /dev/null +++ b/docs/evidence/2026-10-04-requester-delivery.json @@ -0,0 +1,25 @@ +{ + "at": "2026-10-04T21:21:12.710394+00:00", + "authority": "ADMINISTER @ realm:kubernetes/railiance01", + "activation": "APPROVED", + "ccr": "CCR-2026-0032", + "metadata_helper_exit": 0, + "metadata_phase": "metadata_verified", + "node_ip": "92.205.62.239", + "cpu_requests_millicores": 3445, + "server_dry_run_objects": 5, + "diff_reviewed": true, + "application": "informed-decision-requester", + "manifest_revision": "4332c391ea7f66479f67968222a45be4fc6e2f90", + "sync": "Succeeded", + "automated_sync": false, + "store_ready": false, + "eso_ready": false, + "native_failure": { + "lookup_self_failed": true, + "http_403": true + }, + "service_rollout_performed": false, + "credential_values_output": false, + "amendment_pending": "token self lookup/read and revoke/update only" +} diff --git a/docs/provisioning-windows/2026-10-04-1000/informed-decision/checklist.md b/docs/provisioning-windows/2026-10-04-1000/informed-decision/checklist.md index 52bedfe..71517d0 100644 --- a/docs/provisioning-windows/2026-10-04-1000/informed-decision/checklist.md +++ b/docs/provisioning-windows/2026-10-04-1000/informed-decision/checklist.md @@ -1,41 +1,29 @@ -# Requester delivery: approved, awaiting attended execution +# Requester delivery: metadata applied; ESO amendment pending -CCR-2026-0032 was approved by Bernd Worsch in the informed-decision session on -2026-10-04 after owner runtime acceptance at c084600. This is the exact requester -delivery approval; broader service cutover and issuer rotation remain separate. +The founder completed the attended metadata child with exit zero. Receipt: +`docs/evidence/requester-metadata/626537db6f7e45788bc0538054225ae5.json`. +ArgoCD application informed-decision-requester successfully synced manifest +revision 4332c391ea7f66479f67968222a45be4fc6e2f90. It has no automated sync or +pruning. The decision service deployment was not changed. -Approved CCR SHA256: -`c54dd86fd1bd754e64b135f02cac8d9a8f4db314cb3ca44c9645565aa816eee7` +Native validation exposed a missing prerequisite: ESO calls +`auth/token/lookup-self`, which the approved exact-path-only policy denies (403). +The amendment adds exactly these capabilities to the same reader policy: -The metadata child validates this digest, approved status, confirmed reviewed -binding, policy and role before execution. It compares both live objects before -writing missing metadata, refuses conflicts, and reads back exact configuration. -It neither reads credential values nor deploys Kubernetes objects. - -Run from the founder's terminal with the existing OpenBao tunnel and browser: - -```sh -BAO_ADDR=http://127.0.0.1:18200 VAULT_ADDR=http://127.0.0.1:18200 \ - warden access openbao-platform-admin-login --exec -- \ - python3 /home/worsch/railiance-platform/scripts/informed_decision_requester_metadata.py \ - --expected-ccr-sha256 c54dd86fd1bd754e64b135f02cac8d9a8f4db314cb3ca44c9645565aa816eee7 +```hcl +path "auth/token/lookup-self" { capabilities = ["read"] } +path "auth/token/revoke-self" { capabilities = ["update"] } ``` -Warden performs OIDC/MFA, runs the silent child, revokes its session and removes -private custody. Return only the exit code. Exit zero confirms this metadata -operation and Warden cleanup; it does not prove workload delivery or acceptance. -On nonzero exit, inspect bounded native metadata before any retry. +No new data paths, metadata listing, default policy, TTL, account, namespace, +audience or approval scopes are proposed. These are self-token operations only. +CCR-2026-0032 is proposed for this amendment; previous approval/application +remain in its review history. Do not rerun the superseded command/digest. -After successful metadata execution, continue owner-controlled ESO deployment, -exact workload positive/negative proof, mounted projection and requester exchange. -Keep the receipt-contract checks pending until observed. No credential rotation -is included. Checklist complete: false; no live metadata applied by the agent. - -## Helper repair after exit 11 - -The first attended attempt reported child_failed. Installed CLI testing exposed -an absence-diagnostic mismatch, now fixed. The exact CCR digest and command -above remain valid. The child compares both current objects before any writes, -and now records fixed phase/exit metadata under -`docs/evidence/requester-metadata/`. No CLI output or credential data is retained. -Report only the Warden exit code; the agent can inspect the bounded local receipt. +After founder approval, record the amended approved CCR digest. The updated +contained helper compares both objects before replacing only the exact previous +policy with the exact amended policy, preserves the role and refuses any other +drift. Fourteen helper tests pass, including predecessor upgrade and conflict +refusal. Run through the same attended platform-admin lane; it remains silent +and records fixed phase/exit metadata. Then verify ESO readiness and native scope, +projection/exchange and cleanup receipts. Checklist complete: false. diff --git a/openbao/policies/workload-kv-read-informed-decision-sitting-requester-eso.hcl b/openbao/policies/workload-kv-read-informed-decision-sitting-requester-eso.hcl index 8d8d4a0..7a395d1 100644 --- a/openbao/policies/workload-kv-read-informed-decision-sitting-requester-eso.hcl +++ b/openbao/policies/workload-kv-read-informed-decision-sitting-requester-eso.hcl @@ -1,3 +1,11 @@ path "platform/data/workloads/informed-decision/sitting-requester" { capabilities = ["read"] } + +path "auth/token/lookup-self" { + capabilities = ["read"] +} + +path "auth/token/revoke-self" { + capabilities = ["update"] +} diff --git a/scripts/informed_decision_requester_metadata.py b/scripts/informed_decision_requester_metadata.py index 924b6d5..d005a7b 100644 --- a/scripts/informed_decision_requester_metadata.py +++ b/scripts/informed_decision_requester_metadata.py @@ -17,6 +17,8 @@ ROOT = Path(__file__).resolve().parents[1] CCR = ROOT / 'credential-change-requests/CCR-2026-0032.yaml' POLICY = 'workload-kv-read-informed-decision-sitting-requester-eso' ROLE = 'auth/kubernetes/role/informed-decision-sitting-requester-eso' +LEGACY_POLICY = 'path "platform/data/workloads/informed-decision/sitting-requester" {\n capabilities = ["read"]\n}\n' +EXPECTED_POLICY = 'path "platform/data/workloads/informed-decision/sitting-requester" {\n capabilities = ["read"]\n}\n\npath "auth/token/lookup-self" {\n capabilities = ["read"]\n}\n\npath "auth/token/revoke-self" {\n capabilities = ["update"]\n}\n' class Refused(Exception): @@ -75,7 +77,7 @@ def source(expected_digest): auth = bao['auth'] if (bao['policy_name'] != POLICY or bao['kv_path'] != 'platform/workloads/informed-decision/sitting-requester' or bao['fields'] != ['CLIENT_SECRET'] or bao.get('metadata_read') is not False - or bao.get('token_self_lifecycle', False) is not False + or bao.get('token_self_lifecycle', False) is not True or auth['method'] != 'kubernetes' or auth['mount'] != 'kubernetes' or auth['role'] != ROLE.rsplit('/', 1)[1]): raise Refused(2) @@ -87,7 +89,7 @@ def source(expected_digest): 'token_no_default_policy': True}: raise Refused(2) policy = module.generated_policy_hcl(ccr) - if (ROOT / bao['policy_file']).read_text() != policy: + if policy != EXPECTED_POLICY or (ROOT / bao['policy_file']).read_text() != policy: raise Refused(2) return policy, payload @@ -98,11 +100,13 @@ def apply(policy, payload, *, command=cli, phase=lambda value: None): phase('read_role') current_role = command(['read', '-format=json', ROLE], missing_ok=True) # Check BOTH before mutating either; differing objects require a fresh review. - if current_policy is not None and current_policy.get('data', {}).get('policy') != policy: + existing_policy = current_policy.get('data', {}).get('policy') if current_policy is not None else None + allowed_predecessor = policy == EXPECTED_POLICY and existing_policy == LEGACY_POLICY + if current_policy is not None and existing_policy != policy and not allowed_predecessor: raise Refused(3) if current_role is not None and not role_matches(current_role.get('data')): raise Refused(3) - if current_policy is None: + if current_policy is None or allowed_predecessor: phase('write_policy') command(['write', '-format=json', 'sys/policies/acl/' + POLICY, '-'], json.dumps({'policy': policy}).encode()) diff --git a/tests/test_informed_decision_requester_metadata.py b/tests/test_informed_decision_requester_metadata.py index dbcb175..55fed53 100644 --- a/tests/test_informed_decision_requester_metadata.py +++ b/tests/test_informed_decision_requester_metadata.py @@ -82,6 +82,24 @@ class MetadataTests(unittest.TestCase): self.assertEqual(set(saved), {'sys/policies/acl/' + m.POLICY, m.ROLE}) self.assertEqual([args[0] for args in calls], ['read', 'read', 'write', 'write', 'read', 'read']) + def test_exact_legacy_policy_upgrade_preserves_role(self): + saved, writes = [m.LEGACY_POLICY], [] + def command(args, payload=None, **kwargs): + if args[0] == 'write': + writes.append(args[2]); saved[0] = json.loads(payload)['policy']; return {} + return {'data': {'policy': saved[0]}} if args[-1].startswith('sys/') else {'data': role()} + m.apply(m.EXPECTED_POLICY, {}, command=command) + self.assertEqual(writes, ['sys/policies/acl/' + m.POLICY]) + self.assertEqual(saved[0], m.EXPECTED_POLICY) + + def test_legacy_policy_upgrade_refuses_different_role_before_write(self): + calls = [] + def command(args, **kwargs): + calls.append(args) + return {'data': {'policy': m.LEGACY_POLICY}} if args[-1].startswith('sys/') else {'data': dict(role(), audience='wrong')} + with self.assertRaises(m.Refused): m.apply(m.EXPECTED_POLICY, {}, command=command) + self.assertTrue(all(args[0] == 'read' for args in calls)) + def test_postwrite_role_drift_fails_verification(self): calls = [] def command(args, payload=None, **kwargs): diff --git a/workplans/RPF-WP-0051-informed-decision-requester-workload-delivery.md b/workplans/RPF-WP-0051-informed-decision-requester-workload-delivery.md index 9e3c25e..8404fb9 100644 --- a/workplans/RPF-WP-0051-informed-decision-requester-workload-delivery.md +++ b/workplans/RPF-WP-0051-informed-decision-requester-workload-delivery.md @@ -91,7 +91,7 @@ priority: high depends_on: [RPF-WP-0051-T02] needs_human: true decision_id: "0d6792b6-59e4-4fa0-887a-c4e51ea8e131" -blocking_reason: "Exact requester delivery approved by founder. Await attended OpenBao OIDC/MFA execution, then native custody/delivery receipts; broader lifecycle cutover remains separate." +blocking_reason: "Approved metadata applied; ESO validation fails on token lookup-self. Prepared exact self-token lookup/revoke amendment awaits founder approval and attended execution; broader cutover remains separate." state_hub_task_id: "abbe62c9-8520-563a-9f8a-e12b5209af77" ``` @@ -138,3 +138,19 @@ docs/evidence/requester-metadata/*.json and remains silent. Twelve focused tests pass. The approved CCR and permissions are unchanged. A fresh attended attempt will compare both objects before any missing-only write and record its phase. Native delivery remains pending; do not mark the earlier attempt successful. + +## Native delivery result and required amendment — 2026-10-04 + +Founder reported exit 0 and helper receipt confirms metadata_verified. Created +the reviewed dedicated manual ArgoCD application/project and synced three delivery +objects from 4332c39 after diff/server dry-run. Corrected the draft audience field +to serviceAccountRef.audiences using the installed ESO schema. Node IP and CPU +headroom checked (3445m/4000m); no workload rollout or image change occurred. + +ArgoCD sync succeeded; ClusterSecretStore and ExternalSecret are not Ready. +Bounded condition inspection confirms 403 on auth/token/lookup-self. Existing +ESO readers include self lookup/read and revoke/update, omitted by this packet. +Prepared only that amendment and an exact-predecessor policy migration in the +silent helper; 14 tests pass. CCR returns to proposed for changed capabilities, +retaining original approval/application history. T03 stays waiting for amendment +approval and fresh attended execution. Evidence: 2026-10-04-requester-delivery.json.