This is the "latest" release of Envoy Gateway, which contains the most recent commits from the main branch.
This release might not be stable.
Please refer to the /docs documentation for the most current information.
CSRF
4 minute read
This task provides instructions for configuring Cross-Site Request Forgery (CSRF) protection on Envoy Gateway. CSRF is an attack that tricks a user’s browser into making unintended requests to a different site where the user is authenticated.
Envoy Gateway introduces a new field in the SecurityPolicy CRD that allows the user to configure CSRF protection. This instantiated resource can be linked to a Gateway, HTTPRoute or GRPCRoute resource.
Prerequisites
Follow the steps below to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP.
Expand for instructions
Install the Gateway API CRDs and Envoy Gateway using Helm:
Gateway API CRD compatibilityThis command installs Gateway API CRDs. If your Kubernetes provider already manages compatible Gateway API CRDs for the cluster, use the provider-managed Gateway API CRD install steps instead.
helm install eg oci://docker.io/envoyproxy/gateway-helm --version v0.0.0-latest -n envoy-gateway-system --create-namespaceInstall the GatewayClass, Gateway, HTTPRoute and example app:
kubectl apply -f https://github.com/envoyproxy/gateway/releases/download/latest/quickstart.yaml -n defaultVerify Connectivity:
Get the External IP of the Gateway:
export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}')Curl the example app through Envoy proxy:
curl --verbose --header "Host: www.example.com" http://$GATEWAY_HOST/getThe above command should succeed with status code 200.
Get the name of the Envoy service created the by the example Gateway:
export ENVOY_SERVICE=$(kubectl get svc -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}')Get the deployment of the Envoy service created the by the example Gateway:
export ENVOY_DEPLOYMENT=$(kubectl get deploy -n envoy-gateway-system --selector=gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=eg -o jsonpath='{.items[0].metadata.name}')Port forward to the Envoy service:
kubectl -n envoy-gateway-system port-forward service/${ENVOY_SERVICE} 8888:80 &Curl the example app through Envoy proxy:
curl --verbose --header "Host: www.example.com" http://localhost:8888/getThe above command should succeed with status code 200.
Configuration
When CSRF protection is enabled, the Envoy CSRF filter validates that the Origin header of mutating requests
(POST, PUT, DELETE, PATCH) matches the destination or one of the configured additional origins.
Non-mutating requests (GET, HEAD, OPTIONS) are not affected.
additionalOrigins uses the same origin syntax as cors.allowOrigins: a full origin such as
https://www.example.com, a single wildcard label such as https://*.trusted.com, an explicit port such as
http://www.example.com:8080, or * to allow any origin.
Note: Envoy’s CSRF filter compares against the host and port of the origin only, so the scheme is ignored.
https://www.example.com and http://www.example.com are equivalent, and either one allows the request
whichever scheme the client used. The scheme is still required by the syntax so that origins read the same
way here as they do in cors.allowOrigins.
The filter supports gradual rollout via shadowFraction: the fraction of requests that are evaluated in
dry-run mode instead of being enforced. It is expressed as a numerator and an optional denominator that
defaults to 100, and defaults to 0%, i.e. all requests are enforced.
The below example defines a SecurityPolicy that enables CSRF protection and allows www.example.com and any
subdomain of trusted.com as additional origins.
cat <<EOF | kubectl apply -f -
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: csrf-example
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: backend
csrf:
additionalOrigins:
- "https://www.example.com"
- "https://*.trusted.com"
EOF
Save and apply the following resource to your cluster:
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: csrf-example
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: backend
csrf:
additionalOrigins:
- "https://www.example.com"
- "https://*.trusted.com"
With this configuration:
- A
POSTrequest withOrigin: https://www.example.comwill be allowed (Envoy extractswww.example.comand matches the exact origin). - A
POSTrequest withOrigin: http://www.example.comwill also be allowed, since the scheme is not compared. - A
POSTrequest withOrigin: https://app.trusted.comwill be allowed (Envoy extractsapp.trusted.comwhich matches the wildcard). - A
POSTrequest withOrigin: https://trusted.comwill be rejected: the wildcard matches subdomains, not the apex domain. - A
POSTrequest withOrigin: https://www.malicious.comwill be rejected with a403 Forbidden. - A
GETrequest from any origin will be allowed (non-mutating).
Shadow mode (dry-run)
To evaluate CSRF policies without enforcing them, set shadowFraction to 100%:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: csrf-shadow
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: backend
csrf:
shadowFraction:
numerator: 100
additionalOrigins:
- "https://www.example.com"
In this mode, all requests are allowed but Envoy tracks CSRF metrics (request_valid / request_invalid)
so you can monitor the impact before enabling enforcement.
Requests that are not selected for shadowing are enforced, so shadowFraction also doubles as the knob for
rolling enforcement out gradually: numerator: 25 shadows a quarter of the requests and enforces the
remaining three quarters. Lower it towards 0 as the metrics confirm that no legitimate origin is rejected.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.