Envoy Gateway Wasm filter
A proxy-wasm filter loaded by an EnvoyExtensionPolicy that gates protected routes on a verified Presence proof or session and fails closed, with no application changes.
Fetch the published module and verify its checksum
terminal
curl -O https://cdn.decionis.com/envoy-filter/1.0.0/presence_envoy_filter.wasmcurl -O https://cdn.decionis.com/envoy-filter/1.0.0/presence_envoy_filter.wasm.sha256shasum -a 256 -c presence_envoy_filter.wasm.sha256Load the filter on a protected route
presence-extension-policy.yaml
apiVersion: gateway.envoyproxy.io/v1alpha1kind: EnvoyExtensionPolicymetadata: name: presencespec: targetRefs: - group: gateway.networking.k8s.io kind: HTTPRoute name: checkout wasm: - name: presence rootID: presence code: type: HTTP http: url: https://cdn.decionis.com/envoy-filter/1.0.0/presence_envoy_filter.wasm sha256: fb62f681b08368e2dc4c83ca86efb68a895284fc136759a013ed7550cb333de8 config: cluster: presence_api authority: presence.decionis.com api_secret: "presence_sk_••••••••" tenant_id: tn_prod_998124 protected_routes: /api/v1/checkout/*Add the Presence API cluster the filter calls
presence-api-cluster.yaml
apiVersion: gateway.envoyproxy.io/v1alpha1kind: EnvoyPatchPolicymetadata: name: presence-api-clusterspec: targetRef: group: gateway.networking.k8s.io kind: Gateway name: presence-gateway type: JSONPatch jsonPatches: - type: type.googleapis.com/envoy.config.cluster.v3.Cluster name: presence_api operation: op: add path: "" value: name: presence_api type: STRICT_DNS connect_timeout: 5s load_assignment: cluster_name: presence_api endpoints: - lb_endpoints: - endpoint: address: socket_address: address: presence.decionis.com port_value: 443 transport_socket: name: envoy.transport_sockets.tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext sni: presence.decionis.comEnable the patch API and watch the gate fire
terminal
helm upgrade --install eg oci://docker.io/envoyproxy/gateway-helm \ --version v1.8.3 -n envoy-gateway-system --create-namespace \ --set config.envoyGateway.extensionApis.enableEnvoyPatchPolicy=true curl -i -X POST https://gateway.example.com/api/v1/checkout/confirm# HTTP/1.1 403 Forbidden# {"code":"PRESENCE_TOKEN_MISSING"}Attach the filter to the route, then give it a path to Presence
- 01
An EnvoyExtensionPolicy loads the Presence module onto an HTTPRoute or Gateway. Envoy Gateway passes the config block to the module verbatim, so the same fields configure raw Envoy, an Istio WasmPlugin, and Envoy Gateway.
- 02
On POST, PUT, and DELETE requests to a protected route, the filter drops client-supplied x-presence-* headers, verifies a short-lived ES256 proof locally against the published JWKS or calls POST /v1/verify, and forwards only gateway-computed headers.
- 03
Envoy Gateway builds clusters from the Gateway API graph, so an EnvoyPatchPolicy adds the presence_api cluster the filter dispatches to. A missing token returns 403, and an unreachable verification authority returns 503 with no upstream request.
Verify the implementation
Presence is listed in the Envoy Gateway ecosystem directory as an EnvoyExtensionPolicy-attached proxy-wasm filter.
Envoy Gateway ecosystem →The module is built in CI from a pinned Rust toolchain with host paths remapped, so the published bytes reproduce from source. CI rebuilds it and refuses any change that alters a published version.
SHA-256 →Verified end to end on kind with Envoy Gateway v1.8.3: a tokenless protected write returns 403, a valid local ES256 proof and a verified token reach the upstream, a tampered proof returns 403, and unprotected paths pass through.
Local proof verification uses the published ES256 keys. An expired, foreign-tenant, or tampered proof falls through to the token gate, which never converts an API failure into a pass.
Edge proof keys (JWKS) →
Current limits
- Published module paths are versioned and immutable, and there is no latest alias. Pin the SHA-256 from the .sha256 sidecar; a new build ships under a new version, so upgrading is a deliberate policy change.
- EnvoyPatchPolicy is disabled by default. Enable extensionApis.enableEnvoyPatchPolicy on the EnvoyGateway config, or expose the Presence API through an HTTPRoute and point cluster at the generated cluster name.
- Only POST, PUT, and DELETE requests on protected_routes are gated; GET requests and unprotected paths pass through. Verification is bounded by verify_timeout_ms (default 500) and fails closed with 503 and retry-after: 1.
- The filter consumes Presence verdicts; it is an enforcement point, not a decision authority. Token minting and widget injection stay at the frontend edge.
One next step
Continue with the executable path.