# ============================================================================= # L3 FAULT-INJECTION SCAFFOLD — Default-deny fail-closed (R-NET-01, R-NET-02) # *SAFETY-CRITICAL* # Catalog/spec: docs/14 R-TEST-05 lists default-deny among the behaviors that MUST # be proven by fault-injection (not happy-path). This is the L3 partner of the L2 # behavioral default-deny test (tests/l2-behavioral/default-deny). # # GIVEN a source that CAN reach a dest only because of an explicit allow rule, # WHEN the allow rule is REVOKED (fault injection: delete the CiliumNetworkPolicy), # THEN connectivity drops to fail-closed within a bounded window (revocation takes # effect immediately — the baseline denies once the allow is gone), while DNS # still resolves. # # This proves the deny is enforced by the live datapath, not merely declared, and # that removing access fails closed rather than lingering open. # # STATUS: scaffold — needs T-2.2 (baseline) + T-2.3 (rendered allow) + T-3.0 harness. # ============================================================================= apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: name: default-deny-failclosed labels: conformance.home.k3s/R-NET-01: "true" conformance.home.k3s/R-NET-02: "true" annotations: conformance.home.k3s/requirements: "R-NET-01, R-NET-02" conformance.home.k3s/layer: "L3" conformance.home.k3s/safety-critical: "true" conformance.home.k3s/intent: >- Revoking an allow rule drops connectivity to fail-closed immediately; DNS still works — the datapath enforces default-deny, not just declares it. spec: steps: - name: given-source-allowed-to-dest try: - apply: file: fixtures/allowed-pair.yaml # TODO(T-2.3): source+dest+allow policy - script: content: | set -euo pipefail kubectl -n "$NAMESPACE" exec source -- nc -z -w 3 dest 80 && echo ALLOWED_OK check: { ($stdout =~ 'ALLOWED_OK'): true } - name: when-revoke-allow-then-fail-closed try: # FAULT INJECTION: delete the allow policy; baseline default-deny remains. - script: content: | set -euo pipefail echo "TODO(T-3.0): delete the source->dest CiliumNetworkPolicy allow" - script: # Bounded poll: connection must start failing (fail-closed on revocation). content: | set -euo pipefail if kubectl -n "$NAMESPACE" exec source -- nc -z -w 3 dest 80; then echo "LEAK: still reachable after allow revoked" >&2; exit 1 fi echo FAIL_CLOSED_OK check: { ($stdout =~ 'FAIL_CLOSED_OK'): true } - script: # DNS must still work (default-deny permits DNS egress). content: | set -euo pipefail kubectl -n "$NAMESPACE" exec source -- nslookup kubernetes.default && echo DNS_OK check: { ($stdout =~ 'DNS_OK'): true } finally: - script: content: 'echo "cleanup via chainsaw namespace teardown"'