correct exact source case-type pin
Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a126e1-76f8-7643-8cf3-e93336539ade
This commit is contained in:
parent
93ac156adf
commit
62bbdee811
3 changed files with 53 additions and 14 deletions
30
docs/keycape-client-secret-generate-type-pin-review.md
Normal file
30
docs/keycape-client-secret-generate-type-pin-review.md
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# Exact case-type pin correction — 2026-10-10
|
||||
|
||||
The broker's `CASE_TYPE` still required browser-RP @1.0 after the founder
|
||||
authorized @1.1 and net-kingdom re-pinned the accepted Forgejo case. That made
|
||||
the real case fail `case_type_mismatch` before any backend call.
|
||||
|
||||
`keycape_client_secret_generate.py` now accepts exactly
|
||||
`oidc-browser-relying-party@1.1`; @1.0, arbitrary later versions and other
|
||||
types remain refused. Existing exact-byte case-ref, materialized status,
|
||||
client match, confidential/reserved identity, caller/root/agent boundary,
|
||||
scoped grant, CAS0 create-once, silent receipt and revocation checks are unchanged.
|
||||
|
||||
Authority evidence: NK-WP-0048, 2026-10-10 founder go for 1.1; source type
|
||||
`security-case-types/oidc-browser-relying-party/type.yaml` version 1.1,
|
||||
acknowledged; accepted Forgejo case carries @1.1. No case status, live backend
|
||||
or credential changed during this correction.
|
||||
|
||||
Regression uses the actual accepted Forgejo file shape with materialized
|
||||
status solely in the offline fake test fixture. Real accepted (unmaterialized)
|
||||
case remains refused. Ten subprocess CLI tests pass against a fake bao in an
|
||||
isolated temporary tree, including silence, exact mismatch before any backend
|
||||
call, reserved/agent/root identity guards, scoped token delivery, CAS0/race and
|
||||
revocation. No live broker execution is claimed.
|
||||
|
||||
The materialization/run circularity remains an owner contract question:
|
||||
MASON-WP-0010 describes mint-secret as needed before materialized, while
|
||||
WARDEN-WP-0044 and this broker require materialized before mint-secret.
|
||||
Owner review should define structural materialization with exact applied reader
|
||||
receipts, then follow-through creates custody and verifies delivery. This
|
||||
correction does not silently relax status gating or assert those receipts.
|
||||
|
|
@ -16,7 +16,7 @@ Steps (every one fails closed):
|
|||
the broker issuer policy for this grant.
|
||||
2. Re-derive the case reference from ``--case-file`` (sha256 over its exact
|
||||
bytes) and require: it equals ``--case-ref``; type
|
||||
``oidc-browser-relying-party@1.0``; status ``materialized``; client_type
|
||||
``oidc-browser-relying-party@1.1``; status ``materialized``; client_type
|
||||
``confidential``; ``parameters.client_id`` equals ``--client-id``, which
|
||||
matches the type's pattern and is not a reserved entry.
|
||||
3. Mint a 5-minute grant token through token role
|
||||
|
|
@ -57,8 +57,8 @@ ISSUER_POLICY = 'credential-broker-keycape-client-secret-generate-issuer'
|
|||
PREFIX = 'workloads/keycape'
|
||||
RESERVED = {'secrets-engine-openbao'}
|
||||
FIELD = 'CLIENT_SECRET'
|
||||
CASE_TYPE = 'oidc-browser-relying-party@1.0'
|
||||
# oidc-browser-relying-party@1.0 parameter client_id.
|
||||
CASE_TYPE = 'oidc-browser-relying-party@1.1'
|
||||
# oidc-browser-relying-party@1.1 parameter client_id.
|
||||
CLIENT_ID_RE = re.compile(r'^[a-z0-9][a-z0-9-]{1,62}$')
|
||||
CASE_REF_RE = re.compile(r'^[a-z0-9][a-z0-9-]*@sha256:[0-9a-f]{64}$')
|
||||
# 48 random bytes -> 64 URL-safe characters, confirmed by key-cape 2026-10-10
|
||||
|
|
|
|||
|
|
@ -53,17 +53,8 @@ FAKE_BAO = textwrap.dedent(f'''\
|
|||
save(); sys.exit(9)
|
||||
''')
|
||||
|
||||
CASE = textwrap.dedent('''\
|
||||
apiVersion: netkingdom.io/security-case/v0.1
|
||||
kind: SecurityCase
|
||||
spec:
|
||||
id: forgejo-netkingdom-oidc
|
||||
type: oidc-browser-relying-party@1.0
|
||||
status: materialized
|
||||
parameters:
|
||||
client_id: forgejo
|
||||
client_type: confidential
|
||||
''')
|
||||
# Exact accepted Forgejo @1.1 shape; materialized only in this fake test.
|
||||
CASE = '# First KnownSecurityCase of oidc-browser-relying-party 1.1 (NK-WP-0048-T06).\n# Parameters are the request the founder accepted on 2026-10-08\n# (key-cape docs/forgejo-oidc-client-request.yaml, KEY-WP-0038-T01); that\n# acceptance carries over as this case\'s acceptance. One difference: custody is\n# derived by the type (platform/workloads/keycape/forgejo), not the request\'s\n# proposed platform/workloads/forgejo/netkingdom-oidc-client. The founder\n# acknowledged that derivation with the type (memo r4, 2026-10-09).\n# Re-pinned from 1.0 to 1.1 on 2026-10-10 on the founder\'s go, before any\n# apply, so no 1.0 run overlaps (minor change: consumer-enforces-groups).\napiVersion: netkingdom.io/security-case/v0.1\nkind: SecurityCase\nspec:\n id: forgejo-netkingdom-oidc\n type: oidc-browser-relying-party@1.1\n status: materialized\n acceptance:\n at: "2026-10-08"\n record: "key-cape docs/forgejo-oidc-client-request.yaml (status accepted-2026-10-08, KEY-WP-0038-T01); type acknowledged via informed-decision memo nk-wp-0048-t05-oidc-browser-relying-party-r4, hub decision e418263e"\n by:\n - {role: owner, name: "founder (for railiance-apps)"}\n - {role: founder, name: founder}\n owner:\n repo: railiance-apps\n person: founder\n parameters:\n client_id: forgejo\n display_name: Forgejo source forge\n redirect_uris: https://forgejo.coulomb.social/user/oauth2/netkingdom/callback\n allowed_scopes: openid,profile,email,groups\n client_type: confidential\n mfa_required: "true"\n access_groups: forge-admins,forge-coulomb-owners,forge-coulomb-readers\n initial_members: forge-admins=tegwick;forge-coulomb-owners=tegwick\n consuming_service: forgejo\n consumer_owner_repo: railiance-apps\n'
|
||||
|
||||
|
||||
class Generate(unittest.TestCase):
|
||||
|
|
@ -155,6 +146,24 @@ class Generate(unittest.TestCase):
|
|||
code, receipt = self.run_cli()
|
||||
self.assertEqual((code, receipt['outcome']), (2, outcome))
|
||||
|
||||
def test_only_exact_acknowledged_type_version_is_admitted(self):
|
||||
for type_ref in ('oidc-browser-relying-party@1.0',
|
||||
'oidc-browser-relying-party@1.2',
|
||||
'oidc-browser-relying-party@99.0',
|
||||
'confidential-service-client@1.1'):
|
||||
with self.subTest(type_ref=type_ref):
|
||||
self.write_case(CASE.replace('oidc-browser-relying-party@1.1', type_ref))
|
||||
self.state['calls'] = []
|
||||
code, receipt = self.run_cli()
|
||||
self.assertEqual((code, receipt['outcome']), (2, 'case_type_mismatch'))
|
||||
self.assertEqual(self.state['calls'], [])
|
||||
|
||||
def test_exact_accepted_case_still_requires_materialization(self):
|
||||
self.write_case(CASE.replace('status: materialized', 'status: accepted'))
|
||||
code, receipt = self.run_cli()
|
||||
self.assertEqual((code, receipt['outcome']), (2, 'case_not_materialized'))
|
||||
self.assertEqual(self.state['calls'], [])
|
||||
|
||||
def test_agents_root_and_unbound_callers_refused(self):
|
||||
code, receipt = self.run_cli(env_extra={'WARDEN_AGENT_ID': 'codex'})
|
||||
self.assertEqual((code, receipt['outcome']), (2, 'agent_callers_refused'))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue