MASON-WP-0010-T01: review oidc-service-client 0.1 materialization (acceptable with changes)
Eleven findings (R1-R11) on net-kingdom's proposed SecurityCaseType oidc-service-client 0.1 for request f61cc81e: type changes R3, R4, R6, R7, R8; ops-mason builder follow-ups R10; rollback addition R11. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 5502@bnt-lap001 Assistant-Session: 68b3b02f-5d0f-4e71-8421-796f62e50196
This commit is contained in:
parent
827781f318
commit
3c69a25442
1 changed files with 106 additions and 1 deletions
|
|
@ -9,7 +9,7 @@ flavor: implementation
|
|||
owner: claude-code
|
||||
topic_slug: netkingdom
|
||||
created: "2026-10-08"
|
||||
updated: "2026-10-11"
|
||||
updated: "2026-10-31"
|
||||
depends_on: []
|
||||
related_repos:
|
||||
- net-kingdom
|
||||
|
|
@ -98,6 +98,111 @@ NK-WP-0048-T05 still waits on WARDEN-WP-0044-T01 and a founder answer.
|
|||
2026-10-09: the founder accepted memo r4; hub decision `e418263e` resolved and
|
||||
the type is `acknowledged` (net-kingdom `0e86f95`). T02 is unblocked.
|
||||
|
||||
**Review (2026-10-31) of net-kingdom `security-case-types/oidc-service-client/type.yaml` 0.1**
|
||||
(proposed, net-kingdom `5d5f15d`, memo `nk-wp-0056-t14-oidc-service-client-r1`,
|
||||
hub decision `f8044f81`, request message `f61cc81e`). Checked against the
|
||||
browser type 1.1, the live CCR-2026-0041/0042 placement and the bounded
|
||||
executor's native lanes CCR-2026-0058/0059, and by a trial render of
|
||||
`examples/nk-bind-executor-approval.yaml` through `case_plan.render` and
|
||||
`case_build` on a scratch copy marked `acknowledged` (no live survey, no
|
||||
OpenBao). All six items render; names come out as
|
||||
`workload-kv-read-keycape-nk-bind-executor-approval-{eso,bounded-executor}`,
|
||||
`external-secrets-keycape-nk-bind-executor-approval` and catalog entry
|
||||
`bounded-executor-keycape-nk-bind-executor-approval`.
|
||||
|
||||
Verdict: **acceptable with changes.** The structure is right and reuses the
|
||||
browser type's custody, ESO and policy families. R3, R4, R6, R7 and R8 change
|
||||
the type (so memo r2 replaces r1); R10 is ops-mason's own builder work and does
|
||||
not block acknowledgment, but must land before the first case is built.
|
||||
|
||||
- **R1 — client-secret-path: ok.** Derived, not case-settable, same
|
||||
`platform/workloads/keycape/{client_id}` / `CLIENT_SECRET` as the browser type
|
||||
and CCR-2026-0033. Unconditional (the type is always confidential), so no
|
||||
`when`. `client_id` is unique in KeyCape, so browser and service clients
|
||||
cannot collide in the one `keycape/` subtree.
|
||||
- **R2 — keycape-reader-policy and naming family: ok.** Unchanged from the
|
||||
browser type; `workload-kv-read-keycape-<client>-<reader>` is respected for
|
||||
both readers. Longest rendered name is 68 characters, within OpenBao limits.
|
||||
- **R3 — eso-role: change needed (small).** Bound to
|
||||
`external-secrets/external-secrets`, one policy, 15m, no default policy:
|
||||
right. But the body omits `audience: openbao` and `token_explicit_max_ttl:
|
||||
15m`, which the consumer role states and the live
|
||||
`external-secrets-keycape-forgejo` role has; ops-mason's builder fills them
|
||||
in silently today. Add both so the template is what gets built, and the two
|
||||
roles read the same.
|
||||
- **R4 — consumer-reader-policy self-lifecycle stanzas: change needed.** The
|
||||
`auth/token/lookup-self` (read) and `auth/token/revoke-self` (update) stanzas
|
||||
are correct and needed (a native per-call reader should revoke its token
|
||||
after the read, and the platform applier refuses a `token_self_lifecycle:
|
||||
true` policy without them, see T04 2026-10-10). But only the consumer policy
|
||||
declares them, while the ESO policy needs them equally. Declare them in
|
||||
**both** policy bodies, so each body is the complete policy the review
|
||||
checks (item 3 of the 1.0 review). ops-mason then stops appending them (R10).
|
||||
- **R5 — consumer-reader-role (native Kubernetes auth): ok.** One
|
||||
ServiceAccount, one namespace, audience `openbao`, 15m ttl/max/explicit max,
|
||||
one policy, no default policy: this is exactly the CCR-2026-0058/0059 shape
|
||||
that is live and verified for `sso/nk-bind-executor`, and "policies are never
|
||||
combined in one role" holds (the executor gets a third separate role). Role
|
||||
name equal to the policy name matches the native-lane convention. Dropping
|
||||
ESO delivery to the consumer removes a Secret copy and a SecretStore per
|
||||
case; ops-mason prefers it.
|
||||
- **R6 — consumer binding parameters: change needed.** The patterns admit
|
||||
`consumer_service_account: default` and namespaces such as
|
||||
`external-secrets`, `openbao` or `kube-system`. Refuse `default` (any pod in
|
||||
the namespace would read the client secret; CCR-2026-0059 verifies the
|
||||
default SA is denied), and refuse the `external-secrets` and `openbao`
|
||||
namespaces, in the type's constraints or the validator.
|
||||
- **R7 — shared namespace with KeyCape's copy: change needed.** The first case
|
||||
binds `sso/nk-bind-executor`, and `sso` is where `deliver-secret` writes
|
||||
`keycape-{client_id}-client`. So "no Secret copy in the consumer's namespace"
|
||||
(README, purpose) is false for this case; isolation rests on the consumer SA
|
||||
having no Secret read in its namespace (true today: rapp-bounded-executor
|
||||
`manifests/rbac.yaml` grants no Secret access). Add a verification:
|
||||
`{consumer_namespace}/{consumer_service_account}` cannot get Secrets in its
|
||||
namespace (in particular `sso/keycape-{client_id}-client`), `can-i` denial as
|
||||
proof; and reword the README claim to "the type creates no Secret copy for
|
||||
the consumer".
|
||||
- **R8 — verification wording: change needed (small).**
|
||||
`custody-allowed-to-consumer` says the policy grants read on the path "and
|
||||
nothing else"; with R4 it also grants token self-lookup/revoke. Say "and no
|
||||
other path under `platform/`, apart from token self-lifecycle". Optionally
|
||||
add the same allow check for the ESO policy.
|
||||
- **R9 — catalog-entry: ok, one question.** `{consuming_service}-keycape-{client_id}`
|
||||
instead of the browser type's `{consuming_service}-keycape-client` is right:
|
||||
a service holds one client per audience, so the browser form would collide.
|
||||
Question: `consuming_service: bounded-executor` differs from the workload name
|
||||
the platform already uses for this executor (`net-kingdom-bind-executor` in
|
||||
CCR-2026-0058/0059 and their catalog ids). The case should use the
|
||||
established name, or the type README should say which one `workload_ref`
|
||||
carries.
|
||||
- **R10 — ops-mason builder (ours, not a type change).** The trial build shows
|
||||
four defects to fix before the first service-client case is built:
|
||||
(a) `_policy_hcl` always appends the self-lifecycle stanzas, so the consumer
|
||||
policy gets them twice; append only when absent. (b) A policy with a role is
|
||||
treated as ESO: the consumer CCR gets `access_frontdoor.type:
|
||||
external-secrets`; for a native role it must be `platform-owner` (as
|
||||
CCR-2026-0059) with a `delivery: {surface: native-workload-login, namespace,
|
||||
service_account}` block. (c) `catalog_id` is hard-coded to
|
||||
`{consuming_service}-keycape-client`; take it from the catalog item.
|
||||
(d) `audience` and `token_explicit_max_ttl` are hard-coded / copied from
|
||||
`token_max_ttl`; take them from the role body (with R3). The consumer CCR is
|
||||
no longer `in_flight`: with the role in the type it is complete `proposed`,
|
||||
`bound_claims_confirmed: false` until the platform owner confirms the SA.
|
||||
- **R11 — rollback order: ok, with one addition.** Consumer configuration,
|
||||
registration, env binding, delivery, then custody (one metadata delete, after
|
||||
the ExternalSecret is gone, per item 6 of the 1.0 review), roles before their
|
||||
policies, catalog last: consistent with the browser type. Addition: deleting
|
||||
the consumer role does not revoke issued tokens; state that rollback is
|
||||
complete only after the consumer's last token has expired (at most 15m after
|
||||
the role is deleted) or was revoked, as the T03 deactivate note does.
|
||||
Suggested, not required: remove `consumer-reader-role` directly after
|
||||
`hand-over` is reversed, so consumer access ends first. (ops-mason's own
|
||||
`rollback.yaml` lists `removes_exactly` in plain reverse order, which differs
|
||||
from the type's steps; fixed with R10.)
|
||||
|
||||
T04 is unchanged by this type: `secrets-engine-openbao`'s second reader is an
|
||||
attended OIDC operator, not a ServiceAccount, so it fits neither type.
|
||||
|
||||
```task
|
||||
id: MASON-WP-0010-T02
|
||||
status: done
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue