Istio WASM Integration
The Coraza Kubernetes Operator integrates with Istio by deploying a WebAssembly (WASM) plugin into Envoy proxies attached to Kubernetes Gateways. This page explains how that integration works.
How Istio WasmPlugin Works
Istio provides a WasmPlugin resource that instructs Envoy to load and execute a WASM module. The operator creates WasmPlugin resources to inject the Coraza WAF into the request processing pipeline.
When a WasmPlugin is applied, Istio:
- Downloads the WASM binary from the specified OCI registry.
- Loads it into the Envoy proxy as a filter.
- Routes HTTP requests through the WASM filter before forwarding them to the backend.
The coraza-proxy-wasm Plugin
The WASM module used by the operator is coraza-proxy-wasm. It is a purpose-built Envoy WASM filter that:
- Runs the Coraza WAF engine inside Envoy.
- Polls the operator’s RuleSet cache server for rule updates.
- Evaluates incoming HTTP requests against the loaded rules.
- Blocks or allows requests based on rule outcomes.
The plugin is distributed as an OCI image. The operator uses a built-in default image reference, which can be overridden per Engine or globally via the --default-wasm-image flag.
WasmPlugin Resource Generation
When an Engine is reconciled, the operator creates a WasmPlugin resource using server-side apply. The WasmPlugin:
- References the WASM OCI image.
- Targets Gateway pods using the label selector derived from the Engine’s
target.name(via the GEP-1762gateway.networking.k8s.io/gateway-namelabel). - Passes configuration to the WASM plugin, including the cache server URL and the RuleSet key.
- Sets the failure policy (fail-open or fail-closed).
The operator watches WasmPlugin resources it creates and filters out update events to prevent reconcile loops. Only create and delete events trigger re-reconciliation.
Target Selection and Gateway Matching
The Engine’s target field identifies the Gateway by name. The operator derives the workload label selector using the GEP-1762 convention — Gateway API implementations label Gateway pods with:
gateway.networking.k8s.io/gateway-name: <gateway-name>
The target.provider field (default: Istio) identifies the infrastructure provider, which determines which driver types are valid for the Engine. This field is immutable after creation — to switch providers, create a new Engine resource. This ensures the controller does not need to clean up and recreate child resources (WasmPlugin, NetworkPolicy, ServiceAccount tokens) from the previous driver.
Poll-Based Rule Updates
The WASM plugin running inside Envoy polls the operator’s cache server at the interval specified by pollIntervalSeconds (default: 15 seconds). The polling flow is:
- The plugin sends
GET /rules/{namespace/name}/latestto check the current UUID. - If the UUID has changed since the last fetch, the plugin sends
GET /rules/{namespace/name}to download the new rules. - The plugin loads the new rules and begins enforcing them on subsequent requests.
This design allows rule updates without restarting Envoy or the Gateway pods.
Cache Server Connectivity
For the WASM plugin to reach the cache server, the operator:
- Creates a ServiceEntry and DestinationRule to make the cache server discoverable within the Istio mesh (when
--operator-nameis set). - Creates a NetworkPolicy to allow Gateway pods to connect to the cache server port.
- Issues a ServiceAccount token for the WASM plugin to authenticate with the cache server.
Custom WASM Images
Users can build and deploy custom WASM plugins by:
- Building the
coraza-proxy-wasmmodule from source using TinyGo. - Packaging it as an OCI image.
- Specifying the image in the Engine’s
spec.driver.wasm.imagefield.
If the image is in a private registry, an imagePullSecret can be specified to provide authentication credentials.