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