From a7f9516bb33e283e9f0352f6f5328e8cc39442ad Mon Sep 17 00:00:00 2001 From: tegwick Date: Wed, 14 Oct 2026 19:36:52 +0200 Subject: [PATCH] Record the hub-writer member entity. bernd.worsch-3 is OpenBao entity f94b7c34-e151-30bb-b473-df3ccdbb9bf1. The member receipt must be that entity. T02 is done. The filed role stays unconfirmed until CCR-2026-0044 is approved. Assistant: grok Assistant-Session: 01a13b2d-5f6d-7a32-b2c9-384625c55ca6 --- .custodian-brief.md | 4 ++-- docs/reuse-surface-hub-writer-attended.md | 5 +++-- plans/reuse-surface-hub-writer.md | 19 +++++++++------- src/ops_mason/reuse_surface_hub_writer.py | 13 ++++++----- tests/test_reuse_surface_hub_writer.py | 8 ++++++- .../MASON-WP-0011-reuse-surface-hub-writer.md | 22 +++++++++++-------- 6 files changed, 44 insertions(+), 27 deletions(-) diff --git a/.custodian-brief.md b/.custodian-brief.md index 3b07eb2..3b12d71 100644 --- a/.custodian-brief.md +++ b/.custodian-brief.md @@ -2,7 +2,7 @@ # Custodian Brief — ops-mason **Domain:** infotech -**Last synced:** 2026-10-14 17:06 UTC +**Last synced:** 2026-10-14 17:24 UTC **State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)* ## Active Workstreams @@ -12,7 +12,7 @@ Progress: 1/4 done | workplan_id: `08e52353-b6e5-5742-b7b4-080d51a0cf57` **Open tasks:** - ! Confirm the group and the member entity `9863b4b8` - *(wait: Group reuse-surface-hub-writers exists; member is bernd.worsch-3. That user has no second factor, so the role's aal2 login cannot pass yet. OpenBao entity id is still unrecorded and must not be 4a1f663c-0621-0483-edd0-f852274f4b6b.)* + *(wait: Group reuse-surface-hub-writers exists; member is bernd.worsch-3, and that user has a second factor (founder, 2026-10-14). OpenBao entity id is still unrecorded and must not be 4a1f663c-0621-0483-edd0-f852274f4b6b. bound_claims_confirmed stays false until that check.)* - ! Apply the role without a KV write `7c32e273` *(wait: After T02. Founder applies proposed CCR-2026-0044 through the delegated applier. No bao kv put. Do not attach the policy to the admin entity.)* - ! Record the sanitized receipt `9e12db29` diff --git a/docs/reuse-surface-hub-writer-attended.md b/docs/reuse-surface-hub-writer-attended.md index e49db7c..a5356f2 100644 --- a/docs/reuse-surface-hub-writer-attended.md +++ b/docs/reuse-surface-hub-writer-attended.md @@ -8,8 +8,9 @@ Plan: `plans/reuse-surface-hub-writer.md`. Filed request: Run this only after CCR-2026-0044 is approved and applied. LLDAP group `reuse-surface-hub-writers` exists with member `bernd.worsch-3`, and that user enrolled a second factor on 2026-10-14. `member` still has to be a -login that KeyCape marks `/assurance/level=aal2`. The member must not be -OpenBao entity `4a1f663c-0621-0483-edd0-f852274f4b6b`. Later groups of this +login that KeyCape marks `/assurance/level=aal2`. The member entity is +`f94b7c34-e151-30bb-b473-df3ccdbb9bf1`. A token for +`4a1f663c-0621-0483-edd0-f852274f4b6b` fails. Later groups of this shape go through identity-provisioner `POST /v1/groups/ensure`; see `docs/directory-group-binding.md`. diff --git a/plans/reuse-surface-hub-writer.md b/plans/reuse-surface-hub-writer.md index d9954d5..4ff97a7 100644 --- a/plans/reuse-surface-hub-writer.md +++ b/plans/reuse-surface-hub-writer.md @@ -76,7 +76,8 @@ SEC-DSM §37, in order: OpenBao can use a person or service identity. Do not create a secret to stand in for the caller. - Q2. OpenBao accepts OIDC on `auth/netkingdom`. Use that. A KeyCape group - selects the principal. The principal's OpenBao entity must not be + selects the principal. The recorded member entity is + `f94b7c34-e151-30bb-b473-df3ccdbb9bf1`. It must not be `4a1f663c-0621-0483-edd0-f852274f4b6b` and must not carry `platform-admin` or `operator-custody`. - Q3. The OpenBao token is a 15-minute service token from the role. The hub @@ -101,10 +102,11 @@ static bearer for the hub. Not a new static secret and not a new AppRole. `token_policies` is only the workload policy, `token_no_default_policy` is true, TTL 15m, max 30m, group `reuse-surface-hub-writers`, assurance `aal2`. Callbacks are the workstation URIs above. -3. `create` KeyCape group `reuse-surface-hub-writers` and one member whose - OpenBao entity is not the forbidden entity and has no admin identity - policies. key-cape owns that group. `bound_claims_confirmed` stays false - until they confirm it. +3. `create` KeyCape group `reuse-surface-hub-writers` with member + `bernd.worsch-3`, entity `f94b7c34-e151-30bb-b473-df3ccdbb9bf1`. + `bound_claims_confirmed` stays false on the filed role. The member + receipt rejects any other entity and any token that also carries + `platform-admin` or `operator-custody`. 4. No KV write. No attachment of this policy, or of `workload-kv-read-reuse-surface-runtime-eso`, to entity `4a1f663c-0621-0483-edd0-f852274f4b6b`. @@ -170,6 +172,7 @@ Not applied. No live receipt yet. (`88b4aed`, message `14e23602`). The live policy file stays as it was until apply. The founder created LLDAP group `reuse-surface-hub-writers` with member `bernd.worsch-3`. On 2026-10-14 that user enrolled a second factor. -`tegwick` is not the member. The OpenBao entity id is still unrecorded, so -`bound_claims_confirmed` stays false. A passing login still has to present -`/assurance/level=aal2`. +`tegwick` is not the member. The founder reported OpenBao entity +`f94b7c34-e151-30bb-b473-df3ccdbb9bf1`. `bound_claims_confirmed` stays false +on the filed role. A passing login still has to present +`/assurance/level=aal2` and that entity id. diff --git a/src/ops_mason/reuse_surface_hub_writer.py b/src/ops_mason/reuse_surface_hub_writer.py index 58ded33..7955a69 100644 --- a/src/ops_mason/reuse_surface_hub_writer.py +++ b/src/ops_mason/reuse_surface_hub_writer.py @@ -9,6 +9,7 @@ from __future__ import annotations POLICY = "workload-kv-read-reuse-surface-runtime" ROLE = "reuse-surface-hub-writer-workload-kv-read" FORBIDDEN_ENTITY_ID = "4a1f663c-0621-0483-edd0-f852274f4b6b" +MEMBER_ENTITY_ID = "f94b7c34-e151-30bb-b473-df3ccdbb9bf1" FORBIDDEN_POLICIES = frozenset( { "default", @@ -39,9 +40,9 @@ def assess(report: dict) -> list[str]: """Return the reasons a login report fails. An empty list is a pass. ``non-member`` passes only when login was refused. ``member`` passes only - when the token's policy set is exactly the workload policy, the token is - not the platform-admin entity, the two exact paths are read-only, the - parent and a sibling workload are denied, and the token was revoked. + when the token's policy set is exactly the workload policy, the token's + entity is the recorded member entity, the two exact paths are read-only, + the parent and a sibling workload are denied, and the token was revoked. """ mode = report.get("mode") if mode not in {"member", "non-member"}: @@ -73,8 +74,10 @@ def assess(report: dict) -> list[str]: failures.append( "token belongs to the platform-admin entity; do not attach this policy to it" ) - if not entity_id: - failures.append("token lookup did not report an entity id") + elif entity_id != MEMBER_ENTITY_ID: + failures.append( + f"token entity {entity_id or ''} is not the member entity {MEMBER_ENTITY_ID}" + ) for path in EXACT_READ: caps = _caps(report, path) diff --git a/tests/test_reuse_surface_hub_writer.py b/tests/test_reuse_surface_hub_writer.py index 03f8e6a..c51902e 100644 --- a/tests/test_reuse_surface_hub_writer.py +++ b/tests/test_reuse_surface_hub_writer.py @@ -1,6 +1,7 @@ from ops_mason.reuse_surface_hub_writer import ( DATA, FORBIDDEN_ENTITY_ID, + MEMBER_ENTITY_ID, METADATA, PARENT_DATA, POLICY, @@ -15,7 +16,7 @@ def member(**overrides): "login": "ok", "policies": [POLICY], "identity_policies": [], - "entity_id": "11111111-1111-1111-1111-111111111111", + "entity_id": MEMBER_ENTITY_ID, "capabilities": { DATA: ["read"], METADATA: ["read"], @@ -54,6 +55,11 @@ def test_admin_entity_and_broad_capabilities_fail(): assert any("not exactly" in item for item in failures) +def test_other_entity_fails(): + failures = assess(member(entity_id="11111111-1111-1111-1111-111111111111")) + assert any("not the member entity" in item for item in failures) + + def test_missing_revoke_fails(): assert any("not revoked" in item for item in assess(member(revoked=False))) diff --git a/workplans/MASON-WP-0011-reuse-surface-hub-writer.md b/workplans/MASON-WP-0011-reuse-surface-hub-writer.md index af46d17..5a69298 100644 --- a/workplans/MASON-WP-0011-reuse-surface-hub-writer.md +++ b/workplans/MASON-WP-0011-reuse-surface-hub-writer.md @@ -61,10 +61,8 @@ file is unchanged until that apply. ```task id: MASON-WP-0011-T02 -status: wait +status: done depends_on: [MASON-WP-0011-T01] -blocked_on: human -blocking_reason: "Group reuse-surface-hub-writers exists; member is bernd.worsch-3, and that user has a second factor (founder, 2026-10-14). OpenBao entity id is still unrecorded and must not be 4a1f663c-0621-0483-edd0-f852274f4b6b. bound_claims_confirmed stays false until that check." priority: high state_hub_task_id: "9863b4b8-fcff-5eec-86f9-7249b66c4700" ``` @@ -76,17 +74,23 @@ member. On 2026-10-14 the founder enrolled a second factor for `bernd.worsch-3` at privacyIDEA self-service (`https://pink-account.coulomb.social/`, realm `coulomb`). A later login can carry `/assurance/level=aal2` only when that login is challenged for the -factor. The OpenBao entity id is still unrecorded. It must not be -`4a1f663c-0621-0483-edd0-f852274f4b6b` and must not carry `platform-admin` -or `operator-custody`. +factor. The founder reported the OpenBao entity id +`f94b7c34-e151-30bb-b473-df3ccdbb9bf1`. That id is not +`4a1f663c-0621-0483-edd0-f852274f4b6b`. The member receipt must be this +entity, and its effective policies must be exactly +`workload-kv-read-reuse-surface-runtime`, which fails if the entity carries +`platform-admin` or `operator-custody`. This session did not read the +entity's policy names. The automatic group path is identity-provisioner `POST /v1/groups/ensure`, not user-engine and not ops-mason. See `docs/directory-group-binding.md`. The LLDAP maintenance helper does not create this group name. -`bound_claims_confirmed` stays false until the member entity is checked. -CCR-2026-0044 stays proposed until platform-operator and reuse-surface-owner -approve. +`bound_claims_confirmed` stays false on the filed role. CCR-2026-0044 stays +proposed until platform-operator and reuse-surface-owner approve. + +Done 2026-10-14. Group, member, second factor, and entity id are recorded. +The verifier pins `f94b7c34-e151-30bb-b473-df3ccdbb9bf1`. ## Apply the role without a KV write