Files
home-network-k3s-impl/conformance/tests/l3-fault-injection/default-deny-failclosed/fixtures/allowed-pair.yaml
T
jakman85andClaude Opus 4.8 1bf8e3bfc4 feat(conformance): implement L3 default-deny-failclosed (R-NET-01/02, fault injection)
Was a scaffold (fixture TODO, fault-injection a no-op echo). Implemented against the
live datapath: fixtures/allowed-pair.yaml = default-deny baseline + source + dest(:8080)
+ the sole explicit allow. The test verifies source->dest works (ALLOWED_OK), then
REVOKES both halves of the allow (real fault: kubectl delete networkpolicy), and asserts
connectivity fails CLOSED (FAIL_CLOSED_OK) while DNS still resolves (DNS_OK). Proves
default-deny is datapath-enforced and fails closed on revocation. DNS check asserts the
resolved answer, since busybox nslookup exits non-zero on a successful forward lookup.
PASSES (74.8s).

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-08-17 17:42:34 -05:00

109 lines
3.0 KiB
YAML

# =============================================================================
# Fixtures for the default-deny FAIL-CLOSED fault-injection test (R-NET-01/02).
# Applied into the per-test namespace chainsaw creates (hermetic, self-cleaned).
#
# Models: a namespace default-deny baseline + ONE explicit allow that is the SOLE
# reason source can reach dest:8080. The test later DELETES the allow (fault) and
# proves connectivity drops to fail-closed while DNS still resolves.
#
# Standard Kubernetes NetworkPolicy (Cilium enforces it). No readinessProbe on the
# pods: under default-deny the kubelet TCP probe (node->pod) is dropped, so a
# probe-bearing pod would never go Ready — without a probe the container is Ready
# once running, which is all the test needs (K2 finding).
# =============================================================================
---
# --- Default-deny baseline: deny all ingress+egress, allow only DNS egress. -----------
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-baseline
spec:
podSelector: {}
policyTypes: [Ingress, Egress]
ingress: []
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
---
# --- The ONE explicit allow (source -> dest tcp/8080): the two matching halves a
# real rendered dependency produces (egress permit on source, ingress on dest).
# Deleting BOTH is the fault injection.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-source-to-dest-egress
spec:
podSelector:
matchLabels: { app: source }
policyTypes: [Egress]
egress:
- to:
- podSelector:
matchLabels: { app: dest }
ports:
- protocol: TCP
port: 8080
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-source-to-dest-ingress
spec:
podSelector:
matchLabels: { app: dest }
policyTypes: [Ingress]
ingress:
- from:
- podSelector:
matchLabels: { app: source }
ports:
- protocol: TCP
port: 8080
---
# --- source: an idle probe pod (nc is issued via kubectl exec). ------------------------
apiVersion: v1
kind: Pod
metadata:
name: source
labels: { app: source }
spec:
containers:
- name: app
image: busybox:1.36.1
command: ["sh", "-c", "sleep 3600"]
---
# --- dest: LISTENS on 8080 so a block is caused by POLICY, not a missing listener. -----
apiVersion: v1
kind: Pod
metadata:
name: dest
labels: { app: dest }
spec:
containers:
- name: app
image: busybox:1.36.1
command: ["httpd", "-f", "-p", "8080", "-h", "/tmp"]
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: dest
spec:
selector: { app: dest }
ports:
- name: p8080
port: 8080
targetPort: 8080