Skip to content

Test/crd lifecycle e2e - #11

Merged
dvrkn merged 5 commits into
mainfrom
test/crd-lifecycle-e2e
Jun 30, 2026
Merged

dvrkn merged 5 commits into
mainfrom
test/crd-lifecycle-e2e

Conversation

@dvrkn

@dvrkn dvrkn commented Jun 30, 2026

Copy link
Copy Markdown
Owner

No description provided.

dvrkn added 5 commits June 30, 2026 09:56
…solation)

Add Tests 7-9 to test/crd.sh, exercising the three CR-lifecycle semantics the
roadmap called out, in a dedicated `life` namespace isolated from earlier state:

- Test 7 (hot-reload): apply an EgressPolicy denying CIDR-A, then `kubectl apply`
  the same CR denying CIDR-B instead. Assert CIDR-A reopens (old rule lifted live
  via the Programmer's reconcile) AND CIDR-B closes (new rule applied live) — no
  pod or agent restart. CIDR rules program directly into the LPM map (no
  DNS-learning race), so the flip is deterministic after the re-walk window.
- Test 8 (deletion lifts enforcement): delete the CR, assert the blocked IP is
  reachable again (DeleteFunc -> rebuild -> reconcile clears the map entry).
- Test 9 (invalid CR dropped, rest keep enforcing): with a valid deny in effect,
  add an invalid CR (bad CIDR). Assert the operator marks only the invalid one
  Accepted=False while the valid one stays Accepted=True, AND the agent keeps
  enforcing the valid policy — crdsource drops just the bad CR from the aggregate,
  never the whole node. This closes the gap in Tests 1/2, which checked only
  operator status, not the datapath "rest keep enforcing" guarantee.

Add a `reach` helper (curl -sk, fresh connection per call so it reflects current
map state; -k measures datapath reachability, not cert trust) and note the new
coverage in the script header. Update ROADMAP.md: CR lifecycle e2e is now done;
aggregation interactions and more-dimensions checks remain.

Verified green end-to-end on the arm64 k3d box (all 9 crd.sh tests PASS).
… precedence)

Add Tests 10-12 to test/crd.sh in a dedicated `merge` namespace, asserting how
multiple policies governing ONE pod combine — the aggregation interactions the
roadmap called out:

- Test 10 (union): two EgressPolicies in one namespace, both selecting mp, each
  enforce their own deny — mp is blocked to both CIDRs while an unlisted control
  dest stays reachable (the merge is a union of rules, not a blanket deny).
- Test 11 (cross-scope stacking): the node-wide Test-5 ClusterEgressPolicy and
  mp's own namespaced EgressPolicy both bite mp at once (a cluster-scoped and a
  namespace-scoped dest denied simultaneously).
- Test 12 (most-specific wins): adding an Allow for a /32 carves a hole through a
  broader /24 Deny — the host is reachable while the rest of the /24 stays denied.
  The Allow CR sorts before the Deny CR by name, so the engine's first-match and
  the kernel's LPM longest-prefix agree.

These deliberately avoid an overlapping cluster-vs-namespace Allow/Deny on the
SAME CIDR: verdict_for consults the per-pod (namespaced) map entry before the
node-global (cluster) one, so engine first-match-wins and kernel
most-specific-wins disagree there by design — not a behavior to pin in an e2e.

Verified green end-to-end on the arm64 k3d box (all 12 crd.sh tests PASS).
The roadmap had drifted into describing completed work (a "Today" section plus
"X is now covered" notes on the e2e bullet). Make it forward-looking only:

- ROADMAP.md: drop the "Today" section (current state already lives in README +
  docs/) and the "now covered" prose; the e2e bullet now lists only the remaining
  aggregation/posture/dimension cases. Promote the two planning groups to top-level
  headings since the whole file is the plan now.
- docs/install.md: expand the Tests section to document what the suites actually
  assert today — including the CR-lifecycle and policy-merge coverage in crd.sh and
  the unit/envtest entry points — so "what's done" is recorded where it belongs.
Testing isn't part of installation. Move the Tests section into a dedicated
docs/tests.md (host e2e, k3d e2e, unit/envtest, and a CI note covering what each
suite asserts) and wire it into the site: nav + footer (base.html), a "Dig in"
card and a trimmed Install card (index.html), the per-page title (_config.yml),
the README nav, and the ROADMAP coverage pointer. install.md keeps a one-line
cross-reference.
…ms, lockdown, log mode)

Add Tests 13-17 to test/crd.sh, finishing the roadmap's e2e-coverage tranche:

- Test 13 cross-namespace isolation: a deny in namespace A never affects namespace
  B's pods (and vice versa).
- Test 14 domain deny via CRD: a domains: rule blocks the resolved IPs through the
  DNS->IP learner (prime + retry).
- Test 15 deferred dimensions logged-not-dropped: a port-only / IPv6 / L7 rule is
  evaluated for log/metrics but not dropped — HTTPS to a :443 dest still succeeds
  under a deny-:443 rule, and the agent logs the un-enforceable count.
- Test 16 node-wide lockdown: a podSelector-less ClusterEgressPolicy
  defaultAction:Deny flips the GLOBAL default; an internal-CIDR + udp:53 allowlist
  keeps DNS and in-cluster control-plane egress up while external is denied.
- Test 17 log mode via CRD: with enforceMode=log a CRD deny annotates the verdict
  on the event without dropping the connection.

Test 16 needed a non-obvious harness: a true node-global default-deny disrupts the
apiserver->kubelet:10250 channel, so `kubectl exec` itself fails while it is active.
Probing egress via exec during the lockdown therefore measures the exec failure, not
the datapath. Instead a detached in-pod prober (started before the lockdown, immune
to the exec channel) records reachability to a file every 2s; after the lockdown is
lifted the rows stamped during the lockdown window are asserted. The host clock ==
the pod clock (k3d shares the kernel), so the window filter is exact. Verified: the
window rows are uniformly allow=OK deny=FAIL dns=OK.

Also fix the Test 15 deferred-log check: `kubectl logs -l <selector>` silently caps
--tail at 10 lines (buried under JSON event spam), so query the named pod with
--since and retry across a re-walk tick.

docs/tests.md: document the new crd.sh coverage. ROADMAP.md: drop the (now complete)
e2e-coverage item from operator hardening.

Verified green end-to-end on the arm64 k3d box (all 17 crd.sh tests PASS).
@dvrkn
dvrkn merged commit 0959c9a into main Jun 30, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant