From 816610a7a1b566ad3cd4a78dd6a5e6d84b944975 Mon Sep 17 00:00:00 2001 From: tegwick Date: Tue, 29 Sep 2026 00:25:18 +0200 Subject: [PATCH] Add NK-WP-0044 and NetKingdom runbook packs (legacy console wrapper, SSH pack) Co-Authored-By: Claude Sonnet 5.5 Assistant: claude-code Assistant-Model: sonnet Assistant-Process: 295952@bnt-lap001 Assistant-Session: e93f64ad-516c-46eb-9666-aad8d300c477 --- Makefile | 7 +- docs/tutorials/README.md | 4 + runbooks/security-bootstrap-console/pack.yaml | 12 +++ runbooks/ssh-certificates/pack.yaml | 61 ++++++++++++ ...044-runbook-packs-for-runbook-tutorials.md | 93 +++++++++++++++++++ 5 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 runbooks/security-bootstrap-console/pack.yaml create mode 100644 runbooks/ssh-certificates/pack.yaml create mode 100644 workplans/NK-WP-0044-runbook-packs-for-runbook-tutorials.md diff --git a/Makefile b/Makefile index 69bfacf..425c938 100644 --- a/Makefile +++ b/Makefile @@ -189,6 +189,11 @@ openbao-init-unseal-dry-run: ## Dry-run the SOPS-held OpenBao init/unseal path tutorials-verify: ## Verify docs/tutorials structure, ownership tags, and references python3 tools/tutorial-verify/tutorial_verify.py +RTUT_HOME ?= $(HOME)/runbook-tutorials + +runbooks-validate: ## Validate runbook packs under runbooks/ with the runbook-tutorials engine + PYTHONPATH=$(RTUT_HOME) python3 -m rtut validate . + tutorials-verify-test: ## Run tutorial verifier tests python3 -m pytest tools/tutorial-verify/tests @@ -379,7 +384,7 @@ security-bootstrap-ui: security-bootstrap-metadata-init ## Serve local custody a --host "$(SECURITY_BOOTSTRAP_HOST)" \ --port "$(SECURITY_BOOTSTRAP_PORT)" -.PHONY: tutorials-verify tutorials-verify-test help hooks hooks-test sops-setup sops-edit sops-encrypt sops-decrypt sops-rotate \ +.PHONY: runbooks-validate tutorials-verify tutorials-verify-test help hooks hooks-test sops-setup sops-edit sops-encrypt sops-decrypt sops-rotate \ check-secrets creds-init creds-generate creds-bundle creds-apply creds-verify \ creds-status creds-rotate \ creds-agent-init creds-agent-status creds-emergency-reprint \ diff --git a/docs/tutorials/README.md b/docs/tutorials/README.md index 1b1b7dc..1ae7d54 100644 --- a/docs/tutorials/README.md +++ b/docs/tutorials/README.md @@ -4,6 +4,10 @@ Hands-on paths for operating the canonical NetKingdom security patterns (NK-WP-0009). Each tutorial is a file in this directory, written from [`TEMPLATE.md`](TEMPLATE.md) and checked by `make tutorials-verify`. +> **Moving.** Tutorials are becoming runbook packs in `runbooks/` for the +> `runbook-tutorials` engine (NK-WP-0044). `runbooks/ssh-certificates/` is the first. +> These markdown files stay until their packs are exercised. + ## Rules 1. **Exercise status is mandatory.** Per diff --git a/runbooks/security-bootstrap-console/pack.yaml b/runbooks/security-bootstrap-console/pack.yaml new file mode 100644 index 0000000..fba5cdf --- /dev/null +++ b/runbooks/security-bootstrap-console/pack.yaml @@ -0,0 +1,12 @@ +spec: runbook-pack/v0.1 +id: nk.security-bootstrap-console +title: NetKingdom guided security bootstrap (existing console) +owner: net-kingdom +outcome: The platform-root custody, OpenBao ceremony evidence, and identity bootstrap gates are walked through in the existing guided console. +exercise_status: unexercised +engine: legacy-command +legacy: + command: [make, security-bootstrap-ui] + cwd: . + url: http://127.0.0.1:8876 + note: "Exercise history is recorded in NET-WP-0017 evidence, not attributed here. Unchanged console from NET-WP-0016; the engine only lists and launches it. Progress stays in .local/security-bootstrap.json." diff --git a/runbooks/ssh-certificates/pack.yaml b/runbooks/ssh-certificates/pack.yaml new file mode 100644 index 0000000..27285ff --- /dev/null +++ b/runbooks/ssh-certificates/pack.yaml @@ -0,0 +1,61 @@ +spec: runbook-pack/v0.1 +id: nk.ssh-certificates +title: Short-lived SSH credentials for admins, agents and automations +owner: net-kingdom +outcome: An actor obtains a short-lived CA-signed SSH certificate and uses it through an ops-bridge tunnel, with no static key doing the work. +exercise_status: unexercised +engine: native +parameters: + - {id: actor, label: Actor name, type: string, default: agt-claude-railiance01, pattern: "(adm|agt|atm)-[a-z0-9-]+", help: "Actor type prefix decides the maximum TTL: adm 48h, agt 24h, atm 8h."} + - {id: pubkey, label: Public key path, type: path, default: ~/.ssh/id_ed25519.pub} + - {id: tunnel, label: Tunnel name, type: string, default: k3s-api-railiance01, pattern: "[a-z0-9-]+"} +prerequisites: + - {text: warden CLI installed and actor present in the principals inventory, owner: ops-warden} + - {text: bridge CLI and a tunnel definition, owner: ops-bridge} + - {text: Target hosts trust the SSH CA and carry the actor principal, owner: railiance-infra} +steps: + - id: status-before + title: Look at current certificates + owner: ops-warden + command: warden status + verify: {done_when: You know which certificates are current and which are expired, expect: manual} + - id: sign + title: Sign a public key for the actor + owner: ops-warden + command: warden sign {{actor}} --pubkey {{pubkey}} > /tmp/{{actor}}-cert.pub + risk: changes-state + rollback: Delete /tmp/{{actor}}-cert.pub; the certificate expires on its own. + verify: + done_when: A certificate file exists and names the expected principal + command: ssh-keygen -L -f /tmp/{{actor}}-cert.pub + expect: exit-0 + evidence: [actor, certificate_valid_before] + - id: inspect-ttl + title: Check the certificate lifetime + owner: ops-warden + command: ssh-keygen -L -f /tmp/{{actor}}-cert.pub | grep -E "Key ID|Principals|Valid" + verify: {done_when: "Valid before is within the actor-type TTL (adm 48h, agt 24h, atm 8h)", expect: manual} + - id: tunnel-up + title: Bring up the tunnel that uses cert_command + owner: ops-bridge + command: bridge up {{tunnel}} + risk: changes-state + rollback: bridge down {{tunnel}} + verify: + done_when: The tunnel shows connected + command: bridge status + expect: output-contains + contains: "{{tunnel}}" + - id: audit + title: Confirm the signing was audited + owner: ops-warden + command: warden log | tail -5 + verify: {done_when: Your signing appears in the history, expect: manual} +threat_checks: + - Certificate files must be mode 600 and are never reused across reconnects. + - A non-zero cert_command exit is a failure and must trigger backoff. + - ops-warden never vends API keys or passwords; route them with warden route find. +ownership: + - {concern: Certificate issuance and TTL policy, owner: ops-warden} + - {concern: Tunnel lifecycle and refresh, owner: ops-bridge} + - {concern: Host CA trust and principals, owner: railiance-infra} diff --git a/workplans/NK-WP-0044-runbook-packs-for-runbook-tutorials.md b/workplans/NK-WP-0044-runbook-packs-for-runbook-tutorials.md new file mode 100644 index 0000000..40a3643 --- /dev/null +++ b/workplans/NK-WP-0044-runbook-packs-for-runbook-tutorials.md @@ -0,0 +1,93 @@ +--- +id: NK-WP-0044 +type: workplan +title: "Provide NetKingdom runbook packs for the runbook-tutorials engine" +domain: infotech +repo: net-kingdom +status: active +flavor: implementation +owner: claude +topic_slug: netkingdom +created: "2026-09-29" +updated: "2026-09-29" +related: [NK-WP-0009] +--- + +The guided console invented here (NET-WP-0016) now has a home: the +`runbook-tutorials` repository (workplans `RBT-WP-0002` to `RBT-WP-0006`). This +workplan is net-kingdom's side: keep the existing console working, and offer +NetKingdom runbooks as packs in `runbooks/`, following `runbook-pack/v0.1`. + +## Wrap the existing console as a legacy pack + +```task +id: NK-WP-0044-T01 +status: done +priority: high +``` + +`runbooks/security-bootstrap-console/pack.yaml`, engine `legacy-command`. Verified +end to end: `rtut launch` starts `make security-bootstrap-ui`, port 8876 +answers, and the process stops on exit. The console itself is unchanged. + +## Convert the SSH certificate tutorial to a native pack + +```task +id: NK-WP-0044-T02 +status: done +priority: high +``` + +`runbooks/ssh-certificates/pack.yaml` (parameters actor, pubkey, tunnel; owner-tagged +steps; verify and rollback). It validates; it is `unexercised`. + +## Convert the OpenBao and flex-auth tutorials + +```task +id: NK-WP-0044-T03 +status: todo +priority: high +``` + +`docs/tutorials/openbao-operating-path.md` and `protected-system-flex-auth.md` become +native packs. The flex-auth pack's live part uses the informed-decision pin and the +four negative tests as parameterized steps. Keep the markdown until the packs are +exercised. + +## Validate packs in this repository + +```task +id: NK-WP-0044-T04 +status: done +priority: medium +``` + +`make runbooks-validate` runs the `rtut` validator from the runbook-tutorials +checkout (`RTUT_HOME`, default `~/runbook-tutorials`). + +## Exercise the packs through the UI + +```task +id: NK-WP-0044-T05 +status: wait +priority: high +``` + +Blocked on `RBT-WP-0004` (UI). Bernd runs the SSH, OpenBao and flex-auth packs in the +UI; the engine records outcomes, and NK-WP-0009 T03-T05 close on those receipts. + +## Retire the markdown verifier + +```task +id: NK-WP-0044-T06 +status: wait +priority: low +``` + +Once the tutorials are packs, `tools/tutorial-verify` and `make tutorials-verify` are +replaced by `runbooks-validate`, and `docs/tutorials/` becomes a pointer. + +## Acceptance Criteria + +- The console still works and is launched by the engine without changes to it. +- Every NetKingdom pack validates; each is honestly labelled exercised or unexercised.