Record native ESO result and prepare scoped self-token amendment
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a10780-6d41-7952-9718-dfbc1f41236f
This commit is contained in:
tegwick 2026-10-04 23:21:55 +02:00
parent f7776013af
commit e84b68db01
7 changed files with 111 additions and 41 deletions

View file

@ -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

View file

@ -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"
}

View file

@ -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.

View file

@ -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"]
}

View file

@ -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())

View file

@ -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):

View file

@ -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.