From ae55499fcb3bd08e40d0181602f0215ce87adefa Mon Sep 17 00:00:00 2001 From: tegwick Date: Thu, 5 Nov 2026 22:42:33 +0100 Subject: [PATCH] NK-WP-0058-T11 done: OpenBao audit shows no use of the write role during the overnight window Founder-run, value-free audit read: no login, no write-policy request and no failed kubernetes login from 23:33:29Z to the 08:26:56Z close; all logins are the attended runs, diagnostics and the pilot (positive control). Pilot README times corrected from the audit log. Co-Authored-By: Claude Opus 5.5 Assistant: claude-code Assistant-Model: opus Assistant-Process: 943911@bnt-lap001 Assistant-Session: fc322940-1c8e-4bed-ab39-86cec99f23a0 --- WORK-RECORDS.md | 2 +- .../2026-11-05-nk56-t06-pilot/README.md | 10 +- .../01-window-close.json | 9 ++ .../02-write-role-audit.json | 90 ++++++++++++++ .../04-write-role-audit.json | 116 ++++++++++++++++++ .../README.md | 41 +++++++ ...K-WP-0058-bounded-execution-operability.md | 20 ++- 7 files changed, 282 insertions(+), 6 deletions(-) create mode 100644 docs/evidence/2026-11-05-nk58-t11-write-role-check/01-window-close.json create mode 100644 docs/evidence/2026-11-05-nk58-t11-write-role-check/02-write-role-audit.json create mode 100644 docs/evidence/2026-11-05-nk58-t11-write-role-check/04-write-role-audit.json create mode 100644 docs/evidence/2026-11-05-nk58-t11-write-role-check/README.md diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index 99787bc..c08e4af 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -380,7 +380,7 @@ | task | NK-WP-0058-T08 | todo | — | workplans/NK-WP-0058-bounded-execution-operability.md | | task | NK-WP-0058-T09 | todo | — | workplans/NK-WP-0058-bounded-execution-operability.md | | task | NK-WP-0058-T10 | progress | — | workplans/NK-WP-0058-bounded-execution-operability.md | -| task | NK-WP-0058-T11 | todo | — | workplans/NK-WP-0058-bounded-execution-operability.md | +| task | NK-WP-0058-T11 | done | — | workplans/NK-WP-0058-bounded-execution-operability.md | | intake | NK-IN-0001 | closed | blue | docs/intakes/activity-core-ops-sso-operators.md | | intake | NK-IN-0002 | closed | blue | docs/intakes/activity-core-ops-sso-operators.md | | intake | NET-IN-0001 | open | — | intakes/intakes.md | diff --git a/docs/evidence/2026-11-05-nk56-t06-pilot/README.md b/docs/evidence/2026-11-05-nk56-t06-pilot/README.md index 9426727..71176cf 100644 --- a/docs/evidence/2026-11-05-nk56-t06-pilot/README.md +++ b/docs/evidence/2026-11-05-nk56-t06-pilot/README.md @@ -18,16 +18,18 @@ ## Incident: write role open overnight -The last diagnostic of the first attempt opened BEA-2026-0002's window at about 23:20Z +The last diagnostic of the first attempt opened BEA-2026-0002's window at 23:16:24Z (`2026-11-04-nk56-t06-pilot/07-window-open-diag.json`). The final close never ran, so the role stayed until -08:24Z, when `09-window-close-late.json` closed it. +08:26:56Z, when `09-window-close-late.json` closed it. Times are from OpenBao's audit log (NK-WP-0058-T11); an +earlier version of this note said about 23:20Z and 08:24Z. - **Exposure:** only `sso/nk-bind-executor` (audience `openbao`) could log in, with tokens of at most 15 minutes, and no executor Job or diagnostic ran in that time. - **Remedy:** `sso-mfa/k8s/bounded-executor/pilot-run.sh` now opens the window, runs, and closes it from an EXIT trap, so a failed or interrupted run never leaves it open (`e181fb0`, wait fixed in `216a5db`). -- **Not yet done:** confirming "no login" from OpenBao's audit log. That would need the audit device and a reviewed - read, and it remains open. +- **Audit check, done 2026-11-05 (NK-WP-0058-T11):** OpenBao's audit log shows no login with the write role and no + request with its policy from 23:33:29Z (the last diagnostic login plus the 15-minute token lifetime) until the + close. See [`../2026-11-05-nk58-t11-write-role-check/`](../2026-11-05-nk58-t11-write-role-check/README.md). ## Still open for oidc-service-client diff --git a/docs/evidence/2026-11-05-nk58-t11-write-role-check/01-window-close.json b/docs/evidence/2026-11-05-nk58-t11-write-role-check/01-window-close.json new file mode 100644 index 0000000..8576b13 --- /dev/null +++ b/docs/evidence/2026-11-05-nk58-t11-write-role-check/01-window-close.json @@ -0,0 +1,9 @@ +{ + "action": "window-close", + "admission": "BEA-2026-0003", + "phase": "identity", + "reason": "LaneError", + "source_sha256": "9cbd76d6999b765bacf111a1318860403b242fbf52f5aa4a4ead82d031376828", + "status": "failed", + "values_recorded": false +} diff --git a/docs/evidence/2026-11-05-nk58-t11-write-role-check/02-write-role-audit.json b/docs/evidence/2026-11-05-nk58-t11-write-role-check/02-write-role-audit.json new file mode 100644 index 0000000..bbc1245 --- /dev/null +++ b/docs/evidence/2026-11-05-nk58-t11-write-role-check/02-write-role-audit.json @@ -0,0 +1,90 @@ +{ + "action": "write-role-audit", + "check": { + "from": "2026-11-04T22:39:00.000000Z", + "intervals_overlapping": 4, + "log_covers_check": true, + "logins_in_check": 4, + "no_login_in_check": false, + "policy_requests_in_check": 4, + "to": "2026-11-05T08:25:00.000000Z" + }, + "intervals": [ + { + "closed": null, + "failed_k8s_logins": 0, + "login_service_accounts": [], + "login_times": [], + "logins": 0, + "opened": null, + "orphan": true, + "policy_requests": 1 + }, + { + "closed": "2026-11-04T23:03:22.057510Z", + "failed_k8s_logins": 0, + "login_service_accounts": [ + "sso/nk-bind-executor" + ], + "login_times": [ + "2026-11-04T23:02:46.117361Z" + ], + "logins": 1, + "opened": "2026-11-04T23:01:20.019730Z", + "orphan": false, + "policy_requests": 1 + }, + { + "closed": "2026-11-04T23:11:55.088115Z", + "failed_k8s_logins": 0, + "login_service_accounts": [ + "sso/nk-bind-executor" + ], + "login_times": [ + "2026-11-04T23:08:27.740455Z" + ], + "logins": 1, + "opened": "2026-11-04T23:07:03.460025Z", + "orphan": false, + "policy_requests": 1 + }, + { + "closed": "2026-11-05T08:26:56.144210Z", + "failed_k8s_logins": 0, + "login_service_accounts": [ + "sso/nk-bind-executor" + ], + "login_times": [ + "2026-11-04T23:16:32.654774Z", + "2026-11-04T23:18:28.817310Z" + ], + "logins": 2, + "opened": "2026-11-04T23:16:24.183101Z", + "orphan": false, + "policy_requests": 2 + }, + { + "closed": "2026-11-05T08:45:09.306862Z", + "failed_k8s_logins": 0, + "login_service_accounts": [ + "sso/nk-bind-executor" + ], + "login_times": [ + "2026-11-05T08:30:11.745903Z" + ], + "logins": 1, + "opened": "2026-11-05T08:30:06.917172Z", + "orphan": false, + "policy_requests": 6 + } + ], + "log_first_time": "2026-08-03T19:15:27.303070Z", + "log_last_time": "2026-11-05T12:59:11.033093Z", + "log_lines": 9006227, + "log_unparseable": 1, + "role": "net-kingdom-bind-executor-svc-authelia-write", + "role_present_at_log_end": false, + "source_sha256": "75cba8e193b54e3b445ac5df12b857f1b365f6b336164b1bd4e1a2c5787b6971", + "status": "read", + "values_recorded": false +} diff --git a/docs/evidence/2026-11-05-nk58-t11-write-role-check/04-write-role-audit.json b/docs/evidence/2026-11-05-nk58-t11-write-role-check/04-write-role-audit.json new file mode 100644 index 0000000..508c7db --- /dev/null +++ b/docs/evidence/2026-11-05-nk58-t11-write-role-check/04-write-role-audit.json @@ -0,0 +1,116 @@ +{ + "action": "write-role-audit", + "check": { + "from": "2026-11-04T23:33:29.000000Z", + "intervals_overlapping": 2, + "log_covers_check": true, + "logins_in_check": 0, + "no_login_in_check": true, + "policy_requests_in_check": 0, + "to": "2026-11-05T08:26:57.000000Z" + }, + "intervals": [ + { + "closed": null, + "failed_k8s_logins": 0, + "first_seen": "2026-10-31T18:46:06.644298Z", + "login_service_accounts": [], + "login_times": [], + "logins": 0, + "opened": null, + "orphan": true, + "policy_request_times": [ + "2026-10-31T18:46:06.644298Z" + ], + "policy_requests": 1 + }, + { + "closed": "2026-11-04T23:03:22.057510Z", + "failed_k8s_logins": 0, + "first_seen": null, + "login_service_accounts": [ + "sso/nk-bind-executor" + ], + "login_times": [ + "2026-11-04T23:02:46.117361Z" + ], + "logins": 1, + "opened": "2026-11-04T23:01:20.019730Z", + "orphan": false, + "policy_request_times": [ + "2026-11-04T23:02:46.318984Z" + ], + "policy_requests": 1 + }, + { + "closed": "2026-11-04T23:11:55.088115Z", + "failed_k8s_logins": 0, + "first_seen": null, + "login_service_accounts": [ + "sso/nk-bind-executor" + ], + "login_times": [ + "2026-11-04T23:08:27.740455Z" + ], + "logins": 1, + "opened": "2026-11-04T23:07:03.460025Z", + "orphan": false, + "policy_request_times": [ + "2026-11-04T23:08:28.006802Z" + ], + "policy_requests": 1 + }, + { + "closed": "2026-11-05T08:26:56.144210Z", + "failed_k8s_logins": 0, + "first_seen": null, + "login_service_accounts": [ + "sso/nk-bind-executor" + ], + "login_times": [ + "2026-11-04T23:16:32.654774Z", + "2026-11-04T23:18:28.817310Z" + ], + "logins": 2, + "opened": "2026-11-04T23:16:24.183101Z", + "orphan": false, + "policy_request_times": [ + "2026-11-04T23:16:33.174001Z", + "2026-11-04T23:18:29.106514Z" + ], + "policy_requests": 2 + }, + { + "closed": "2026-11-05T08:45:09.306862Z", + "failed_k8s_logins": 0, + "first_seen": null, + "login_service_accounts": [ + "sso/nk-bind-executor" + ], + "login_times": [ + "2026-11-05T08:30:11.745903Z" + ], + "logins": 1, + "opened": "2026-11-05T08:30:06.917172Z", + "orphan": false, + "policy_request_times": [ + "2026-11-05T08:30:11.966153Z", + "2026-11-05T08:30:11.973966Z", + "2026-11-05T08:30:11.977193Z", + "2026-11-05T08:30:11.980109Z", + "2026-11-05T08:30:12.935954Z", + "2026-11-05T08:30:42.471889Z" + ], + "policy_requests": 6 + } + ], + "log_first_time": "2026-08-03T19:15:27.303070Z", + "log_last_time": "2026-11-05T21:33:07.422792Z", + "log_lines": 9070712, + "log_unparseable": 0, + "role": "net-kingdom-bind-executor-svc-authelia-write", + "role_present_at_log_end": false, + "source_sha256": "75950f1f9bea502dfdfb540c649a5569f0c6f77ded1dca489079ac04209397c2", + "status": "read", + "values_recorded": false +} diff --git a/docs/evidence/2026-11-05-nk58-t11-write-role-check/README.md b/docs/evidence/2026-11-05-nk58-t11-write-role-check/README.md new file mode 100644 index 0000000..f21881e --- /dev/null +++ b/docs/evidence/2026-11-05-nk58-t11-write-role-check/README.md @@ -0,0 +1,41 @@ +# NK-WP-0058-T11: no login used the write role while it was open overnight (2026-11-05) + +**Result: clean.** OpenBao's file audit log shows no login with the executor write role +`net-kingdom-bind-executor-svc-authelia-write` (CCR-2026-0058) and no request made with its policy, from +2026-11-04T23:33:29Z until the late close at 2026-11-05T08:26:56Z. There was no failed Kubernetes login of any kind +in that time either. The role is absent at the end of the log (2026-11-05T21:33:07Z). + +Founder-run, read-only. The audit log was streamed from `openbao-0` into `tools/service-binds/write-role-audit.py` +(`7031c97`, source sha256 `75950f1f…`) and nothing was stored on the way. The receipts hold times, counts and +ServiceAccount names only. + +| Receipt | What it is | +| --- | --- | +| `04-write-role-audit.json` | **The result.** Check period 23:33:29Z–08:26:57Z; log 2026-08-03T19:15Z–2026-11-05T21:33Z, 9 070 712 lines, 1 unparseable; `log_covers_check: true`, `no_login_in_check: true` | +| `02-write-role-audit.json` | First read, superseded. Its built-in period started at the window start, 22:39Z, so it counted the attended evening logins (below). The tool then gained request times and a required period | +| `01-window-close.json` | Failed `phase: identity`, `LaneError`: no valid platform-admin OpenBao login in that shell. The bare error type is a T03 example. Not repeated; role absence is shown by the audit log instead | + +## Every interval in which the write role existed + +| Opened (UTC) | Closed (UTC) | Logins (`sso/nk-bind-executor`) | Write-policy requests | What it was | +| --- | --- | --- | --- | --- | +| — | — | — | 2026-10-31 18:46:06 | `executor-lanes.py setup`: proof that the fence beats the policy, made with a token that carries it; no role | +| 11-04 23:01:20 | 23:03:22 | 23:02:46 | 23:02:46 | run 1 of BEA-2026-0002 (refused `setup:URLError`) | +| 11-04 23:07:03 | 23:11:55 | 23:08:27 | 23:08:28 | run 2 (refused again) | +| 11-04 23:16:24 | **11-05 08:26:56** | 23:16:32, 23:18:28 | 23:16:33, 23:18:29 | diagnostics 2 and 3, the real `build()` with the write-role login, each revoked at once. **Then nothing for 9 h 8 min** | +| 11-05 08:30:06 | 08:45:09 | 08:30:11 | six, 08:30:11–08:30:42 | the BEA-2026-0003 pilot run: the positive control, proving that the read detects a real login | + +The period starts at 23:33:29Z, which is the last attended login (23:18:28) plus the 15-minute maximum token +lifetime. Any later use would have needed a new login, and none happened. + +## Corrections to the NK-WP-0056 pilot evidence + +The overnight window opened at **23:16:24Z** (not "about 23:20Z") and was closed at **08:26:56Z** (not 08:24Z). This is +corrected in `../2026-11-05-nk56-t06-pilot/README.md`. + +## Not done here + +- A direct read that the role is absent now (`window-close` rerun with a platform-admin login). The audit log + records every create and delete of the role, so its absence through 21:33Z follows from the log; the direct read + stays available as `executor-lanes.py window-close`, which is safe to repeat. +- Making an unclosed window impossible to forget is NK-WP-0058-T06. diff --git a/workplans/NK-WP-0058-bounded-execution-operability.md b/workplans/NK-WP-0058-bounded-execution-operability.md index 585b2a7..6ea932c 100644 --- a/workplans/NK-WP-0058-bounded-execution-operability.md +++ b/workplans/NK-WP-0058-bounded-execution-operability.md @@ -76,7 +76,7 @@ and T07 can run in parallel with these, and T08 comes last. ```task id: NK-WP-0058-T11 -status: todo +status: done priority: high assignee: claude-code state_hub_task_id: "e2d02456-b072-5d42-a25b-964dc14de5ef" @@ -94,6 +94,24 @@ founder runs them and reports one result line for each. **Done when:** a dated, value-free receipt records both results under the NK-WP-0056 pilot evidence. Any login that was found is routed as a security finding to railiance-platform. +**Result, 2026-11-05: clean.** Evidence is in `docs/evidence/2026-11-05-nk58-t11-write-role-check/`, linked from the +NK-WP-0056 pilot README. + +- From 23:33:29Z (the last attended login plus the 15-minute token lifetime) to the close at 08:26:56Z, there was no + login with the write role, no request with its policy, and no failed Kubernetes login. +- All five logins in the log are the documented attended runs and diagnostics, plus the pilot run. +- The role is absent at the end of the log (21:33Z). This was derived from the audit log's create and delete + entries, because the direct `window-close` read failed for lack of a platform-admin login. +- No finding was routed. + +Tool: `tools/service-binds/write-role-audit.py`, with tests in `tests/test_write_role_audit.py`. + +Inputs for other tasks: + +- **T06:** the audit file is not rotated (2 GiB PVC, history since 2026-08-03), and one read takes about 10 minutes + through `kubectl exec`. A recurring check should use audit forwarding (NK-WP-0055-T11), not this stream. +- **T03:** the failed close reported only `LaneError`, without its cause. + ### Interface and responsibility inventory, part 1: executor and its services ```task