NK-WP-0056-T10: attended OpenBao setup and proof for the executor lanes
tools/service-binds/executor-lanes.py (bind-lane.py shape): under both sha256-bound, approved, binding-confirmed CCRs (0058 write, 0059 journey) and an attended platform-admin, apply both policies, set cas_required on the svc-authelia key, create the standing journey-read role, refuse if the window-scoped write role exists, prove the agent fence; verify proves the journey token reads only its path (<=15m) and denies wrong SA, wrong audience and write-role login. Value-free receipts. 12 tests on a fake OpenBao (real helpers), in make bounded-executor-test. Founder runbook: sso-mfa/k8s/bounded-executor/T10-LANES-RUNBOOK.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 5502@bnt-lap001 Assistant-Session: 68b3b02f-5d0f-4e71-8421-796f62e50196
This commit is contained in:
parent
37f4d4f306
commit
634b3a41df
4 changed files with 479 additions and 1 deletions
73
sso-mfa/k8s/bounded-executor/T10-LANES-RUNBOOK.md
Normal file
73
sso-mfa/k8s/bounded-executor/T10-LANES-RUNBOOK.md
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
# T10 runbook: executor standing objects and OpenBao lanes (founder-run)
|
||||
|
||||
NK-WP-0056-T10. Three steps, about 15 minutes. Nothing here starts a Job or touches the svc-authelia value. The
|
||||
bind write role (CCR-2026-0058) is **not** created: it exists only inside an admitted window.
|
||||
|
||||
| Step | Where | What changes |
|
||||
| --- | --- | --- |
|
||||
| 1 | `~/rapp-bounded-executor` | creates ServiceAccount `nk-bind-executor`, its Role and RoleBinding, and NetworkPolicy `bounded-executor` in `sso` |
|
||||
| 2 | `~/railiance-platform` | records `binding_confirmed` in CCR-2026-0058 and CCR-2026-0059 |
|
||||
| 3 | `~/net-kingdom` | OpenBao: both policies, `cas_required` on the svc-authelia key, the standing journey-read role, and proof |
|
||||
|
||||
## 1. Standing objects (rapp)
|
||||
|
||||
```bash
|
||||
cd ~/rapp-bounded-executor && git pull --ff-only
|
||||
K="kubectl --kubeconfig $HOME/.kube/config-railiance01"
|
||||
make server-dry-run KUBECTL="$K" # 4 objects "serverside-applied (server dry run)"
|
||||
make deploy KUBECTL="$K" # the same 4 objects, without "(server dry run)"
|
||||
make verify-live KUBECTL="$K" # {"role_matches_ceiling": true, "standing_objects_present": true, ...}
|
||||
```
|
||||
|
||||
The pod runs nothing yet: no Job exists until `make run` under an admission.
|
||||
|
||||
## 2. Confirm the binding (railiance-platform)
|
||||
|
||||
The CCRs bind `service_account_names: [nk-bind-executor]` in `sso`, audience `openbao`. Confirm that this
|
||||
ServiceAccount now exists, as declared:
|
||||
|
||||
```bash
|
||||
cd ~/railiance-platform && git pull --ff-only
|
||||
UID_SA=$($K -n sso get serviceaccount nk-bind-executor -o jsonpath='{.metadata.uid}'); echo "$UID_SA"
|
||||
for C in CCR-2026-0058 CCR-2026-0059; do
|
||||
scripts/credential-change.py confirm-binding "$C" --reviewer platform-owner --comment \
|
||||
"Binding confirmed: ServiceAccount nk-bind-executor in namespace sso only (uid $UID_SA), audience openbao, from rapp-bounded-executor."
|
||||
done
|
||||
git status --short # exactly the two CCR files modified
|
||||
```
|
||||
|
||||
## 3. OpenBao lanes (attended platform-admin)
|
||||
|
||||
```bash
|
||||
cd ~/net-kingdom && git pull --ff-only
|
||||
bao login -method=oidc -path=netkingdom role=platform-admin # MFA; the tool fails closed without it
|
||||
W=$(sha256sum ~/railiance-platform/credential-change-requests/CCR-2026-0058-*.yaml | cut -d' ' -f1)
|
||||
J=$(sha256sum ~/railiance-platform/credential-change-requests/CCR-2026-0059-*.yaml | cut -d' ' -f1)
|
||||
E=docs/evidence/$(date +%F)-nk56-t10-executor-lanes; mkdir -p "$E"
|
||||
|
||||
python3 tools/service-binds/executor-lanes.py setup --write-ccr-sha256 "$W" --journey-ccr-sha256 "$J" \
|
||||
--receipt "$E/01-setup.json" # {"status": "lanes_prepared", "phase": "done"}
|
||||
python3 tools/service-binds/executor-lanes.py verify --write-ccr-sha256 "$W" --journey-ccr-sha256 "$J" \
|
||||
--kubeconfig "$HOME/.kube/config-railiance01" --receipt "$E/02-verify.json" # {"status": "lanes_verified", ...}
|
||||
```
|
||||
|
||||
`setup` is idempotent: it creates what is missing and refuses on any drift. It never changes the coding-agent fence,
|
||||
because CCR-2026-0053 and CCR-2026-0057 established it; it only proves the fence. Receipts hold no values. `verify`
|
||||
reads the journey entry into memory only to check its field names.
|
||||
|
||||
If a step stops, the receipt's `phase` and `reason` say where:
|
||||
|
||||
| `reason` | Meaning, next step |
|
||||
| --- | --- |
|
||||
| `write:ccr_digest` / `journey:ccr_digest` | the CCR changed after `W`/`J` were computed; compute them again |
|
||||
| `*:binding_unconfirmed` | step 2 not done (or not saved) |
|
||||
| `attended_platform_admin_required` | no `bao login` as platform-admin, or a root token |
|
||||
| `agent_fence_missing` | the boundary policy lacks a deny line for one of the two paths; stop and hand to claude-code |
|
||||
| `command_failed` in phase `cas_required` | platform-admin may not patch KV metadata; hand to claude-code |
|
||||
| `write_role_exists_outside_a_window` | someone created the window-scoped write role; delete it, or stop |
|
||||
| `*:policy_drift` | a policy of that name exists with other text; stop |
|
||||
| `negative_login_accepted` / `journey_capabilities` | the role is wider than approved; delete the journey role and stop |
|
||||
|
||||
## 4. Afterwards
|
||||
|
||||
Tell claude-code. It commits the two CCRs and the receipts, moves CCR-2026-0059 on, and records T10 progress.
|
||||
Loading…
Add table
Add a link
Reference in a new issue