---
title: Kubernetes Istio
summary: null
url: >-
  https://www.fastly.com/documentation/guides/next-gen-waf/setup-and-configuration/kubernetes/kubernetes-istio
---

In this example, the Next-Gen WAF agent runs in a Docker sidecar and integrates directly with an Istio service mesh deployed on the application. In this configuration, you can configure the Next-Gen WAF to inspect east/west (service-to-service) web requests along with the traditional north/south (client to server) requests.

## Integrating the Next-Gen WAF agent

Refer to [Agent container image integration](https://www.fastly.com/documentation/guides/next-gen-waf/setup-and-configuration/kubernetes/kubernetes-agent/#integrating-the-next-gen-waf-agent)

## Integrating the Next-Gen WAF agent using EnvoyFilter

Istio uses the Envoy proxy as its data plane. As a result, you can use the Next-Gen WAF agent in gRPC mode the same way you would with a generic Envoy deployment. Installing and configuring the Next-Gen WAF agent is similar to a generic Envoy deployment, except Istio automatically deploys the Envoy proxy as a sidecar. You then configure Envoy using Istio's `EnvoyFilter`.

To add Next-Gen WAF support to an Istio based application deployment, you will need to:

- Add the `sigsci-agent` container to the pod, configured in Envoy gRPC listener mode.
- Add an `emptyDir{}` volume as a place for the `sigsci-agent` to write temporary data.
- Add an Istio `EnvoyFilter` for the app to allow the required Envoy configuration to be injected into the generated `istio-proxy` config.

### Add the Next-Gen WAF agent as an Envoy gRPC service

```yaml
...
      containers:
      - name: sigsci-agent
        image: signalsciences/sigsci-agent:latest
        imagePullPolicy: IfNotPresent
        env:
        - name: SIGSCI_ACCESSKEYID
          valueFrom:
            secretKeyRef:
              # This secret needs added (see docs on sigsci secrets)
              name: sigsci-agent-accesskey
              key: accesskeyid
        - name: SIGSCI_SECRETACCESSKEY
          valueFrom:
            secretKeyRef:
              # This secret needs added (see docs on sigsci secrets)
              name: sigsci-agent-accesskey
              key: secretaccesskey
        - name: SIGSCI_ENVOY_EXTPROC_ENABLED
          value: "true"
        # Configure the agent to use envoy gRPC on port 9999
        - name: SIGSCI_ENVOY_GRPC_ADDRESS
          value: localhost:9999
        # Comment out debug logging as appropriate
        - name: SIGSCI_DEBUG_LOG_VERBOSITY
          value: "3"
        - name: SIGSCI_DEBUG_LOG_WEB_INPUTS
          value: "2"
        - name: SIGSCI_DEBUG_LOG_WEB_OUTPUTS
          value: "2"
        - name: SIGSCI_DEBUG_LOG_UPLOADS
          value: "2"
        - name: SIGSCI_SERVER_FLAVOR
          value: "istio"
        ports:
        - containerPort: 9999
        securityContext:
          # The sigsci-agent container should run with its root filesystem read only
          readOnlyRootFilesystem: true
```

### Adding the Next-Gen WAF agent temp volume definition to the deployment

The agent temp volume needs to be defined for use by the other containers in the pod using the builtin `emptyDir: {}` volume type:

```yaml
...
      volumes:
      # Define a volume where sigsci-agent will write temp data and share the socket file,
      # which is required with the root filesystem is mounted read only
      - name: sigsci-tmp
        emptyDir: {}
```

### Adding the Istio EnvoyFilter object to inject the required Envoy config into the Istio proxy

Istio's `EnvoyFilter` object is a feature rich way of customizing the Envoy configuration for the `istio-proxy`.

Example `example-httpbin-sigsci_envoyfilter.yaml`:

```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: httpbin
---
apiVersion: v1
kind: Service
metadata:
  name: httpbin
  labels:
    app: httpbin
    service: httpbin
spec:
  ports:
  - name: http
    port: 8000
    targetPort: 80
  selector:
    app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
  labels:
    app: httpbin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
      version: v1
  template:
    metadata:
      labels:
        app: httpbin
        version: v1
    spec:
      serviceAccountName: httpbin
      containers:
      - image: docker.io/kennethreitz/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        ports:
        - containerPort: 80
      - name: sigsci-agent
        image: signalsciences/sigsci-agent:latest
        imagePullPolicy: IfNotPresent
        env:
        - name: SIGSCI_ACCESSKEYID
          valueFrom:
            secretKeyRef:
              # This secret needs added (see docs on sigsci secrets)
              name: sigsci-agent-accesskey
              key: accesskeyid
        - name: SIGSCI_SECRETACCESSKEY
          valueFrom:
            secretKeyRef:
              # This secret needs added (see docs on sigsci secrets)
              name: sigsci-agent-accesskey
              key: secretaccesskey
        - name: SIGSCI_ENVOY_EXTPROC_ENABLED
          value: "true"
        # Configure the agent to use envoy gRPC on port 9999
        - name: SIGSCI_ENVOY_GRPC_ADDRESS
          value: localhost:9999
        - name: SIGSCI_DEBUG_LOG_VERBOSITY
          value: "0"
        - name: SIGSCI_DEBUG_LOG_WEB_INPUTS
          value: "0"
        - name: SIGSCI_DEBUG_LOG_WEB_OUTPUTS
          value: "0"
        - name: SIGSCI_DEBUG_LOG_UPLOADS
          value: "0"
        - name: SIGSCI_SERVER_FLAVOR
          value: "istio"
        ports:
        - containerPort: 9999
        securityContext:
          # The sigsci-agent container should run with its root filesystem read only
          readOnlyRootFilesystem: true
      volumes:
          # Define a volume where sigsci-agent will write temp data and share the socket file,
          # which is required with the root filesystem is mounted read only
          - name: sigsci-tmp
            emptyDir: {}
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: httpbin-gateway
spec:
  gatewayClassName: istio
  listeners:
  - name: http
    port: 80
    protocol: HTTP
    allowedRoutes:
      namespaces:
        from: Same
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: httpbin
spec:
  parentRefs:
  - name: httpbin-gateway
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: httpbin
      port: 8000
---
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: httpbin
  namespace: default
spec:
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: SIDECAR_INBOUND
      listener:
        name: virtualInbound
        filterChain:
          filter:
            name: envoy.filters.network.http_connection_manager
    patch:
      operation: INSERT_FIRST
      value:
        name: envoy.filters.http.ext_proc
        typed_config:
          '@type': type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor
          failure_mode_allow: true
          message_timeout: 0.2s
          grpc_service:
            envoy_grpc:
              cluster_name: sigsci-agent-grpc
            timeout: 0.2s
          request_attributes:
            - "connection.tls_version"
            - "request.host"
            - "request.path"
            - "request.scheme"
            - "source.address"
          processing_mode:
            request_header_mode: SEND
            response_header_mode: SEND
            request_body_mode: BUFFERED
            response_body_mode: NONE
            request_trailer_mode: SKIP
            response_trailer_mode: SKIP
  - applyTo: CLUSTER
    patch:
      operation: ADD
      value:
        name: sigsci-agent-grpc
        type: STRICT_DNS
        connect_timeout: 0.5s
        http2_protocol_options: {}
        load_assignment:
          cluster_name: sigsci-agent-grpc
          endpoints:
          - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: 127.0.0.1
                    port_value: 9999

```

To use this example,

1. Follow Istio's [getting started](https://istio.io/latest/docs/setup/getting-started/#download) guide to install the default profile,
   add a namespace label to instruct Istio to automatically inject Envoy sidecar proxies, and Install the Gateway API CRDs.

The application can then be deployed as you normally would with Istio. For example:

```term nolinenums
$ kubectl apply -f example-httpbin-sigsci_envoyfilter.yaml
serviceaccount/httpbin created
service/httpbin created
deployment.apps/httpbin created
gateway.gateway.networking.k8s.io/httpbin-gateway created
$ kubectl get pods
NAME                                     READY   STATUS    RESTARTS   AGE
httpbin-d9b4c94bb-h4vfk                  3/3     Running   0          70s
httpbin-gateway-istio-54494c698d-vgpvp   1/1     Running   0          68s
$ kubectl get pod httpbin-d9b4c94bb-h4vfk -o jsonpath='{.spec.containers[*].name}'
httpbin sigsci-agent
$ kubectl logs httpbin-d9b4c94bb-h4vfk sigsci-agent | head
2026/06/29 20:41:29.977416 Signal Sciences Agent 4.79.0 starting as user sigsci with PID 1, Max open files=1073741816, Max data size=unlimited, Max address space=unlimited, Max stack size=8388608
2026/06/29 20:41:29.978372 Shared Cache Dir: /sigsci/tmp/cache
2026/06/29 20:41:29.978375 Agent Cache Dir: /sigsci/tmp/cache/agent_httpbin-d9b4c94bb-h4vfk
2026/06/29 20:41:29.979280 =====================================================
2026/06/29 20:41:29.979282 Agent:     httpbin-d9b4c94bb-h4vfk
2026/06/29 20:41:29.979284 System:    alpine 3.24.0 (linux 6.17.0-1025-oem)
2026/06/29 20:41:29.979284 Memory:    38.903G / 58.501G RAM available
2026/06/29 20:41:29.979285 CPU:       12 MaxProcs / 24 CPU cores available
2026/06/29 20:41:29.979286 gRPC:      localhost:9999
2026/06/29 20:41:29.979286 =====================================================
```

## Integrating the Next-Gen WAF agent using external authorization

> **WARNING:** The following integration method is considered legacy and preference would be to integrate using [EnvoyFilter](https://www.fastly.com/documentation/guides/next-gen-waf/setup-and-configuration/kubernetes/kubernetes-istio/#integrating-the-next-gen-waf-agent-using-envoyfilter)

As of Istio v1.9, support has been added to setup an authorization policy that delegates access control to an external authorization system.

The snippets below follow Istio's [example](https://istio.io/latest/docs/tasks/security/authorization/authz-custom/) and enhance the process to replace the example `ext-authz` service with the Next-Gen WAF agent. Refer to the Istio documentation for initial namespace and test workloads, as those are referenced in the snippets below. All files are applied to the 'foo' namespace unless otherwise indicated.

### Deploy the external authorizer

Assumes the secrets have been applied.

```yaml
apiVersion: v1
kind: Service
metadata:
  name: sigsci-agent
  labels:
    app: sigsci-agent
spec:
  ports:
  - name: grpc
    port: 9999
    targetPort: 9999
  selector:
    app: sigsci-agent
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sigsci-agent
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sigsci-agent
  template:
    metadata:
      labels:
        app: sigsci-agent
    spec:
      containers:
      - name: sigsci-agent
        image: signalsciences/sigsci-agent:latest
        imagePullPolicy: IfNotPresent
        # Configure the agent to use Envoy gRPC on port 9999
        env:
        - name: SIGSCI_ACCESSKEYID
          valueFrom:
            secretKeyRef:
              # This secret needs added (see docs on sigsci secrets)
              name: sigsci-agent-accesskey
              key: accesskeyid
        - name: SIGSCI_SECRETACCESSKEY
          valueFrom:
            secretKeyRef:
              # This secret needs added (see docs on sigsci secrets)
              name: sigsci-agent-accesskey
              key: secretaccesskey
        # Configure the Envoy to expect response data (if using a gRPC access log config for Envoy)
        - name: SIGSCI_ENVOY_EXPECT_RESPONSE_DATA
          value: "1"
        - name: SIGSCI_ENVOY_GRPC_ADDRESS
          value: :9999
        ports:
        - containerPort: 9999
        securityContext:
          # The sigsci-agent container should run with its root filesystem read only
          readOnlyRootFilesystem: true
---
```

Verify the Agent is running.

```term copy
$ kubectl logs "$(kubectl get pod -l app=sigsci-agent -n foo -o jsonpath={.items..metadata.name})" -n foo -c sigsci-agent
```

### Define the external authorizer

Edit the mesh config with the following command and add the extension provide definitions.

```term copy
$ kubectl edit configmap istio -n istio-system
```

```yaml
data:
  mesh: |-
    # Add the following content to define the external authorizers.
    extensionProviders:
      - name: "sigsci-agent-ext-authz"
        envoyExtAuthzGrpc:
          service: "sigsci-agent.foo.svc.cluster.local"
          port: "9999"
          timeout: 0.2s
          failOpen: true
          includeRequestBodyInCheck:
            packAsBytes: true
            # use `allowPartialMessage: false` if you want to inspect larger payloads
            allowPartialMessage: true
            maxRequestBytes: 8192
      - name: "sigsci-agent-access-log"
        envoyHttpAls:
          service: "sigsci-agent.foo.svc.cluster.local"
          port: "9999"
          additionalRequestHeadersToLog:
          - "x-sigsci-request-id"
          - "x-sigsci-waf-response"
          - "accept"
          - "content-type"
          - "content-length"
          additionalResponseHeadersToLog:
          - "date"
          - "server"
          - "content-type"
          - "content-length"
```

### Enable with external authorization

Enable the external authorization and apply logging.

```yaml
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: ext-authz
spec:
  selector:
    matchLabels:
      app: httpbin
  action: CUSTOM
  provider:
    # The provider name must match the extension provider defined in the mesh config.
    name: sigsci-agent-ext-authz
  rules:
    # The rules specify when to trigger the external authorizer.
    - to:
      - operation:
          paths: ["/headers"]
```

```yaml
# kubectl apply -f logging.yaml
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
  name: mesh-default
  namespace: istio-system
spec:
  accessLogging:
    - providers:
      - name: sigsci-agent-access-log
```

```term copy nolinenums
# In another terminal curl the httpbin app:
$ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl -v "http://httpbin.foo:8000/headers"  -s

# tail the logs
$ kubectl logs -f "$(kubectl get pod -l app=sigsci-agent -n foo -o jsonpath={.items..metadata.name})" -n foo -c sigsci-agent
```

## Related content

- [Kubernetes installation overview](https://www.fastly.com/documentation/guides/next-gen-waf/setup-and-configuration/kubernetes/kubernetes-intro)
- [Kubernetes agent scaling](https://www.fastly.com/documentation/guides/next-gen-waf/setup-and-configuration/kubernetes/kubernetes-agent-scaling)
