Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a07ff8-19d0-7820-b4d0-1353833cb7fc
4.4 KiB
Repair the identity provisioner's stored LLDAP credential
NK-WP-0036-T04, 2026-09-11. Attended live repair completed and independently verified.
The native User Engine Create login request reached identity-provisioner, whose LLDAP admin login returned HTTP 401 before identity creation. Reloading the existing lldap-secrets reference did not fix it. The tenant and user-domain records are independent and remain intact. Root portal login is working.
This procedure performs an attended consumer-reference reconciliation. It does not
rotate the LLDAP account, change signing keys, restore an exposed predecessor,
read a Secret payload, or rebuild KeyCape's configuration. The operator must
supply the currently working LLDAP admin password from existing custody through
a hidden terminal prompt. The platform-root portal password is a different input.
No value belongs in chat, shell arguments or work records. Do not fetch values
through the unresolved warden pointer lane or a Kubernetes Secret export.
The owner contract is warden route net-kingdom-lldap-bind-credential, with railiance-platform custody and the NetKingdom attended procedure. Operator acceptance of this narrow repair is required before its explicit apply command; the older full-bundle incident approval is not reused. If the current working credential is unavailable, stop at the custody-owner recovery boundary.
The helper is sso-mfa/k8s/lldap/identity-provisioner-reconcile.py. Run inspect first; it emits only the exact Secret UID/resourceVersion and rejects controller ownership or the wrong cluster:
python3 sso-mfa/k8s/lldap/identity-provisioner-reconcile.py inspect
python3 sso-mfa/k8s/lldap/identity-provisioner-reconcile.py check
check requires an interactive terminal and a hidden current-password prompt.
It authenticates the existing admin against the pinned in-cluster LLDAP URL and
performs a directory read. It changes no provider or consumer state.
Use the current UID/resourceVersion from inspect. The following command records the accepted and completed 2026-09-11 execution; its old resourceVersion will now be refused:
python3 sso-mfa/k8s/lldap/identity-provisioner-reconcile.py apply --expected-uid c6a9e6be-5bb5-47e6-9faa-06b8d72afec3 --expected-resource-version 51345775
The helper validates the candidate against the provider before any write, server dry-runs a JSON patch, then updates only lldap-secrets/LLDAP_LDAP_USER_PASS with UID/resourceVersion tests. Values travel only in child stdin/process memory; there is no temporary credential file, Secret export or full-manifest output. It restarts only identity-provisioner, waits for readiness and verifies the reloaded credential through the consumer. Failure after a successful field update is reported as incomplete verification; the rejected old value is never restored. Other login services and the LLDAP provider are not restarted.
Seven synthetic tests cover exact patch scope, stale metadata and controller refusal, candidate rejection before writes, check-only behavior, stdin-only value handling, redaction of child errors and the apply/reload/proof sequence. The operator subsequently supplied the working password only through the hidden terminal prompt and completed apply. Its sanitized receipt reports result reconciled, provider_login true, consumer_login true, and provider_password_changed false. Secret UID is unchanged; resourceVersion is now 60026132. Independent verification from the restarted consumer confirms directory authentication plus a directory read. Deployment readiness is 1/1, with its existing image digest 5b460f5ca9e329e287939f4707a2bb8d5674b7f94e24cfb5f6d790f54c3f8d06. No native user/password-setup completion is inferred from these service checks.
After success, retry Create login only for the existing intended user, inspect the returned password-setup page and record the native identity linkage. Password setup links are private, short-lived and must not enter evidence. User Engine's display name is not necessarily its directory username: the current provider derives a name from email unless preferred_username is sent. Keep the requested demo login-name mapping explicit before provisioning.
Follow-up remains necessary for credential custody/publication and a functional provisioner preflight: the current /healthz confirms process health while the directory connection is broken. The HTTP handler also fails to catch the upstream HTTPError. These are tracked in NK-WP-0036-T05.