NK-WP-0048: oidc-browser-relying-party 1.1; re-pin the Forgejo case
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Adds verification consumer-enforces-groups and makes hand-over require the
consumer to enforce access_groups (key-cape review R2). Founder go to move to
1.1 before any apply, so no 1.0 run overlaps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 736651@bnt-lap001
Assistant-Session: f6189624-fd64-4109-b53e-f8a59ca8a2d8
This commit is contained in:
tegwick 2026-10-10 13:25:54 +02:00
parent 61ab6bcc33
commit e2174cebaf
7 changed files with 47 additions and 7 deletions

View file

@ -1,4 +1,4 @@
# oidc-browser-relying-party 1.0
# oidc-browser-relying-party 1.1
An internal web service signs its human users in through NetKingdom (KeyCape)
with an OIDC authorization-code client. This type covers the client
@ -126,3 +126,16 @@ Rollback is the exact inverse, in reverse order. The hand-over is removed first,
then the registration, then the secret and its policies, then the case's group
memberships. Groups are deleted only if this case created them and no other case
uses them.
## History
- **1.1** (2026-10-10, minor): verification `consumer-enforces-groups`, and
hand-over requires the consumer to enforce `access_groups`, because KeyCape has
no per-client group gate (key-cape type review R2, key-cape 6038483). No new
acknowledgment: the risk class is unchanged. The Forgejo case was re-pinned
before any apply, on the founder's go.
- **1.0 patch** (2026-10-10): R1 redirect URIs refuse `?` and `#`; R2 `groups`
scope always required; R3/R4 documentation (net-kingdom 61ab6bc).
`{client_id:env}` adopted in `bind-env` and its rollback (9a9b8e3).
- **1.0** (2026-10-09): acknowledged via informed-decision memo r4 (hub decision
`e418263e`).

View file

@ -3,7 +3,7 @@ apiVersion: netkingdom.io/security-case/v0.1
kind: SecurityCase
spec:
id: example-public-portal
type: oidc-browser-relying-party@1.0
type: oidc-browser-relying-party@1.1
status: proposed
owner:
repo: net-kingdom

View file

@ -6,7 +6,7 @@ apiVersion: netkingdom.io/security-case/v0.1
kind: SecurityCase
spec:
id: forgejo-netkingdom-oidc
type: oidc-browser-relying-party@1.0
type: oidc-browser-relying-party@1.1
status: proposed
owner:
repo: railiance-apps

View file

@ -199,3 +199,13 @@ def test_unknown_format_spec_is_rejected():
t = copy.deepcopy(TYPE)
t["spec"]["rollback"][0]["action"] += " {client_id:shout}"
assert any("unknown format spec" in m for m in msgs(v.validate_type(t)))
def test_consumer_enforces_access_groups():
# 1.1: KeyCape has no per-client group gate, so the consumer must (key-cape R2).
issues, r = v.render_case(FORGEJO, as_implemented(), DECLS)
assert msgs(issues) == []
checks = {c["id"]: c for c in r["verification"]}
assert "forge-admins,forge-coulomb-owners,forge-coulomb-readers" in checks["consumer-enforces-groups"]["check"]
hand_over = [s for s in r["follow_through"] if s["id"] == "hand-over"][0]
assert "groups claim" in hand_over["entry_point"]

View file

@ -2,7 +2,7 @@ apiVersion: netkingdom.io/security-case-type/v0.1
kind: SecurityCaseType
spec:
id: oidc-browser-relying-party
version: "1.0"
version: "1.1"
status: acknowledged
title: "Browser OIDC relying party for an internal service"
purpose: >-
@ -238,7 +238,7 @@ spec:
stops the single replica and every client loses sign-in (R1).
- id: hand-over
owner: "{consumer_owner_repo}"
entry_point: "configure {consuming_service} with issuer {issuer}, client {client_id} and custody bao:platform/workloads/keycape/{client_id}"
entry_point: "configure {consuming_service} with issuer {issuer}, client {client_id} and custody bao:platform/workloads/keycape/{client_id}, and make it require one of {access_groups} in the groups claim before sign-in completes"
auth: "the consumer owner's own deployment path"
warden_executes: false
attended: false
@ -267,6 +267,12 @@ spec:
check: "LLDAP groups {access_groups} exist, with exactly the memberships of the accepted case added"
expect: present
reads_secret_value: false
- id: consumer-enforces-groups
# KeyCape has no per-client group gate; only the consumer can enforce
# access_groups (key-cape type review R2, type 1.1).
check: "{consuming_service}'s OIDC source for {client_id} (owner {consumer_owner_repo}) requires one of {access_groups} in the groups claim (configuration read, no secret value)"
expect: present
reads_secret_value: false
- id: secret-delivered
when: "client_type == confidential"
check: "the delivery for sso/keycape-{client_id}-client reports Ready=True (status only)"

View file

@ -1,15 +1,17 @@
# First KnownSecurityCase of oidc-browser-relying-party 1.0 (NK-WP-0048-T06).
# First KnownSecurityCase of oidc-browser-relying-party 1.1 (NK-WP-0048-T06).
# Parameters are the request the founder accepted on 2026-10-08
# (key-cape docs/forgejo-oidc-client-request.yaml, KEY-WP-0038-T01); that
# acceptance carries over as this case's acceptance. One difference: custody is
# derived by the type (platform/workloads/keycape/forgejo), not the request's
# proposed platform/workloads/forgejo/netkingdom-oidc-client. The founder
# acknowledged that derivation with the type (memo r4, 2026-10-09).
# Re-pinned from 1.0 to 1.1 on 2026-10-10 on the founder's go, before any
# apply, so no 1.0 run overlaps (minor change: consumer-enforces-groups).
apiVersion: netkingdom.io/security-case/v0.1
kind: SecurityCase
spec:
id: forgejo-netkingdom-oidc
type: oidc-browser-relying-party@1.0
type: oidc-browser-relying-party@1.1
status: accepted
acceptance:
at: "2026-10-08"

View file

@ -407,6 +407,15 @@ re-pinning. Also open with key-cape: a KeyCape entry point that validates a
rendered client registry without starting the server; until then
`keycape-client.py` mirrors the redirect rule.
2026-10-10: founder go for 1.1, so no 1.0 run overlaps. The type adds
verification `consumer-enforces-groups`, and hand-over now requires the consumer
to enforce `access_groups` (minor, canon section 6; risk class unchanged, no new
acknowledgment; history in the type README). The accepted Forgejo case and both
examples are re-pinned to `oidc-browser-relying-party@1.1` before any apply; the
acknowledgment intake keeps `@1.0` as the record of what was acknowledged.
ops-mason's build and ops-warden's case-ref digest predate this and need a
re-render.
```task
id: NK-WP-0048-T07
status: wait