railiance-platform/credential-change-requests/CCR-2026-0054-net-kingdom-keycape-bind.yaml
codex 674a7132d0
All checks were successful
CCR intake gate / gate (push) Successful in 1m9s
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
CCR-2026-0054: verified (setup, ESO delivery, env rollout, clear-password and verify passed; net-kingdom a656739)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 896183@bnt-lap001
Assistant-Session: 3a18c01a-3205-4d02-94db-9efff25649a2
2026-10-31 10:52:22 +01:00

148 lines
6.7 KiB
YAML

id: CCR-2026-0054
kind: credential-change-request
schema_version: 1
request_type: workload-kv-read
title: NetKingdom KeyCape directory bind (svc-keycape) delivery
status: verified
created: '2026-10-31'
updated: '2026-10-31'
requester:
agent: claude-code
reason: 'NK-WP-0056-T04, third lane (after CCR-2026-0052 svc-provisioner and CCR-2026-0053
svc-authelia): move the svc-keycape LLDAP bind out of the founder''s personal
SOPS custody into platform custody. KeyCape reads it from KEYCAPE_LLDAP_BIND_PW
(key-cape KEY-WP-0046), so ESO owns a dedicated Secret instead of one field inside
keycape-config.'
review:
required: true
required_approvers:
- platform-owner
- net-kingdom-owner
comments:
- at: '2026-10-31T09:36:13+00:00'
reviewer: platform-owner
decision: approved
comment: 'Approved as proposed: read-only svc-keycape lane, CAS=0 from live value,
ESO-owned dedicated Secret keycape-lldap-bind.'
- at: '2026-10-31T09:36:25+00:00'
reviewer: net-kingdom-owner
decision: approved
comment: Approved as proposed for NK-WP-0056-T04, including the KeyCape image
main-e2b5fa1.
- at: '2026-10-31T09:36:35+00:00'
reviewer: platform-owner
decision: binding_confirmed
comment: 'Binding confirmed: ServiceAccount net-kingdom-svc-keycape-bind-eso in
namespace sso only, audience openbao, as declared in net-kingdom sso-mfa/k8s/keycape/bind-eso.yaml.'
target:
domain: infotech
tenant: platform
workload: net-kingdom-keycape
environment: production
purpose: Hold the svc-keycape LLDAP bind password in platform custody and deliver
it as the dedicated Secret sso/keycape-lldap-bind (key password), read by KeyCape
as KEYCAPE_LLDAP_BIND_PW; no signing key, client or other keycape-config value,
no ld-admin, admin or other service bind
openbao:
mount: platform
kv_path: platform/workloads/net-kingdom/directory-binds/svc-keycape
fields:
- LDAP_BIND_PASSWORD
policy_name: net-kingdom-svc-keycape-bind-eso
policy_file: openbao/policies/net-kingdom-svc-keycape-bind-eso.hcl
metadata_read: false
token_self_lifecycle: true
auth:
method: kubernetes
mount: kubernetes
role: net-kingdom-svc-keycape-bind-eso
audience: openbao
ttl: 15m
token_max_ttl: 15m
token_explicit_max_ttl: 15m
token_no_default_policy: true
policies:
- net-kingdom-svc-keycape-bind-eso
bound_claims:
service_account_names:
- net-kingdom-svc-keycape-bind-eso
service_account_namespaces:
- sso
bound_claims_confirmed: true
access_frontdoor:
type: platform-owner
catalog_id: net-kingdom-svc-keycape-bind
readiness: pending-review
resolvable: false
lifecycle:
deactivate: Restore bindPW in keycape-config (directory-bind-rollout.py --operation
switch), remove the KEYCAPE_LLDAP_BIND_PW env from the Deployment, then delete
the ExternalSecret (deletionPolicy Retain keeps the Secret) and withdraw the role
and policy.
rotate: Change the svc-keycape password in LLDAP and write the new value as the
next KV version with CAS on the current version; ESO projects it and KeyCape is
restarted. Only after bindPW is cleared from keycape-config, because KeyCape refuses
differing values. Until NK-WP-0056 executors exist this is founder-run.
compromised: Reset svc-keycape in LLDAP first (read-only bind, lldap_strict_readonly),
then rotate as above; fence the reader role if its boundary is in doubt.
delivery:
surface: ESO-owned Secret (creationPolicy Owner, new dedicated Secret)
namespace: sso
secret: keycape-lldap-bind
key: password
service_account: net-kingdom-svc-keycape-bind-eso
reader: KeyCape Deployment in sso, env KEYCAPE_LLDAP_BIND_PW from secretKeyRef keycape-lldap-bind/password
(image with key-cape KEY-WP-0046); no agent credential delivery
manifest: 'net-kingdom: sso-mfa/k8s/keycape/bind-eso.yaml'
cluster_uid: a553c742-0115-43d4-99a4-a5ca56fe0786
risk:
classification: medium
notes:
- svc-keycape is a read-only directory bind (lldap_strict_readonly); a leak exposes
directory attributes (users, groups, emails), not write access.
- keycape-config also holds the signing key and client configuration; this request
delivers none of it, and setup compares only lldap.bindDN/bindPW in memory.
- Initial KV write is CAS=0 with the value already live in keycape-config and the
founder's custody; no rotation happens in this request. An existing different
KV value refuses.
- Setup refuses unless the live config binds uid=svc-keycape. KeyCape refuses to
start if KEYCAPE_LLDAP_BIND_PW and bindPW differ, so a wrong delivery cannot be
used silently.
- 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 keycape-config bindPW before ESO is applied (setup),
and the delivered Secret (and bindPW while present) after ESO sync (verify), compared
in memory only
- ExternalSecret Ready/SecretSynced; KeyCape with the env rolls out Ready and a
portal login works, again after bindPW is cleared from keycape-config
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;
the KeyCape image with KEY-WP-0046 deployed before the env is added.
- Positive and negative results recorded in value-free receipts.
evidence:
- at: '2026-10-31T09:52:22+00:00'
actor: founder (attended), claude-code guiding
kind: verifier_custody_and_rollout
result: passed
details:
- '2026-10-31: bind-lane.py setup (live keycape-config binds svc-keycape, custody
equal to bindPW, coding agents fenced, KV v1 CAS=0, policy+role) and verify
passed with env and config, then again env-only after directory-bind-rollout.py
clear-password; KeyCape main-e2b5fa1 (KEY-WP-0046) rolled out with KEYCAPE_LLDAP_BIND_PW;
admin signed in with OTP before and after. Evidence: net-kingdom docs/evidence/2026-10-31-nk56-svc-keycape-bind/
(a656739).'