kubeWAF is under active development — feedback and stars on GitHub are very welcome!
kubeWAFkubeWAF
kubeWAFmodsecurity-proxy-wasmpow-proxy-wasm

Architecture

Control plane, data plane, ECDS, and high availability

kubeWAF is a Kubernetes operator that turns structured security CRDs into live WAF configuration on Envoy-based data planes. Evaluation runs in modsecurity-proxy-wasm; you can optionally put pow-proxy-wasm (PoW challenge) in front via spec.challenge.

Configuration is pushed over Envoy’s Extension Config Discovery Service (ECDS); each gateway product only receives a thin filter slot.

Big picture

Control plane vs data plane

PlaneResponsibility
Kubernetes APIDesired state: rules, sets, attachment (WAF)
kubeWAF operatorResolve rules → SecLang → portable config; multi-module wasm serve; ECDS; provider slots
Gateway control planeRouting, TLS, listeners (Envoy Gateway / Istio / Cilium)
Envoy + Wasm enginesChallenge (optional) then modsecurity-proxy-wasm evaluates traffic

kubeWAF does not replace the gateway’s ADS (LDS/RDS/CDS). It only owns extension config (ECDS) and installs a small filter that points at that ECDS resource.

Operator internals

Why this split?

Envoy (and Envoy Gateway) load-balance against the operator Service. If only the leader held ECDS config, non-leader pods would return empty snapshots and requests would fail or bypass WAF randomly. Dataplane servers and the sync controller therefore run on every pod; Kubernetes writes stay on the leader.

Portable config artifact

After rule resolution, every path produces the same intermediate object — now with an ordered filter list (optional Challenge, then WAF engine):

The ECDS resource type is always:

type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm

with modsecurity-proxy-wasm plugin JSON of the form (see schemas/waf-plugin-config.json):

{
  "mode": "kubewaf",
  "config_id": "kubewaf/shop/shop-waf",
  "allow_fallback": false,
  "default_directives": "default",
  "directives_map": {
    "default": [
      "Include @kubewaf-defaults",
      "SecRuleEngine On",
      "SecDebugLogLevel 3",
      "Include @crs-setup-conf",
      "Include @owasp_crs/*.conf",
      "..."
    ]
  },
  "metric_labels": {
    "waf_namespace": "shop",
    "waf_name": "shop-waf",
    "engine": "modsecurity",
    "owner": "modsecurity-proxy-wasm",
    "team": "payments"
  },
  "metrics": { "enabled": true, "per_rule_id": true, "rule_tags": true },
  "block": { "message": "blocked by kubeWAF" }
}

End-to-end request path

Multi-provider slots

ProviderSlot resourceHow filter is installed
EnvoyGateway(none owned by kubeWAF)EG Extension Server hooks mutate xDS
IstioEnvoyFilterconfig_discovery → external ECDS
CiliumCiliumEnvoyConfigCEC clusters + attachment to Service

See Data plane (ECDS) for configuration details.

Core CRDs

CRDPurposeMaturity
SecRuleIndividual security rule (structured YAML)Stable
RuleSetNamed collection (selectors, recursion, allowedRules)Stable
WAFAttach RuleSets to a gateway provider + push ECDSStable
WAFInstanceStandalone proxy / sidecar (future)Alpha

Data flow (lifecycle)

  1. AuthorSecRule / SecAction (or CRS converter).
  2. AggregateRuleSet selects rules (names or labels).
  3. AttachWAF references RuleSets and a provider.
  4. Resolve — flatten graph, enforce namespace policy, back-references (leader).
  5. Publish — every pod updates its ECDS snapshot.
  6. Slot — leader ensures EnvoyFilter / CEC / EG index.
  7. Enforce — modsecurity-proxy-wasm evaluates traffic.

Rule content changes bump the ECDS snapshot only; platform slots are not rewritten unless provider or ECDS endpoint settings change.

Operator ports and Service

PortProtocolConsumers
18001gRPC ECDSEnvoy (kubewaf_ecds cluster)
5005gRPC EG extension APIEnvoy Gateway only
18002HTTPEnvoy fetching the .wasm binary

Security model

  • Rules are namespaced.
  • RuleSet.allowedRules controls who may contribute rules (Same / All / Selector).
  • Only RuleSets attach to a WAF (not raw SecRules).
  • Platform teams own RuleSets + WAF attachment; app teams own SecRules in their namespace.

Status and conditions

kubectl get waf -o wide
kubectl describe waf shop-waf
Field / conditionMeaning
ReadyECDS published and slot ensured
ReferencesResolvedAll RuleSet refs resolved
status.providerEnvoyGateway / Istio / Cilium
status.engineActive WAF engine (e.g. ModSecurity)
status.challengeEnabledPoW filter installed
status.ecdsResourceNamee.g. kubewaf/shop/shop-waf
status.ecdsVersionSnapshot generation counter
status.slotKindExtensionServer / EnvoyFilter / CiliumEnvoyConfig

Current limitations

  • WAFInstance does not yet deploy proxies.
  • No validating admission webhooks yet.
  • Cilium full L7 filter-chain merge depends on the cluster’s Envoy build (CEC slot is always created).
  • Envoy Gateway requires extensionManager configured to call kubeWAF.

Next

On this page