Envoy
Envoy’s ext_authz HTTP filter delegates authorization decisions to an external service. Fairvisor Edge implements a compatible decision endpoint at /v1/decision.
How it works
Client → Envoy → ext_authz → Fairvisor Edge /v1/decision
↓ 200 allow
Envoy → Upstream backend
↓ 429 reject
Envoy → 429 to client
Cluster configuration
Define the Fairvisor Edge cluster:
static_resources:
clusters:
- name: fairvisor_edge
connect_timeout: 0.25s
type: STRICT_DNS
load_assignment:
cluster_name: fairvisor_edge
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: fairvisor-edge.default.svc.cluster.local
port_value: 8080
HTTP filter configuration
Add the ext_authz filter to your filter chain:
http_filters:
- name: envoy.filters.http.ext_authz
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
http_service:
server_uri:
uri: http://fairvisor_edge
cluster: fairvisor_edge
timeout: 0.25s
path_prefix: /v1/decision
authorization_request:
allowed_headers:
patterns:
- exact: authorization # Bearer JWT for claim extraction
- exact: x-forwarded-for # Client IP
- prefix: x- # Pass all x- headers
authorization_response:
allowed_upstream_headers:
patterns:
- exact: x-fairvisor-reason
- exact: retry-after
- exact: ratelimit
- exact: ratelimit-reset
- prefix: ratelimit
failure_mode_allow: true # Fail-open if edge unreachable
failure_mode_allow
Set to true to fail-open (allow requests when Fairvisor Edge is unreachable). Set to false to fail-closed (reject all requests when edge is unavailable). Fairvisor Edge itself is fail-open for storage errors; this setting controls Envoy’s behaviour when the edge is down entirely.
timeout
The timeout on server_uri is the maximum time Envoy waits for the /v1/decision response. Fairvisor Edge typically responds in under 1 ms for token bucket checks. Set this to 200–500 ms to allow for scheduling jitter without blocking user traffic.
Passing the original method and URI
Envoy’s ext_authz automatically passes the original request path and method as part of the CheckRequest message. Fairvisor Edge reads these from the X-Original-Method and X-Original-URI headers forwarded by Envoy.
If you need to customise which headers are forwarded, use authorization_request.headers_to_add:
authorization_request:
headers_to_add:
- header:
key: x-original-method
value: "%REQ(:METHOD)%"
- header:
key: x-original-uri
value: "%REQ(:PATH)%"
Istio
When using Istio, configure Fairvisor Edge as an AuthorizationPolicy with an CUSTOM action pointing to an external authorizer:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: fairvisor-edge
namespace: default
spec:
action: CUSTOM
provider:
name: fairvisor-edge
rules:
- to:
- operation:
paths: ["/api/*"]
Register the external authorizer in the Istio MeshConfig:
extensionProviders:
- name: fairvisor-edge
envoyExtAuthzHttp:
service: fairvisor-edge.default.svc.cluster.local
port: 8080
headersToDownstreamOnDeny:
- retry-after
- x-fairvisor-reason
includeRequestHeadersInCheck:
- authorization
- x-forwarded-for
Verifying the integration
# Verify edge is reachable from Envoy pod
kubectl exec -it <envoy-pod> -- \
curl -s http://fairvisor-edge.default.svc.cluster.local:8080/readyz
# Send a test request and check for rate-limit headers
curl -v http://your-envoy-endpoint/api/test \
-H "Authorization: Bearer <jwt>"