Record native ESO result and prepare scoped self-token amendment
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a10780-6d41-7952-9718-dfbc1f41236f
This commit is contained in:
parent
f7776013af
commit
e84b68db01
7 changed files with 111 additions and 41 deletions
|
|
@ -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
|
||||
|
|
|
|||
25
docs/evidence/2026-10-04-requester-delivery.json
Normal file
25
docs/evidence/2026-10-04-requester-delivery.json
Normal 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"
|
||||
}
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue