build: provision and verify Whitehat foundational plane
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a02878-7c21-7692-bcd6-ce2838c4b448
This commit is contained in:
parent
acab22ff25
commit
c26a6e59de
6 changed files with 244 additions and 5 deletions
137
docs/evidence/whitehat-foundational-plane.json
Normal file
137
docs/evidence/whitehat-foundational-plane.json
Normal file
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
62
docs/evidence/whitehat-foundational-plane.md
Normal file
62
docs/evidence/whitehat-foundational-plane.md
Normal file
|
|
@ -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`.
|
||||||
|
|
@ -3,7 +3,7 @@ id: whitehat-foundational-plane
|
||||||
demand_source: "statehub-message:311a274e-9434-4fc3-bc52-8ea15ca68274"
|
demand_source: "statehub-message:311a274e-9434-4fc3-bc52-8ea15ca68274"
|
||||||
consumer_repo: whitehat-security
|
consumer_repo: whitehat-security
|
||||||
credential_type: kubernetes-foundational-plane
|
credential_type: kubernetes-foundational-plane
|
||||||
status: approved
|
status: built
|
||||||
approved_by: "Bernd Worsch"
|
approved_by: "Bernd Worsch"
|
||||||
approved_at: "2026-08-22"
|
approved_at: "2026-08-22"
|
||||||
created: "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
|
## 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`.
|
||||||
|
|
|
||||||
|
|
@ -555,7 +555,10 @@ def apply(
|
||||||
_check_inputs_clean(bundle, runner)
|
_check_inputs_clean(bundle, runner)
|
||||||
before = preflight(bundle, runner)
|
before = preflight(bundle, runner)
|
||||||
|
|
||||||
|
server_validated = list(before["server_validated_manifests"])
|
||||||
|
persisted: list[str] = []
|
||||||
for manifest in bundle.manifests:
|
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()))
|
docs = list(yaml.safe_load_all(manifest.path.read_text()))
|
||||||
namespaced = any(doc.get("metadata", {}).get("namespace") for doc in docs)
|
namespaced = any(doc.get("metadata", {}).get("namespace") for doc in docs)
|
||||||
if namespaced:
|
if namespaced:
|
||||||
|
|
@ -571,6 +574,7 @@ def apply(
|
||||||
str(manifest.path),
|
str(manifest.path),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
server_validated.append(relative_path)
|
||||||
_run(
|
_run(
|
||||||
runner,
|
runner,
|
||||||
[
|
[
|
||||||
|
|
@ -582,6 +586,7 @@ def apply(
|
||||||
str(manifest.path),
|
str(manifest.path),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
persisted.append(relative_path)
|
||||||
|
|
||||||
verified = verify(bundle, runner)
|
verified = verify(bundle, runner)
|
||||||
evidence = {
|
evidence = {
|
||||||
|
|
@ -597,6 +602,11 @@ def apply(
|
||||||
"revision": bundle.source_revision,
|
"revision": bundle.source_revision,
|
||||||
"implementation_revision": bundle.implementation_revision,
|
"implementation_revision": bundle.implementation_revision,
|
||||||
},
|
},
|
||||||
|
"apply": {
|
||||||
|
"field_manager": "ops-mason",
|
||||||
|
"server_validated_manifests": server_validated,
|
||||||
|
"persisted_manifests": persisted,
|
||||||
|
},
|
||||||
"preflight": before,
|
"preflight": before,
|
||||||
"verification": verified,
|
"verification": verified,
|
||||||
"rollback": rollback_plan(bundle),
|
"rollback": rollback_plan(bundle),
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,10 @@ def test_whitehat_bundle_is_exactly_four_allowlisted_objects() -> None:
|
||||||
"NetworkPolicy/whitehat/allow-audit-core-e2",
|
"NetworkPolicy/whitehat/allow-audit-core-e2",
|
||||||
"ServiceAccount/whitehat/whitehat-runner",
|
"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} == {
|
assert {doc["kind"] for doc in bundle.documents} == {
|
||||||
"Namespace",
|
"Namespace",
|
||||||
"NetworkPolicy",
|
"NetworkPolicy",
|
||||||
|
|
@ -234,6 +237,11 @@ def test_apply_runs_guarded_path_and_writes_metadata_only_evidence(tmp_path: Pat
|
||||||
runner=cluster,
|
runner=cluster,
|
||||||
)
|
)
|
||||||
assert evidence["verification"]["negative_scope"] == {"pods": 0, "secrets": 0}
|
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()
|
assert bundle.evidence_path.exists()
|
||||||
text = bundle.evidence_path.read_text()
|
text = bundle.evidence_path.read_text()
|
||||||
assert "uid-1" in text
|
assert "uid-1" in text
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ Whitehat README alignment request: State Hub message
|
||||||
|
|
||||||
```task
|
```task
|
||||||
id: MASON-WP-0002-T02
|
id: MASON-WP-0002-T02
|
||||||
status: progress
|
status: done
|
||||||
priority: high
|
priority: high
|
||||||
state_hub_task_id: "23f78bc5-4185-5181-9f3c-fd718641d2a5"
|
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
|
checks are clean, and the exact rollback commands have been captured without
|
||||||
executing them.
|
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
|
## Return evidence and bounded handoff
|
||||||
|
|
||||||
```task
|
```task
|
||||||
id: MASON-WP-0002-T03
|
id: MASON-WP-0002-T03
|
||||||
status: todo
|
status: progress
|
||||||
priority: high
|
priority: high
|
||||||
state_hub_task_id: "a9c0844b-bf0a-5a53-b7e7-c0c2fbb842e6"
|
state_hub_task_id: "a9c0844b-bf0a-5a53-b7e7-c0c2fbb842e6"
|
||||||
```
|
```
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue