From c26a6e59de378fd0d822ef89a0cf8d52debb5004 Mon Sep 17 00:00:00 2001 From: tegwick Date: Sat, 22 Aug 2026 11:26:49 +0200 Subject: [PATCH] build: provision and verify Whitehat foundational plane Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a02878-7c21-7692-bcd6-ce2838c4b448 --- .../evidence/whitehat-foundational-plane.json | 137 ++++++++++++++++++ docs/evidence/whitehat-foundational-plane.md | 62 ++++++++ plans/whitehat-foundational-plane.md | 20 ++- src/ops_mason/kubernetes_plane.py | 10 ++ tests/test_kubernetes_plane.py | 10 +- ...SON-WP-0002-whitehat-foundational-plane.md | 10 +- 6 files changed, 244 insertions(+), 5 deletions(-) create mode 100644 docs/evidence/whitehat-foundational-plane.json create mode 100644 docs/evidence/whitehat-foundational-plane.md diff --git a/docs/evidence/whitehat-foundational-plane.json b/docs/evidence/whitehat-foundational-plane.json new file mode 100644 index 0000000..fe7b802 --- /dev/null +++ b/docs/evidence/whitehat-foundational-plane.json @@ -0,0 +1,137 @@ +{ + "apply": { + "field_manager": "ops-mason", + "persisted_manifests": [ + "manifests/whitehat-plane/namespace.yaml", + "manifests/whitehat-plane/network-policy.yaml", + "manifests/whitehat-plane/service-account.yaml" + ], + "server_validated_manifests": [ + "manifests/whitehat-plane/namespace.yaml", + "manifests/whitehat-plane/network-policy.yaml", + "manifests/whitehat-plane/service-account.yaml" + ] + }, + "plan": { + "approved_at": "2026-08-22", + "approved_by": "Bernd Worsch", + "id": "whitehat-foundational-plane" + }, + "preflight": { + "bundle_digest": "9636f48f0b994118ff60a8c014e0099486945d66a2b3d3582dc57a09862b2035", + "bundle_id": "whitehat-foundational-plane", + "client_validated_manifests": [ + "manifests/whitehat-plane/namespace.yaml", + "manifests/whitehat-plane/network-policy.yaml", + "manifests/whitehat-plane/service-account.yaml" + ], + "context": "default", + "deferred_server_validation": [ + "manifests/whitehat-plane/network-policy.yaml", + "manifests/whitehat-plane/service-account.yaml" + ], + "dependencies": [ + { + "assertions": { + "/spec/ports/0/port": 8080 + }, + "name": "audit-core", + "namespace": "audit-core", + "resource": "services" + }, + { + "assertions": { + "/spec/ingress/0/from/0/namespaceSelector/matchLabels/kubernetes.io~1metadata.name": "whitehat", + "/spec/ingress/0/from/0/podSelector/matchLabels/whitehat.security~1plane": "true", + "/spec/ingress/0/from/0/podSelector/matchLabels/whitehat.security~1target": "audit-core", + "/spec/ingress/0/ports/0/port": 8080 + }, + "name": "audit-core-whitehat-ingress", + "namespace": "audit-core", + "resource": "networkpolicies.networking.k8s.io" + } + ], + "objects": [ + { + "object": "Namespace/whitehat", + "state": "absent" + }, + { + "object": "NetworkPolicy/whitehat/default-deny", + "state": "absent" + }, + { + "object": "NetworkPolicy/whitehat/allow-audit-core-e2", + "state": "absent" + }, + { + "object": "ServiceAccount/whitehat/whitehat-runner", + "state": "absent" + } + ], + "ok": true, + "plan_approved": true, + "plan_id": "whitehat-foundational-plane", + "server_validated_manifests": [ + "manifests/whitehat-plane/namespace.yaml" + ] + }, + "recorded_at": "2026-08-22T09:24:44.407612+00:00", + "rollback": { + "bundle_id": "whitehat-foundational-plane", + "conditional_namespace_commands": [ + "kubectl delete namespaces whitehat" + ], + "inventory_before_namespace_delete": [ + "kubectl -n whitehat get all,configmaps,secrets,serviceaccounts,networkpolicies" + ], + "object_scoped_commands": [ + "kubectl -n whitehat delete networkpolicies.networking.k8s.io default-deny", + "kubectl -n whitehat delete networkpolicies.networking.k8s.io allow-audit-core-e2", + "kubectl -n whitehat delete serviceaccounts whitehat-runner" + ], + "warning": "Delete the namespace only after proving it contains no later or unrelated objects." + }, + "schema_version": "ops-mason.kubernetes-plane-evidence/v1", + "source": { + "implementation_revision": "95129d7a35c8999be359b163b554853c9c6afa3a", + "repo": "whitehat-security", + "revision": "4882c2d47a826a305d5c4e05aa7fcc1252c3887e" + }, + "verification": { + "bundle_digest": "9636f48f0b994118ff60a8c014e0099486945d66a2b3d3582dc57a09862b2035", + "bundle_id": "whitehat-foundational-plane", + "context": "default", + "negative_scope": { + "pods": 0, + "secrets": 0 + }, + "objects": [ + { + "generation": null, + "object": "Namespace/whitehat", + "resource_version": "50841574", + "uid": "b0f97761-28a2-4b50-b4cb-890995fc0993" + }, + { + "generation": 1, + "object": "NetworkPolicy/whitehat/default-deny", + "resource_version": "50841577", + "uid": "f4143fc9-4e42-454e-867b-c3fe5a050945" + }, + { + "generation": 1, + "object": "NetworkPolicy/whitehat/allow-audit-core-e2", + "resource_version": "50841578", + "uid": "84ba88a8-74df-448d-b9ba-066083c49b0f" + }, + { + "generation": null, + "object": "ServiceAccount/whitehat/whitehat-runner", + "resource_version": "50841583", + "uid": "6229deb0-82b8-4ca7-aee5-e00b4eff81a9" + } + ], + "ok": true + } +} diff --git a/docs/evidence/whitehat-foundational-plane.md b/docs/evidence/whitehat-foundational-plane.md new file mode 100644 index 0000000..4068787 --- /dev/null +++ b/docs/evidence/whitehat-foundational-plane.md @@ -0,0 +1,62 @@ +# Whitehat foundational plane apply evidence + +Applied: `2026-08-22T09:24:44Z` +Plan: `whitehat-foundational-plane` +Approved by: Bernd Worsch, 2026-08-22 +Executor source: ops-mason `2b31863` +Bundle digest: `9636f48f0b994118ff60a8c014e0099486945d66a2b3d3582dc57a09862b2035` + +## Provenance and guard result + +- Whitehat coordination revision: + `4882c2d47a826a305d5c4e05aa7fcc1252c3887e` +- Plane implementation revision: + `95129d7a35c8999be359b163b554853c9c6afa3a` +- The three source files and Mason pins are byte-identical. +- Context `default`, create RBAC, audit-core Service TCP 8080, and + `audit-core-whitehat-ingress` exact selectors/port passed. +- All four objects were absent before apply. +- All three manifests passed client validation and server dry-run before + persistence. + +## Live objects + +| Object | UID | Resource version | +| --- | --- | --- | +| Namespace `whitehat` | `b0f97761-28a2-4b50-b4cb-890995fc0993` | `50841574` | +| NetworkPolicy `default-deny` | `f4143fc9-4e42-454e-867b-c3fe5a050945` | `50841577` | +| NetworkPolicy `allow-audit-core-e2` | `84ba88a8-74df-448d-b9ba-066083c49b0f` | `50841578` | +| ServiceAccount `whitehat-runner` | `6229deb0-82b8-4ca7-aee5-e00b4eff81a9` | `50841583` | + +Post-apply preflight classifies every object as `exact` and server-validates +all manifests. ServiceAccount token automount is `false`. The namespace has +zero Pods and zero Secrets. Kubernetes created its normal `default` +ServiceAccount and `kube-root-ca.crt` ConfigMap; neither is part of the bundle. + +No runner Pod, credential, projected identity, custody lease, new engagement, +or target request was created or sent. + +## Rollback + +Object-scoped rollback, in order: + +```bash +kubectl -n whitehat delete networkpolicies.networking.k8s.io default-deny +kubectl -n whitehat delete networkpolicies.networking.k8s.io allow-audit-core-e2 +kubectl -n whitehat delete serviceaccounts whitehat-runner +``` + +Before considering Namespace deletion, inventory it: + +```bash +kubectl -n whitehat get all,configmaps,secrets,serviceaccounts,networkpolicies +``` + +Only if no later or unrelated object exists: + +```bash +kubectl delete namespaces whitehat +``` + +No rollback command was executed. Machine-readable evidence is in +`docs/evidence/whitehat-foundational-plane.json`. diff --git a/plans/whitehat-foundational-plane.md b/plans/whitehat-foundational-plane.md index fba600a..222cf21 100644 --- a/plans/whitehat-foundational-plane.md +++ b/plans/whitehat-foundational-plane.md @@ -3,7 +3,7 @@ id: whitehat-foundational-plane demand_source: "statehub-message:311a274e-9434-4fc3-bc52-8ea15ca68274" consumer_repo: whitehat-security credential_type: kubernetes-foundational-plane -status: approved +status: built approved_by: "Bernd Worsch" approved_at: "2026-08-22" created: "2026-08-22" @@ -84,4 +84,20 @@ above and does not extend to a runner, credential, engagement, or traffic. ## 6. Build result -Pending guarded apply and metadata-only verification. +Built and verified on 2026-08-22 with the guarded executor introduced in +ops-mason commit `2b31863` and immutable bundle digest +`9636f48f0b994118ff60a8c014e0099486945d66a2b3d3582dc57a09862b2035`. + +- created Namespace `whitehat` with restricted Pod Security enforcement; +- created NetworkPolicies `default-deny` and `allow-audit-core-e2`; +- created ServiceAccount `whitehat-runner` with token automount disabled; +- server-dry-ran every manifest before persistence; +- independently re-verified all desired fields and found zero live drift; +- found zero Pods and zero Secrets in the namespace; +- generated object-scoped rollback plus a separately conditional Namespace + rollback; no rollback command was executed. + +Kubernetes automatically created only its normal `default` ServiceAccount and +`kube-root-ca.crt` ConfigMap alongside the four governed objects. No runner, +credential, projected identity, lease, engagement, or target request exists. +Evidence: `docs/evidence/whitehat-foundational-plane.json` and `.md`. diff --git a/src/ops_mason/kubernetes_plane.py b/src/ops_mason/kubernetes_plane.py index 0a6c8b0..766d34f 100644 --- a/src/ops_mason/kubernetes_plane.py +++ b/src/ops_mason/kubernetes_plane.py @@ -555,7 +555,10 @@ def apply( _check_inputs_clean(bundle, runner) before = preflight(bundle, runner) + server_validated = list(before["server_validated_manifests"]) + persisted: list[str] = [] for manifest in bundle.manifests: + relative_path = str(manifest.path.relative_to(bundle.repo_root)) docs = list(yaml.safe_load_all(manifest.path.read_text())) namespaced = any(doc.get("metadata", {}).get("namespace") for doc in docs) if namespaced: @@ -571,6 +574,7 @@ def apply( str(manifest.path), ], ) + server_validated.append(relative_path) _run( runner, [ @@ -582,6 +586,7 @@ def apply( str(manifest.path), ], ) + persisted.append(relative_path) verified = verify(bundle, runner) evidence = { @@ -597,6 +602,11 @@ def apply( "revision": bundle.source_revision, "implementation_revision": bundle.implementation_revision, }, + "apply": { + "field_manager": "ops-mason", + "server_validated_manifests": server_validated, + "persisted_manifests": persisted, + }, "preflight": before, "verification": verified, "rollback": rollback_plan(bundle), diff --git a/tests/test_kubernetes_plane.py b/tests/test_kubernetes_plane.py index 9fb2dea..f1f3acb 100644 --- a/tests/test_kubernetes_plane.py +++ b/tests/test_kubernetes_plane.py @@ -28,7 +28,10 @@ def test_whitehat_bundle_is_exactly_four_allowlisted_objects() -> None: "NetworkPolicy/whitehat/allow-audit-core-e2", "ServiceAccount/whitehat/whitehat-runner", ] - assert bundle.plan().is_approved() + plan = bundle.plan() + assert plan.status == "built" + assert plan.approved_by == "Bernd Worsch" + assert plan.approved_at == "2026-08-22" assert {doc["kind"] for doc in bundle.documents} == { "Namespace", "NetworkPolicy", @@ -234,6 +237,11 @@ def test_apply_runs_guarded_path_and_writes_metadata_only_evidence(tmp_path: Pat runner=cluster, ) assert evidence["verification"]["negative_scope"] == {"pods": 0, "secrets": 0} + assert evidence["apply"] == { + "field_manager": "ops-mason", + "server_validated_manifests": ["manifests/plane.yaml"], + "persisted_manifests": ["manifests/plane.yaml"], + } assert bundle.evidence_path.exists() text = bundle.evidence_path.read_text() assert "uid-1" in text diff --git a/workplans/MASON-WP-0002-whitehat-foundational-plane.md b/workplans/MASON-WP-0002-whitehat-foundational-plane.md index 753b0d0..85d9ba2 100644 --- a/workplans/MASON-WP-0002-whitehat-foundational-plane.md +++ b/workplans/MASON-WP-0002-whitehat-foundational-plane.md @@ -94,7 +94,7 @@ Whitehat README alignment request: State Hub message ```task id: MASON-WP-0002-T02 -status: progress +status: done priority: high state_hub_task_id: "23f78bc5-4185-5181-9f3c-fd718641d2a5" ``` @@ -124,11 +124,17 @@ or broad selector for rollback. checks are clean, and the exact rollback commands have been captured without executing them. +**Done (2026-08-22):** guarded apply created exactly the four approved objects. +All desired fields re-verify as exact, every manifest passed server dry-run, +`whitehat-runner` reports token automount `false`, and the namespace has zero +Pods and zero Secrets. Evidence includes object UIDs/resource versions and +rollback; no rollback command or target packet was executed. + ## Return evidence and bounded handoff ```task id: MASON-WP-0002-T03 -status: todo +status: progress priority: high state_hub_task_id: "a9c0844b-bf0a-5a53-b7e7-c0c2fbb842e6" ```