diff --git a/credential-change-requests/CCR-2026-0052-net-kingdom-identity-provisioner-bind.yaml b/credential-change-requests/CCR-2026-0052-net-kingdom-identity-provisioner-bind.yaml index 7469167..49daa40 100644 --- a/credential-change-requests/CCR-2026-0052-net-kingdom-identity-provisioner-bind.yaml +++ b/credential-change-requests/CCR-2026-0052-net-kingdom-identity-provisioner-bind.yaml @@ -1,111 +1,128 @@ -{ - "id": "CCR-2026-0052", - "kind": "credential-change-request", - "schema_version": 1, - "request_type": "workload-kv-read", - "title": "NetKingdom identity-provisioner directory bind (svc-provisioner) delivery", - "status": "proposed", - "created": "2026-10-30", - "updated": "2026-10-30", - "requester": { - "agent": "claude-code", - "reason": "NK-WP-0056-T04 pilot: move the first LLDAP service bind out of the founder's personal SOPS custody into platform custody, so later rotations need neither a decrypted custody copy nor a person handling the value. svc-provisioner is the simplest consumer: its own Secret, two keys, no embedded config." - }, - "review": { - "required": true, - "required_approvers": [ - "platform-owner", - "net-kingdom-owner" - ], - "comments": [] - }, - "target": { - "domain": "infotech", - "tenant": "platform", - "workload": "net-kingdom-identity-provisioner", - "environment": "production", - "purpose": "Hold the svc-provisioner LLDAP bind password in platform custody and project only that value into the existing Secret sso/identity-provisioner-ldap; no ld-admin, admin or other service bind" - }, - "openbao": { - "mount": "platform", - "kv_path": "platform/workloads/net-kingdom/directory-binds/svc-provisioner", - "fields": [ - "LDAP_BIND_PASSWORD" - ], - "policy_name": "net-kingdom-svc-provisioner-bind-eso", - "policy_file": "openbao/policies/net-kingdom-svc-provisioner-bind-eso.hcl", - "metadata_read": false, - "token_self_lifecycle": true, - "auth": { - "method": "kubernetes", - "mount": "kubernetes", - "role": "net-kingdom-svc-provisioner-bind-eso", - "audience": "openbao", - "ttl": "15m", - "token_max_ttl": "15m", - "token_explicit_max_ttl": "15m", - "token_no_default_policy": true, - "policies": [ - "net-kingdom-svc-provisioner-bind-eso" - ], - "bound_claims": { - "service_account_names": [ - "net-kingdom-svc-provisioner-bind-eso" - ], - "service_account_namespaces": [ - "sso" - ] - }, - "bound_claims_confirmed": false - } - }, - "access_frontdoor": { - "type": "platform-owner", - "catalog_id": "net-kingdom-svc-provisioner-bind", - "readiness": "pending-review", - "resolvable": false - }, - "lifecycle": { - "deactivate": "Delete the ExternalSecret (deletionPolicy Retain keeps the working Secret), then withdraw the role and policy; the KV entry stays as custody until the founder's copy is confirmed current.", - "rotate": "Change the svc-provisioner password in LLDAP and write the new value as the next KV version with CAS on the current version; ESO projects it and the provisioner restarts. Until NK-WP-0056 executors exist this is founder-run.", - "compromised": "Disable or reset svc-provisioner in LLDAP first (it is in lldap_admin), then rotate as above and review directory changes made under that account; fence the reader role if its boundary is in doubt." - }, - "delivery": { - "surface": "ESO-managed Secret key (Merge into existing Secret)", - "namespace": "sso", - "secret": "identity-provisioner-ldap", - "key": "password", - "service_account": "net-kingdom-svc-provisioner-bind-eso", - "reader": "identity-provisioner Deployment in sso (existing secretKeyRef, unchanged); no agent credential delivery", - "manifest": "net-kingdom: sso-mfa/k8s/identity-provisioner/bind-eso.yaml", - "cluster_uid": "a553c742-0115-43d4-99a4-a5ca56fe0786" - }, - "risk": { - "classification": "medium", - "notes": [ - "svc-provisioner is a member of lldap_admin (founder decision 2026-10-28, exception recorded in the Service Identity standard): a leak grants directory administration. Treat the path as high-value even though the lane itself is a single-field read.", - "Initial KV write is CAS=0 with the value already live in the Secret and the founder's custody; no rotation happens in this request. An existing different KV value refuses.", - "ESO uses creationPolicy Merge so the existing Secret (created by apply-service-secrets.py) keeps its username key and owner; only password is projected. deletionPolicy Retain: removing the ExternalSecret leaves the working Secret in place.", - "Coding agents are fenced from the data and metadata paths in agent-high-risk-boundary before the first write.", - "Node root, ESO administration and platform-admin remain inside this credential boundary." - ] - }, - "verification": { - "positive": [ - "Exact policy, role and bound claims read back; native reader login as the ESO ServiceAccount gets only this policy with a lease of at most 15m", - "KV value equals the live Secret password before ESO is applied (setup) and after ESO sync (verify), compared in memory only", - "ExternalSecret Ready/SecretSynced; identity-provisioner readiness (includes directory login) stays Ready after a restart" - ], - "negative": [ - "Reader cannot read metadata, a sibling path, the other directory-bind paths or create tokens", - "Wrong ServiceAccount, wrong audience and wrong namespace logins are denied", - "Coding-agent boundary denies data and metadata of the path" - ], - "activation_conditions": [ - "Explicit platform-owner and net-kingdom-owner approval of this exact request (sha256-bound by the setup tool).", - "Attended platform-admin (aal2) session for setup; the founder runs it, value read from the decrypted custody copy without display.", - "Policy, role and KV in place and equal to live before the ExternalSecret is applied.", - "Positive and negative results recorded in value-free receipts." - ] - } -} +id: CCR-2026-0052 +kind: credential-change-request +schema_version: 1 +request_type: workload-kv-read +title: NetKingdom identity-provisioner directory bind (svc-provisioner) delivery +status: approved +created: '2026-10-30' +updated: '2026-10-30' +requester: + agent: claude-code + reason: 'NK-WP-0056-T04 pilot: move the first LLDAP service bind out of the founder''s + personal SOPS custody into platform custody, so later rotations need neither a + decrypted custody copy nor a person handling the value. svc-provisioner is the + simplest consumer: its own Secret, two keys, no embedded config.' +review: + required: true + required_approvers: + - platform-owner + - net-kingdom-owner + comments: + - at: '2026-10-30T22:04:42+00:00' + reviewer: User (platform-owner) + decision: approved + comment: 'Approved as proposed: read-only svc-provisioner lane, CAS=0 from live + value, ESO Merge of password only.' + - at: '2026-10-30T22:04:43+00:00' + reviewer: User (net-kingdom-owner) + decision: approved + comment: Approved as proposed for NK-WP-0056-T04 pilot. + - at: '2026-10-30T22:06:09+00:00' + reviewer: User (platform-owner) + decision: binding_confirmed + comment: 'Binding confirmed: ServiceAccount net-kingdom-svc-provisioner-bind-eso + in namespace sso only, audience openbao, as declared in net-kingdom sso-mfa/k8s/identity-provisioner/bind-eso.yaml.' +target: + domain: infotech + tenant: platform + workload: net-kingdom-identity-provisioner + environment: production + purpose: Hold the svc-provisioner LLDAP bind password in platform custody and project + only that value into the existing Secret sso/identity-provisioner-ldap; no ld-admin, + admin or other service bind +openbao: + mount: platform + kv_path: platform/workloads/net-kingdom/directory-binds/svc-provisioner + fields: + - LDAP_BIND_PASSWORD + policy_name: net-kingdom-svc-provisioner-bind-eso + policy_file: openbao/policies/net-kingdom-svc-provisioner-bind-eso.hcl + metadata_read: false + token_self_lifecycle: true + auth: + method: kubernetes + mount: kubernetes + role: net-kingdom-svc-provisioner-bind-eso + audience: openbao + ttl: 15m + token_max_ttl: 15m + token_explicit_max_ttl: 15m + token_no_default_policy: true + policies: + - net-kingdom-svc-provisioner-bind-eso + bound_claims: + service_account_names: + - net-kingdom-svc-provisioner-bind-eso + service_account_namespaces: + - sso + bound_claims_confirmed: true +access_frontdoor: + type: platform-owner + catalog_id: net-kingdom-svc-provisioner-bind + readiness: pending-review + resolvable: false +lifecycle: + deactivate: Delete the ExternalSecret (deletionPolicy Retain keeps the working Secret), + then withdraw the role and policy; the KV entry stays as custody until the founder's + copy is confirmed current. + rotate: Change the svc-provisioner password in LLDAP and write the new value as + the next KV version with CAS on the current version; ESO projects it and the provisioner + restarts. Until NK-WP-0056 executors exist this is founder-run. + compromised: Disable or reset svc-provisioner in LLDAP first (it is in lldap_admin), + then rotate as above and review directory changes made under that account; fence + the reader role if its boundary is in doubt. +delivery: + surface: ESO-managed Secret key (Merge into existing Secret) + namespace: sso + secret: identity-provisioner-ldap + key: password + service_account: net-kingdom-svc-provisioner-bind-eso + reader: identity-provisioner Deployment in sso (existing secretKeyRef, unchanged); + no agent credential delivery + manifest: 'net-kingdom: sso-mfa/k8s/identity-provisioner/bind-eso.yaml' + cluster_uid: a553c742-0115-43d4-99a4-a5ca56fe0786 +risk: + classification: medium + notes: + - 'svc-provisioner is a member of lldap_admin (founder decision 2026-10-28, exception + recorded in the Service Identity standard): a leak grants directory administration. + Treat the path as high-value even though the lane itself is a single-field read.' + - Initial KV write is CAS=0 with the value already live in the Secret and the founder's + custody; no rotation happens in this request. An existing different KV value refuses. + - 'ESO uses creationPolicy Merge so the existing Secret (created by apply-service-secrets.py) + keeps its username key and owner; only password is projected. deletionPolicy Retain: + removing the ExternalSecret leaves the working Secret in place.' + - Coding agents are fenced from the data and metadata paths in agent-high-risk-boundary + before the first write. + - Node root, ESO administration and platform-admin remain inside this credential + boundary. +verification: + positive: + - Exact policy, role and bound claims read back; native reader login as the ESO + ServiceAccount gets only this policy with a lease of at most 15m + - KV value equals the live Secret password before ESO is applied (setup) and after + ESO sync (verify), compared in memory only + - ExternalSecret Ready/SecretSynced; identity-provisioner readiness (includes directory + login) stays Ready after a restart + negative: + - Reader cannot read metadata, a sibling path, the other directory-bind paths or + create tokens + - Wrong ServiceAccount, wrong audience and wrong namespace logins are denied + - Coding-agent boundary denies data and metadata of the path + activation_conditions: + - Explicit platform-owner and net-kingdom-owner approval of this exact request (sha256-bound + by the setup tool). + - Attended platform-admin (aal2) session for setup; the founder runs it, value read + from the decrypted custody copy without display. + - Policy, role and KV in place and equal to live before the ExternalSecret is applied. + - Positive and negative results recorded in value-free receipts.