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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
...
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:

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
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 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:

$ 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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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.

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

$ kubectl edit configmap istio -n istio-system
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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"]
1
2
3
4
5
6
7
8
9
10
# 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
# 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