Documentation menu
Connect it yourselfHow do we enforce Presence at Envoy Gateway?

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.sha256

Load 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.com

Enable 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

  1. 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.

  2. 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.

  3. 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.

Create a sandbox