Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 327203@bnt-lap001 Assistant-Session: 55028ae3-4914-4bd1-8f5c-815f3527aef0
144 lines
7.2 KiB
Markdown
144 lines
7.2 KiB
Markdown
---
|
|
id: case-forgejo-netkingdom-oidc
|
|
demand_source: SecurityCase forgejo-netkingdom-oidc (owner railiance-apps)
|
|
consumer_repo: railiance-apps
|
|
credential_type: security-case
|
|
derived_from_type: oidc-browser-relying-party@1.1
|
|
render_digest: sha256:af1f4f81ef313f5e086e6e3de17197d9112dd40f00b4c20b52b5ca73c7a6d18a
|
|
status: reviewed
|
|
case_acceptance:
|
|
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
|
|
at: '2026-10-08'
|
|
by:
|
|
- owner
|
|
- founder
|
|
reference_case: true
|
|
approved_by: null
|
|
approved_at: null
|
|
---
|
|
|
|
# Construction plan (derived-from-type): forgejo-netkingdom-oidc
|
|
|
|
Rendered from `oidc-browser-relying-party@1.1` (Browser OIDC relying party for an internal service). Do not edit by hand:
|
|
re-run `ops-mason plan --case` instead. Render digest `sha256:af1f4f81ef313f5e086e6e3de17197d9112dd40f00b4c20b52b5ca73c7a6d18a`.
|
|
|
|
**Reference case:** the type is `acknowledged`, not yet `implemented`. This case
|
|
is the one whose live materialization takes the type to `implemented`.
|
|
|
|
## 1. Demand
|
|
|
|
Let an internal web service sign its human users in through NetKingdom (KeyCape): an exact-redirect OIDC client, optional MFA pin, the LLDAP groups the service maps to its own roles, and, for confidential clients, a client secret minted straight into OpenBao custody. Replaces the per-client rollout scripts in sso-mfa/k8s/keycape. First case: Forgejo (KEY-WP-0038).
|
|
|
|
## 2. Existing-structure survey
|
|
|
|
Survey source: live (metadata only).
|
|
|
|
No collision with existing policies, roles, KV paths or catalog entries.
|
|
|
|
Already present from this case's own build bundle (not collisions):
|
|
|
|
- openbao_policy workload-kv-read-keycape-forgejo-eso
|
|
|
|
## 3. Objects (from the type's materialization)
|
|
|
|
| Item | Kind | Name |
|
|
|---|---|---|
|
|
| client-secret-path | kv_path | `platform/workloads/keycape/forgejo` |
|
|
| keycape-reader-policy | openbao_policy | `workload-kv-read-keycape-forgejo-eso` |
|
|
| consumer-reader-policy | openbao_policy | `workload-kv-read-keycape-forgejo-forgejo` |
|
|
| eso-role | openbao_role | `external-secrets-keycape-forgejo` |
|
|
| catalog-entry | catalog_entry | `forgejo-keycape-client` |
|
|
|
|
### client-secret-path
|
|
|
|
```
|
|
field CLIENT_SECRET; minted by the credential broker, never written by hand
|
|
```
|
|
|
|
### keycape-reader-policy
|
|
|
|
```
|
|
path "platform/data/workloads/keycape/forgejo" {
|
|
capabilities = ["read"]
|
|
}
|
|
```
|
|
|
|
### consumer-reader-policy
|
|
|
|
```
|
|
path "platform/data/workloads/keycape/forgejo" {
|
|
capabilities = ["read"]
|
|
}
|
|
```
|
|
|
|
### eso-role
|
|
|
|
```
|
|
auth: kubernetes
|
|
bound_service_account_names: [external-secrets]
|
|
bound_service_account_namespaces: [external-secrets]
|
|
token_policies: [workload-kv-read-keycape-forgejo-eso]
|
|
token_no_default_policy: true
|
|
token_ttl: 15m
|
|
token_max_ttl: 15m
|
|
```
|
|
|
|
### catalog-entry
|
|
|
|
```
|
|
id: forgejo-keycape-client
|
|
owner_repo: key-cape
|
|
warden_executes: false
|
|
risk: high
|
|
status: active once verification passes
|
|
workload_ref: applicable, name forgejo, declaration_ref of the consumer's published declaration or the explicit unknown form, never inferred
|
|
path_template: platform/workloads/keycape/forgejo
|
|
field: CLIENT_SECRET
|
|
delegation: native, intended_owner key-cape
|
|
rotation: mint-secret then verification; automatable false until a run has been proven
|
|
```
|
|
|
|
## 4. Review notes
|
|
|
|
Shape reviewed once, when the type was acknowledged; this review checks only
|
|
this case's names against existing structure (section 2).
|
|
|
|
Follow-through (ops-warden):
|
|
|
|
- ensure-groups — net-kingdom (attended): identity-provisioner ensure_service_groups, run inside the provisioner pod through the session's contained cluster access (groups forge-admins,forge-coulomb-owners,forge-coulomb-readers; members exactly forge-admins=tegwick;forge-coulomb-owners=tegwick as recorded in the accepted case, nothing else)
|
|
- mint-secret — railiance-platform: railiance-platform credential broker: generate a client secret inside custody at bao:platform/workloads/keycape/forgejo
|
|
- deliver-secret — railiance-platform: ExternalSecret sso/keycape-forgejo-client (key client-secret) from bao:platform/workloads/keycape/forgejo
|
|
- bind-env — net-kingdom (attended): patch Deployment sso/keycape: env KEYCAPE_FORGEJO_CLIENT_SECRET from sso/keycape-forgejo-client
|
|
- register-client — net-kingdom (attended): sso-mfa/k8s/keycape/keycape-client.py apply --client-file <client-from-case> --case-acceptance <record> (net-kingdom.keycape-client-registration)
|
|
- hand-over — railiance-apps: configure forgejo with issuer https://kc.coulomb.social, client forgejo and custody bao:platform/workloads/keycape/forgejo, and make it require one of forge-admins,forge-coulomb-owners,forge-coulomb-readers in the groups claim before sign-in completes
|
|
|
|
Verification:
|
|
|
|
- authorize-accepts-redirects (present): GET https://kc.coulomb.social/authorize with client forgejo and each of https://forgejo.coulomb.social/user/oauth2/netkingdom/callback returns the login page
|
|
- authorize-refuses-other-redirect (deny): GET https://kc.coulomb.social/authorize with client forgejo and an unregistered redirect returns an OAuth error
|
|
- custody-denied-to-default (deny): a default-only OpenBao identity has no read capability on bao:platform/workloads/keycape/forgejo
|
|
- custody-allowed-to-consumer (allow): policy workload-kv-read-keycape-forgejo-forgejo grants read on bao:platform/workloads/keycape/forgejo (capabilities check only)
|
|
- groups-present (present): LLDAP groups forge-admins,forge-coulomb-owners,forge-coulomb-readers exist, with exactly the memberships of the accepted case added
|
|
- consumer-enforces-groups (present): forgejo's OIDC source for forgejo (owner railiance-apps) requires one of forge-admins,forge-coulomb-owners,forge-coulomb-readers in the groups claim (configuration read, no secret value)
|
|
- secret-delivered (present): the delivery for sso/keycape-forgejo-client reports Ready=True (status only)
|
|
- mfa-pinned (present): keycape-client.py inspect for forgejo shows the MFA pin on the registered client (non-secret client view)
|
|
|
|
Rollback, in order:
|
|
|
|
- remove the OIDC source for forgejo from forgejo (owner railiance-apps)
|
|
- keycape-client.py apply --operation remove for forgejo
|
|
- remove env KEYCAPE_FORGEJO_CLIENT_SECRET from Deployment sso/keycape, after register-client is reversed
|
|
- delete ExternalSecret sso/keycape-forgejo-client and its target
|
|
- covered by client-secret-path: one metadata delete, after deliver-secret is reversed
|
|
- identity-provisioner revoke_service_groups inside the provisioner pod (attended, as ensure-groups) with the case's memberships; delete_if_empty only if no other case uses forge-admins,forge-coulomb-owners,forge-coulomb-readers
|
|
- delete metadata and all versions at platform/workloads/keycape/forgejo, after the ExternalSecret is gone (this also reverses mint-secret)
|
|
- delete Kubernetes-auth role external-secrets-keycape-forgejo
|
|
- delete policy workload-kv-read-keycape-forgejo-eso, after eso-role
|
|
- delete policy workload-kv-read-keycape-forgejo-forgejo
|
|
- remove catalog entry forgejo-keycape-client
|
|
|
|
## 5. Case acceptance (replaces the executive summary)
|
|
|
|
Accepted by owner, founder at 2026-10-08; 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`.
|