audit-core/tests/test_networkpolicies.py
tegwick c4016a70d5
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
AUDIT-WP-0009-T11 — register informed-decision, and answer GH-DEC-2026-014
informed-decision is the browser-facing approver surface; GH-DEC-2026-012
limit 3 makes its evidence copy the one that must reach audit-core
independently of the emitter, because there the actor being audited and the
evidence source are the same component.

Registration accepted on every proposed field — exact source,
["tenant:platform"], write true, read false, load-bearing, secret_policy
redact. Prepared and inert: the scope overlay applies only to a sender the
Secret already carries, asserted by test rather than by reading. Ingress ANDs
namespace and pod label in one peer, following approval-engine rather than
user-engine's older breadth.

Gate House asked whether the record shape can carry a source-held-content
declaration with a retrieval expectation, and asked for a straight answer
rather than a rule the storage cannot meet. Both halves, which must travel
together:

  It CAN carry the declaration. data is stored verbatim into details.data and
  hash-chained, so content_exists and custody need no schema change and become
  as tamper-evident as the commitment they accompany.

  It CANNOT detect non-production. audit-core performs no retrieval and its
  egress permits Postgres and DNS only. Detection happens at retrieval, by the
  reviewer; the stored declaration is what turns a blank into a failure
  attributable to the named custodian.

Residual stated rather than left to be found: a custodian that never held the
content can emit a false content_exists. audit-core validates the declaration's
shape, never its truth — the same class as omission at source, and not closed
by the chain, by attestation, or by T04/T06. A test asserts no egress to the
emitter exists, because that claim silently stops being true if one appears.

Cadence: reconciliation plus heartbeat is right for a mixed-volume source, with
both scoped per class rather than per source — a per-source heartbeat is
satisfied by the high-volume presentation stream and says nothing about a quiet
month of dispositions. Bound: a compromised emitter suppresses the event and
its own count together.

Also recorded: commitment-only satisfies non-alteration and never
reconstructability, in this repo's documents as in theirs; and tenant
provenance under GH-DEC-2026-013 lands in the registration record, not the
envelope, since audit-core checks a value the credential may write rather than
resolving an identity claim.

No secret was created and no production manifest applied.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nb7Q6ZmXppNDkTWytfYqfv

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 2069992@bnt-lap001
Assistant-Session: 167dd7f8-2a25-4be1-aa46-3b6f1a5f94c6
2026-09-10 15:15:35 +02:00

99 lines
3.9 KiB
Python

from pathlib import Path
ROOT = Path(__file__).parents[1]
def test_whitehat_ingress_is_bound_to_namespace_and_target_labels():
documents = (ROOT / "deploy" / "networkpolicies.yaml").read_text().split("\n---\n")
policy = next(
document
for document in documents
if "name: audit-core-whitehat-ingress" in document
)
# Both selectors must remain in the same `from` peer. Splitting them into
# two list items changes AND to OR and would admit every pod in either set.
expected_peer = """ - namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: whitehat
podSelector:
matchLabels:
whitehat.security/plane: \"true\"
whitehat.security/target: audit-core"""
assert expected_peer in policy
assert policy.count(" - namespaceSelector:") == 1
assert " - {protocol: TCP, port: 8080}" in policy
def test_approval_engine_ingress_is_bound_to_namespace_and_pod_labels():
"""AUDIT-WP-0009-T09. A load-bearing source gets a narrow rule, not a wide one."""
documents = (ROOT / "deploy" / "networkpolicies.yaml").read_text().split("\n---\n")
policy = next(
document
for document in documents
if "name: audit-core-approval-engine-ingress" in document
)
# One `from` peer holding both selectors. Two list items would be OR, and
# would admit every pod in the approval-engine namespace plus every pod
# anywhere carrying the app label.
expected_peer = """ - namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: approval-engine
podSelector:
matchLabels:
app.kubernetes.io/name: approval-engine"""
assert expected_peer in policy
assert policy.count(" - namespaceSelector:") == 1
assert " - {protocol: TCP, port: 8080}" in policy
def test_user_engine_sender_ingress_is_unchanged_by_the_new_sender():
"""glas-harness asked for user-engine's sender to stay as it is."""
documents = (ROOT / "deploy" / "networkpolicies.yaml").read_text().split("\n---\n")
policy = next(
document
for document in documents
if "name: audit-core-sender-ingress" in document
)
assert "kubernetes.io/metadata.name: user-engine" in policy
assert "approval-engine" not in policy
def test_informed_decision_ingress_is_bound_to_namespace_and_pod_labels():
"""AUDIT-WP-0009-T11. A second load-bearing source gets the narrow rule too."""
documents = (ROOT / "deploy" / "networkpolicies.yaml").read_text().split("\n---\n")
policy = next(
document
for document in documents
if "name: audit-core-informed-decision-ingress" in document
)
expected_peer = """ - namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: informed-decision
podSelector:
matchLabels:
app.kubernetes.io/name: informed-decision"""
assert expected_peer in policy
assert policy.count(" - namespaceSelector:") == 1
assert " - {protocol: TCP, port: 8080}" in policy
def test_no_egress_to_informed_decision_is_created():
"""The custody declaration is carried, never dereferenced.
GH-DEC-2026-014 limit 3 is met by storing an attributable declaration, not
by audit-core retrieving content. If an egress rule to the emitter ever
appears, the claim in docs/informed-decision-source-registration.md that
audit-core performs no retrieval has silently stopped being true.
"""
documents = (ROOT / "deploy" / "networkpolicies.yaml").read_text().split("\n---\n")
egress = next(
document for document in documents if "name: audit-core-egress" in document
)
assert "informed-decision" not in egress
assert "approval-engine" not in egress
# Postgres and DNS only.
assert egress.count(" - namespaceSelector:") == 2