# Envoy

- Canonical URL: https://docs.fairvisor.com/docs/gateway/envoy/
- Section: docs
- Last updated: n/a
> Integrating Fairvisor Edge with Envoy Proxy via the ext_authz filter.


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:

```yaml
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:

```yaml
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`:

```yaml
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:

```yaml
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`:

```yaml
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

```bash
# 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>"
```

