diff --git a/credential-change-requests/CCR-2026-0055-net-kingdom-privacyidea-bind.yaml b/credential-change-requests/CCR-2026-0055-net-kingdom-privacyidea-bind.yaml index ee5fcff..5f0593d 100644 --- a/credential-change-requests/CCR-2026-0055-net-kingdom-privacyidea-bind.yaml +++ b/credential-change-requests/CCR-2026-0055-net-kingdom-privacyidea-bind.yaml @@ -11,8 +11,9 @@ requester: reason: 'NK-WP-0056-T04, fourth lane (after CCR-2026-0052/0053/0054): move the svc-privacyidea LLDAP bind out of the founder''s personal SOPS custody into platform custody. privacyIDEA stores the resolver password encrypted in its own database and accepts - it only through pi-admin with a fresh MFA code, so no workload reads it: delivery - is an attended write-through.' + it only through its pi-admin API; an unattended writer would need pi-admin''s + password standing in the cluster, so no workload reads it: delivery is an attended + write-through.' review: required: true required_approvers: @@ -48,7 +49,8 @@ lifecycle: current; privacyIDEA keeps its stored resolver password. rotate: Change the svc-privacyidea password in LLDAP, write the next KV version with CAS on the current version, then run realm_bootstrap.py --rotate-bind --from-openbao - (pi-admin + MFA) and verify with an OTP login. Founder-run. + (attended pi-admin; --verify-user MFA login required) and verify with an OTP login. + Founder-run. compromised: Reset svc-privacyidea in LLDAP first (read-only bind, lldap_strict_readonly), then rotate as above. delivery: @@ -57,8 +59,8 @@ delivery: target: resolver BINDPW, stored encrypted in the privacyIDEA database procedure: net-kingdom sso-mfa/k8s/privacyidea/realm_bootstrap.py --rotate-bind --from-openbao - gate: attended platform-admin (aal2) OpenBao session and pi-admin with a fresh MFA - code + gate: attended platform-admin (aal2) OpenBao session, attended pi-admin password, + and a fresh MFA login through the resolver (--verify-user) that proves the write risk: classification: medium notes: @@ -82,6 +84,7 @@ verification: - Explicit platform-owner and net-kingdom-owner approval of this exact request (sha256-bound by the setup tool). - Attended platform-admin (aal2) session; the founder runs setup with the decrypted - custody copy and the write-through with pi-admin MFA. + custody copy and the write-through with pi-admin and an MFA login through the + resolver. - Positive and negative results recorded in value-free receipts. evidence: [] diff --git a/docs/credential-lane-designs/attended-service-credential-delivery.md b/docs/credential-lane-designs/attended-service-credential-delivery.md index 3800a24..f3bb2cb 100644 --- a/docs/credential-lane-designs/attended-service-credential-delivery.md +++ b/docs/credential-lane-designs/attended-service-credential-delivery.md @@ -4,18 +4,19 @@ Request type `attended-service-credential-delivery` (`scripts/attended_service_d CCR-2026-0055 (NetKingdom `svc-privacyidea`, NK-WP-0056-T04). Some services keep a credential in their own encrypted store and accept it only through an administrator API -that requires a person's MFA. privacyIDEA's LDAP resolver is one: its `BINDPW` lives encrypted in the -privacyIDEA database and only `pi-admin` with a fresh code may change it. ESO cannot deliver such a value, and an -unattended job would need an administrator credential without MFA. +that a person operates. privacyIDEA's LDAP resolver is one: its `BINDPW` lives encrypted in the privacyIDEA +database and only the `pi-admin` API may change it. ESO cannot deliver such a value, and an unattended job would +need the administrator password standing in the cluster. The contract therefore holds the value in OpenBao and nothing else: - `openbao.auth` is the attended `platform-admin` OIDC session on `netkingdom`; `runtime_access: false`; `initial_cas: 0`. No policy, auth role, ESO object or other access may be declared. - The runtime frontdoor stays disabled (`access_frontdoor.resolvable: false`). -- `delivery` names the service, the target inside it, the owner's procedure and the gate (the person's MFA). +- `delivery` names the service, the target inside it, the owner's procedure and the gate (the attended person and + the proof they run). - Approval follows `review.required_approvers`; from `applied` onward every listed role must have approved. The owner's procedure reads the value in memory under the attended session and writes it into the service; the -person's MFA remains the gate. A rotation needs no decrypted custody copy. Modelled on +person runs it and proves the write with an MFA login through the service. A rotation needs no decrypted custody copy. Modelled on `attended-host-key-delivery` (CCR-2026-0028), which delivers to a host file instead of a service. diff --git a/scripts/attended_service_delivery.py b/scripts/attended_service_delivery.py index 3431986..3643bf0 100644 --- a/scripts/attended_service_delivery.py +++ b/scripts/attended_service_delivery.py @@ -2,8 +2,8 @@ """attended-service-credential-delivery CCRs: a value in platform custody that no workload reads. NetKingdom NK-WP-0056-T04 (svc-privacyidea). Some services keep a credential in -their own encrypted store and accept it only through an administrator API that -requires a person's MFA (privacyIDEA's LDAP resolver bind). The value is held in +their own encrypted store and accept it only through an administrator API +(privacyIDEA's LDAP resolver bind) that a person operates. The value is held in OpenBao, written once with CAS=0 from the attended platform-admin session, and delivered by an attended procedure that reads it in memory and writes it into the service. No Kubernetes or workload auth role, policy or ESO object exists,