From 19a2c5e4a5cfc4b30eb3bd1f427514ffb4392b09 Mon Sep 17 00:00:00 2001 From: Justin Klein Date: Mon, 19 Oct 2026 13:07:40 +0000 Subject: [PATCH] test(networkpolicy): tie the ambient probe-source half to probeSources, not to a chart name Gitea #143. Five charts offer no networkPolicy.probeSources - their probes are exec probes and put no packet on the network - so for them 169.254.7.127/32 would be an ipBlock that matches nothing, which is exactly the strict-looking empty rule this script exists to catch. Assertion 7 now exempts them on the absence of that value, the same conditionality assertion 4 and the overlay guard already use, and records the exemption as a held assertion rather than as silence. Also names two limits of assertion 7 in its header: assertions 1, 3, 4 and 5 are not re-run on the switched-on render, and assertion 3's omission is the interesting one - with probeSources empty, 15008 sits in a rule with no "from" that neither of assertion 3's two justifications covers. Teaching it a third would mean writing a rule against a guess, because where ztunnel dials from cannot be settled until a namespace joins the mesh. --- ci/run-networkpolicy-test.sh | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/ci/run-networkpolicy-test.sh b/ci/run-networkpolicy-test.sh index 19398fb..fd77156 100755 --- a/ci/run-networkpolicy-test.sh +++ b/ci/run-networkpolicy-test.sh @@ -1283,6 +1283,24 @@ done # test did not identify. A chart whose policy stops following the convention # fails here instead of silently losing its coverage. # +# TWO LIMITS OF THIS ASSERTION, named rather than left to be discovered: +# +# - ASSERTIONS 1, 3, 4 AND 5 ARE NOT RE-RUN ON THE SWITCHED-ON RENDER. Only +# assertion 2's subject matter is, because that is the one the exception +# touches. Assertion 3 is the interesting omission: with the switch on and +# probeSources empty, 15008 sits in a rule with no "from", and assertion 3's +# two justifications for an open rule - a network probe addresses the port, +# or a NodePort publishes it - cover neither. That is intended rather than +# overlooked. The port has to be reachable from wherever ztunnel dials from, +# and that address is not knowable from a render: ztunnel runs with its own +# pod IPs in istio-system (measured 2026-10-19, no hostNetwork on the +# DaemonSet, Istio 1.30.6), but whether a peer of its own is needed cannot +# be settled until a namespace actually joins the mesh. Teaching assertion 3 +# a third justification before then would be a rule written against a guess. +# - THE PROBE-SOURCE HALF IS CONDITIONAL ON THE CHART OFFERING probeSources, +# like assertion 4 and the overlay guard. A chart with exec-only probes has +# no probe on the network to redirect, so the ipBlock would match nothing. +# # BUILT INTO THIS SCRIPT rather than added as a new test with its own pipeline # job - the same decision as assertion 6 for #136, and here it is stronger than # convenience. The exception WEAKENS assertion 2, so it belongs next to it: a @@ -1551,9 +1569,26 @@ else: % (gate, PORT)) # The inseparability of the two halves, where the render can reach it. + # + # Conditional on the chart OFFERING probeSources, exactly as assertion 4 and + # the overlay guard are, and for the same reason: a chart with exec-only + # probes (valkey, minecraft-server) puts no probe packet on the network at + # all, so there is no probe to redirect and 169.254.7.127/32 would be an + # entry that matches nothing - the kind of strict-looking, empty rule this + # script exists to catch. Those charts render the port half only, and say so + # in their values.yaml. + offers_probe_sources = bool(re.search( + r"^\s*probeSources\s*:", values_yaml, re.M)) for name, i, rule in carriers: if not rule.get("from"): continue + if not offers_probe_sources: + ok("%s ingress[%d] carries port %d in a source-restricted rule and " + "no ipBlock %s - correct here, because this chart offers no " + "networkPolicy.probeSources: its probes put no packet on the " + "network, so there is no redirected probe to allow" + % (name, i, PORT, CIDR)) + continue if CIDR in cidrs_of(rule): ok("%s ingress[%d] carries port %d AND the ipBlock %s in the same " "\"from\" list - the two halves of the switch are inseparable, "