Envoy Gateway
Prerequisites
- Envoy Gateway
v1.6.0installed- DataDome Envoy Gateway integration uses EnvoyPatchPolicy that might evolve in the future
- The server-side key available in your DataDome dashboard
datadome.luafile
Important: Two Namespaces
This integration uses two different namespaces:
-
Envoy Gateway Namespace (typically
envoy-gateway-system):- Where Envoy Gateway control plane is installed. ConfigMap and EnvoyProxy resources go here.
-
Gateway Namespace (e.g.,
production,default):- Where the Gateway resource lives. EnvoyPatchPolicy goes here.
Pre-flight Checks
Find your GatewayClass and Gateway names before starting:
# Find your GatewayClass name
kubectl get gatewayclass # Example output: NAME: eg, CONTROLLER: gateway.envoyproxy.io/gatewayclass-controller
# Find your Gateway name and namespace
kubectl get gateway -A # Example output: NAMESPACE: production, NAME: api-gateway, CLASS: eg
# Find listener name (usually 'http' or 'https')
kubectl get gateway <gateway-name> -n <gateway-namespace> -o yaml | grep -A 2 "listeners:" # Example output: - name: httpSet these as environment variables:
export GATEWAYCLASS_NAME="eg" # From first command
export GATEWAY_NAME="api-gateway" # From second command
export GATEWAY_NAMESPACE="production" # From second commandStep 1: Enable EnvoyPatchPolicy
Make sure you activate enableEnvoyPatchPolicy: true on the Envoy Gateway configuration. If you already have an envoy-gateway-config ConfigMap, merge this setting with your existing configuration.)
kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: envoy-gateway-config
namespace: envoy-gateway-system
data:
envoy-gateway.yaml: |
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyGateway
extensionApis:
enableEnvoyPatchPolicy: true
EOFRestart:
kubectl rollout restart deployment/envoy-gateway -n envoy-gateway-system
kubectl rollout status deployment/envoy-gateway -n envoy-gateway-systemVerify:
kubectl get configmap envoy-gateway-config -n envoy-gateway-systemStep 2: Create ConfigMap to store DataDome code
Store the DataDome Lua filter code in Kubernetes.
kubectl create configmap datadome-lua \
--from-file=datadome.lua=./datadome.lua \
-n envoy-gateway-system \
--dry-run=client -o yaml | kubectl apply -f -Verify:
kubectl get configmap datadome-lua -n envoy-gateway-systemStep 3: Create EnvoyProxy Resource
Mount the ConfigMap into Envoy proxy pods at /etc/envoy-lua-filters/.
kubectl apply -f - <<EOF
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
name: datadome-proxy-config
namespace: envoy-gateway-system
spec:
provider:
type: Kubernetes
kubernetes:
envoyDeployment:
pod:
volumes:
- name: datadome-lua-filter
configMap:
name: datadome-lua
container:
volumeMounts:
- name: datadome-lua-filter
mountPath: /etc/envoy-lua-filters
readOnly: true
EOFVerify:
kubectl get envoyproxy datadome-proxy-config -n envoy-gateway-systemStep 4: Update GatewayClass
Link the GatewayClass to the EnvoyProxy resource to activate the mount.
kubectl patch gatewayclass ${GATEWAYCLASS_NAME} --type=merge -p '{
"spec": {
"parametersRef": {
"group": "gateway.envoyproxy.io",
"kind": "EnvoyProxy",
"name": "datadome-proxy-config",
"namespace": "envoy-gateway-system"
}
}
}'Note: This triggers a rolling restart of Envoy proxy pods.
Verify:
kubectl get gatewayclass ${GATEWAYCLASS_NAME} -o yaml | grep -A 4 parametersRefStep 5: Apply EnvoyPatchPolicy
Inject the Lua filter into the HTTP filter chain and add DataDome API cluster.
Set your API key and find listener name:
export DATADOME_API_KEY="your-api-key-here"
# Find your listener name (usually 'http' or 'https')
export LISTENER_NAME=$(kubectl get gateway ${GATEWAY_NAME} -n ${GATEWAY_NAMESPACE} -o jsonpath='{.spec.listeners[0].name}')
echo "Listener name: ${LISTENER_NAME}"Apply the policy:
kubectl apply -f - <<EOF
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyPatchPolicy
metadata:
name: datadome-filter-patch
namespace: ${GATEWAY_NAMESPACE}
spec:
targetRef:
group: gateway.networking.k8s.io
kind: Gateway
name: ${GATEWAY_NAME}
type: JSONPatch
jsonPatches:
- type: "type.googleapis.com/envoy.config.listener.v3.Listener"
name: "${GATEWAY_NAMESPACE}/${GATEWAY_NAME}/${LISTENER_NAME}"
operation:
op: add
path: "/default_filter_chain/filters/0/typed_config/http_filters/0"
value:
name: envoy.filters.http.lua
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
default_source_code:
inline_string: |
assert(loadfile("/etc/envoy-lua-filters/datadome.lua"))({
['API_KEY'] = '${DATADOME_API_KEY}',
['API_TIMEOUT'] = 150,
['DATADOME_ENDPOINT'] = 'api.datadome.co',
})
- type: "type.googleapis.com/envoy.config.cluster.v3.Cluster"
name: "datadome"
operation:
op: add
path: ""
value:
name: datadome
type: STRICT_DNS
load_assignment:
cluster_name: datadome
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: api.datadome.co
port_value: 443
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
sni: api.datadome.co
EOFVerify:
kubectl get envoypatchpolicy datadome-filter-patch -n ${GATEWAY_NAMESPACE}Updated about 17 hours ago
