docs(nk-wp-0033): record the 2026-08-27 attended session findings
platform-root login is restored and the resolver holds the current bind
credential, so T04's outstanding reconciliation is done. No green receipt
yet — the run of record is a FAIL at resolver-lookup, and T05 stays open.
Records four things the session established:
- the predecessor is dead, observed twice by hand, but not by receipt;
- the value is unrecoverable, because no KeePassXC database has ever
existed despite platform-root-custody.md naming a safe entry, and the
only copy lived in a Firefox entry overwritten during the session.
T04 replaced the credential with no step to update operator custody —
the root cause of the whole session;
- the reconciliation script had never completed a run (4a38511);
- verify-t06.sh reported success at bootstrap against a resolver that
was misconfigured and a reconciliation path that could not execute.
That blind spot is open and is the finding worth acting on.
Also corrects the record: the stale bind credential was real but did not
cause the lookup failure. The HTTP 400 was our own request builder.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 3377672@bnt-lap001
Assistant-Session: 15463ccf-238f-4e13-b163-93aa25c6d166
This commit is contained in:
parent
4a38511d11
commit
0f5f56275c
2 changed files with 75 additions and 1 deletions
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Incident: `KEYCAPE-EXPOSURE-20260823-01`
|
||||
Workplan: `NK-WP-0033`
|
||||
NetKingdom procedure: `sso-mfa/k8s/privacyidea/reconcile-lldap-resolver-live.sh` (revision pinned by the approved checkout)
|
||||
NetKingdom procedure: `sso-mfa/k8s/privacyidea/reconcile-lldap-resolver-live.sh` (repaired 2026-08-27 in `4a38511`; the previously pinned revision could not complete a run — see NK-WP-0033 T05)
|
||||
Platform recovery contract: railiance-platform `453fed3`
|
||||
Owner cutover receipt: State Hub message `45b236c8-052f-43d3-a472-44f8e9694da2`
|
||||
|
||||
|
|
@ -99,3 +99,27 @@ T03 may move to done only after the helper run and cleanup receipt are recorded
|
|||
by the attended operator. T05 may move to done only after the resolver’s
|
||||
replacement success, predecessor denial, owner cutover receipt, and all
|
||||
residual limitations are recorded as sanitized evidence.
|
||||
|
||||
## Revision note — 2026-08-27
|
||||
|
||||
The pinned revision of `reconcile-lldap-resolver-live.sh` had never completed a
|
||||
run. Four defects were found by running it and are fixed in `4a38511`; see
|
||||
`NK-WP-0033` T05 for the full findings. Two change how this procedure is
|
||||
invoked:
|
||||
|
||||
- `--predecessor-unavailable` — use when the exposed predecessor cannot be
|
||||
produced. The denial bind is not attempted and the receipt records
|
||||
`predecessor denial=NOT-PROVEN`. Do **not** type a placeholder at the
|
||||
predecessor prompt instead: a wrong value also fails the bind, and the run
|
||||
records it as a *passing* denial proof — a receipt asserting a test that never
|
||||
ran.
|
||||
- `--note TEXT` — operator context carried verbatim in the receipt line, so a
|
||||
claim and its caveat travel together. One line, 200 characters, no
|
||||
credentials.
|
||||
|
||||
`TIMEOUT`, `CACHE_TIMEOUT` and `SIZELIMIT` are now sent with the resolver body
|
||||
(default 5 / 120 / 500, overridable via the matching `LDAP_*` environment
|
||||
variables). Before this fix, `--apply` dropped them, because a resolver write
|
||||
replaces the whole object. A resolver with them unset still resolves users, but
|
||||
the WebUI refuses to save or test it — so a hand repair was silently reverted by
|
||||
the next run.
|
||||
|
|
|
|||
|
|
@ -168,3 +168,53 @@ rollout status, positive authentication/MFA outcomes, predecessor rejection or
|
|||
expiry, cleanup receipts, and residual limitations. Close the incident only
|
||||
after all four credential classes have an authoritative disposition and no
|
||||
temporary plaintext or stale bundle remains.
|
||||
|
||||
### Attended session 2026-08-27 — findings
|
||||
|
||||
The resolver reconciliation was attempted and the operator's `platform-root`
|
||||
login is restored. `bao login -method=oidc` succeeds, and
|
||||
`GET /user/?realm=coulomb&username=platform-root` returns the record. **No
|
||||
green receipt has been produced yet**; the run below is the state of record.
|
||||
|
||||
**LLDAP bind credential — reconciled.** The `--apply` run wrote the current
|
||||
`LLDAP_LDAP_USER_PASS` into resolver `lldap-coulomb`, and the replacement
|
||||
authenticated against LLDAP in the same run. The resolver had been holding the
|
||||
pre-cutover value since 2026-08-23, which is what T04 left outstanding.
|
||||
|
||||
**Predecessor disposition — NOT PROVEN by receipt; observed twice by hand.**
|
||||
The exposed value is dead: the operator was locked out of the LLDAP WebUI on
|
||||
2026-08-27 after logging out of a persisted session, and the `--check` run the
|
||||
same day passed `predecessor-denial` with the real value before it was lost.
|
||||
Neither observation is carried by an emitted receipt. The value is
|
||||
unrecoverable — see the custody gap below.
|
||||
|
||||
**Custody gap — the actual root cause of this session.** T04 replaced the
|
||||
credential without a step that updates operator custody, and there was no
|
||||
custody store to update it into. `platform-root-custody.md` names a password
|
||||
safe entry `net-kingdom/LLDAP/admin`; **no KeePassXC database exists** and never
|
||||
did. The value lived only in a Firefox password-manager entry dated 2026-06-28,
|
||||
which was overwritten with the replacement on 2026-08-27, destroying the
|
||||
predecessor. Any rotation runbook that does not name where the outgoing value is
|
||||
retained will lose it the same way.
|
||||
|
||||
**The reconciliation script had never completed a run.** Four defects, fixed in
|
||||
`4a38511`: `Content-Type` on bodyless GETs (HTTP 400 on every GET), `/user/`
|
||||
parsed as a dict when it returns a list (traceback past the except clause),
|
||||
resolver writes dropping `TIMEOUT`/`CACHE_TIMEOUT`/`SIZELIMIT` (silently
|
||||
un-repairing a hand-fixed resolver), and no way to declare an unavailable
|
||||
predecessor (forcing a placeholder that records a *passing* denial proof).
|
||||
|
||||
**Verification blind spot — open.** `verify-t06.sh` reported success at
|
||||
bootstrap against a resolver created without the three tuning parameters, by a
|
||||
reconciliation path that could not execute. A verification that passes while its
|
||||
subject cannot run is not verification. This is the finding worth acting on
|
||||
beyond the four fixes, and it is not yet addressed.
|
||||
|
||||
**Diagnosis correction.** The "stale bind credential" reading in T04 was real but
|
||||
was not what blocked the resolver lookup; the HTTP 400 was our own request
|
||||
builder throughout. The two faults were independent and looked like one, which
|
||||
is why each partial fix appeared to change nothing.
|
||||
|
||||
Remaining before T05 can close: a green receipt from the repaired script, and a
|
||||
ruling on whether a predecessor disposition observed but not receipted is an
|
||||
acceptable close for this incident.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue