NK-WP-0054-T05: privacyIDEA resolver still bound as admin after step 8; fixed live, runbook check added

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 673304@bnt-lap001
Assistant-Session: 959b12c7-cf2e-440b-a60d-91229cc9e96e
This commit is contained in:
tegwick 2026-10-30 21:18:15 +01:00
parent 103c2c1505
commit 08087ec5ac
2 changed files with 17 additions and 2 deletions

View file

@ -36,5 +36,15 @@ UTC, agent (Claude Code) guiding. All receipts are value-free (`values_recorded:
4. Rollouts of identity-provisioner, KeyCape and LLDAP use `Recreate`: each had a short outage of
about 30 s.
5. **privacyIDEA resolver was still bound as `admin` (found 2026-10-30 evening).** After step 10
every OTP check failed: KeyCape logged `mfa_failed` (`openbao-admin`) and `mfa_check_error`
(`user-engine-portal`); privacyIDEA logged `LDAP Bind unsuccessful: invalidCredentials (49)` from
19:00:10 UTC, last successful lookup 18:49:30 UTC, step 10 at 18:53 UTC. Founder found Bind DN
`uid=admin,…` on `lldap-coulomb` in the privacyIDEA UI, set `uid=svc-privacyidea,…` with the custody
`LLDAP_SVC_PRIVACYIDEA_PASS`, and **Test LDAP Resolver** passed. No repository tool rewrites the
resolver, so step 8's apply most likely did not take effect; its OTP check passed only because the
old shared password was still valid. Runbook step 8 now requires the resolver Bind DN and test, and
step 10 a fresh OTP sign-in.
Closing condition still open: the restore drill on the first backup generation after this run
(NK-WP-0053 stages 2-5, T17/T19 under the new accounts).

View file

@ -136,7 +136,11 @@ portal or the OpenBao UI through `openbao-ui-railiance01`). Rollback: the same t
python3 sso-mfa/k8s/privacyidea/realm_bootstrap.py "$CUSTODY" --switch-bind # preview
python3 sso-mfa/k8s/privacyidea/realm_bootstrap.py "$CUSTODY" --switch-bind --apply
```
Expect `actions: ["switch-bind"]`, one write. Check: a sign-in with OTP (step 6 again). There is no
Expect `actions: ["switch-bind"]`, one write; a `"result":"unverified"` line on stderr means it did not
apply. Check: as `pi-admin`, Config → Users → `lldap-coulomb` shows Bind DN
`uid=svc-privacyidea,…` and **Test LDAP Resolver** passes. An OTP sign-in alone does not prove the
switch: until step 10 retires the old password a resolver still bound as `admin` keeps working
(2026-10-30 incident, `docs/evidence/2026-10-30-nk54-bind-split/README.md`). There is no
automated rollback; the old bind is the `admin` account, which still works, so the attended repair
(`--attended`, prompts) can set it back if needed.
@ -157,7 +161,8 @@ Sign in to the LLDAP UI as `admin`, change your password, store it in your passw
python3 sso-mfa/k8s/lldap/bind-split.py verify --endpoint https://lldap.coulomb.social "$CUSTODY" --old-admin-retired --receipt ~/nk54/10-verify.json
```
It prompts for the new `admin` password, then the old shared one, and requires that the old one is
refused. `"verdict": "pass"` ends the live run.
refused. `"verdict": "pass"` ends the live run once a fresh OTP sign-in still succeeds afterwards
(this is the first check that no consumer still binds with the old shared password).
## 11. Afterwards