Skip to content

fix(waf): keep the WAF controller wired to tear down EnvoyExtensionPolicies on disable#4989

Open
electricjesus wants to merge 1 commit into
tigera:masterfrom
electricjesus:seth/waf-eep-teardown
Open

fix(waf): keep the WAF controller wired to tear down EnvoyExtensionPolicies on disable#4989
electricjesus wants to merge 1 commit into
tigera:masterfrom
electricjesus:seth/waf-eep-teardown

Conversation

@electricjesus

Copy link
Copy Markdown
Member

Description

The operator half of EV-6751. Disabling Gateway WAF (GatewayAPI spec.extensions.waf.state: Disabled) dropped the applicationlayer controller from kube-controllers ENABLED_CONTROLLERS and stripped its envoyextensionpolicies …delete RBAC in the same reconcile that tore down the rest of the WAF surface. So the controller never got the chance, or the permission, to delete the EnvoyExtensionPolicy objects it had generated. The gateway kept enforcing WAF after WAF was "off". That is the ordering race behind EV-6751: the operator removed the thing that was supposed to clean up, at the same moment it asked for cleanup.

What changed

Gate the applicationlayer controller enablement and its WAF / Gateway-API / EnvoyExtensionPolicy RBAC on a new GatewayAPIPresent (the GatewayAPI CR exists) rather than on waf.state == Enabled. GatewayAPIPresent is a superset of WAFGatewayExtensionEnabled — you can't enable WAF without the CR present, so in practice they move together on enable, but GatewayAPIPresent stays true through a disable.

Result: the WAF controller stays wired, with identical RBAC, whether WAF is enabled or disabled, so it can tear down its EEPs when disabled. A new WAF_GATEWAY_EXTENSION_ENABLED env on the kube-controllers Deployment tells the reconciler whether to program (enabled) or de-program (disabled).

The active WAF surface stays gated on waf.state == Enabled: WASM_* env vars, the admission webhook + its cert, wasm image resolution, and the webhook NetworkPolicy. Toggling waf.state causes no ClusterRole churn, since the WAF RBAC set is identical enabled vs disabled.

Because the controller only watches Gateway API / Envoy Gateway CRDs when they exist, gating on GatewayAPIPresent keeps it off on clusters that never installed Gateway API (where those CRDs are absent). The toggle-disable path this fixes keeps Gateway API installed, so the CRDs the controller watches are present.

Pairs with

calico-private https://github.com/tigera/calico-private/pull/12568 — the reconciler change that reads WAF_GATEWAY_EXTENSION_ENABLED and tears down on disable. This operator PR is inert without it, and it is inert without this (the reconciler never sees the disable signal, and gets torn down before it can clean up). Land them together.

Deferred (follow-up)

A belt-and-suspenders operator-side final GC — delete leftover EEPs by label (app.kubernetes.io/name=calico-waf) cluster-wide — for the hard-uninstall case where Gateway API itself is removed and no in-cluster controller can run. Not needed for the toggle-disable scenario this PR fixes; called out so it isn't lost.

Test plan

  • go test ./pkg/render/kubecontrollers/ — green (44 specs). New spec: WAF disabled but Gateway API present renders the applicationlayer controller, WAF_GATEWAY_EXTENSION_ENABLED=false, and the envoyextensionpolicies delete RBAC, but no WASM_IMAGE / webhook cert.
  • Existing WAF-enabled specs updated to set GatewayAPIPresent alongside WAFGatewayExtensionEnabled (the production invariant).
  • gofmt + go vet clean; container pre-commit hook passed.
  • Cluster verification (enable → disable → confirm EEP torn down + no enforcement) pending alongside the calico-private PR, on matched dev images.

Release Note

Fixed a bug where disabling Gateway WAF left the generated EnvoyExtensionPolicy in place so the gateway kept enforcing WAF. The WAF controller now stays running while disabled so it can tear down what it generated.

…licies on disable

Disabling Gateway WAF (GatewayAPI spec.extensions.waf.state: Disabled) removed
the applicationlayer controller from kube-controllers ENABLED_CONTROLLERS and
stripped its envoyextensionpolicies delete RBAC in the same reconcile that tore
down the rest of the WAF surface. The controller never got the chance, or the
permission, to delete the EnvoyExtensionPolicies it had generated, so the gateway
kept enforcing WAF after WAF was turned off. That is the operator half of the
EV-6751 ordering race.

Gate the applicationlayer controller enablement and its WAF / Gateway-API / EEP
RBAC on GatewayAPIPresent (the GatewayAPI CR exists) rather than on
waf.state==Enabled. The controller now stays wired, with identical RBAC, whether
WAF is enabled or disabled, so it can tear down its EEPs when disabled. A new
WAF_GATEWAY_EXTENSION_ENABLED env tells the reconciler whether to program
(enabled) or de-program (disabled). The active surface (WASM_* env, admission
webhook, wasm image resolution, webhook NetworkPolicy) stays gated on
waf.state==Enabled.

Pairs with the calico-private reconciler change that reads
WAF_GATEWAY_EXTENSION_ENABLED and tears down on disable.

EV-6751

@vara2504 vara2504 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants