Envoy extension :: Cerbos Authorization Management Platform // Documentation

Envoy extension

Synapse implements the Envoy external authorization API natively and its behaviour can be configured either declratively or programmatically.

A typical Envoy configuration to use Synapse as the external authorization service is as follows.

Envoy configuration

static_resources:
  listeners:
    - name: listener_0
      address:
        socket_address:
          address: 0.0.0.0
          port_value: 8080
      filter_chains:
        - filters:
            - name: envoy.filters.network.http_connection_manager
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
                codec_type: AUTO
                http_filters:
                  - name: envoy.filters.http.ext_authz
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
                      transport_api_version: V3
                      grpc_service:
                        envoy_grpc:
                          cluster_name: synapse
                  - name: envoy.filters.http.router
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
                route_config:
                  ...

clusters:
    - name: synapse
      type: STATIC
      typed_extension_protocol_options:
        envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
          "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
          explicit_http_config:
            http2_protocol_options: {}
      load_assignment:
        cluster_name: synapse
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: 127.0.0.1
                      port_value: 3594

transport_socket:
        name: envoy.transport_sockets.tls
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
          sni: synapse.localhost
          common_tls_context:
            validation_context:
              trust_chain_verification: ACCEPT_UNTRUSTED

Declarative mapping

Map Envoy Check requests to Cerbos CheckResources and back using CEL expressions.

extensions:
  envoyExternalAuthz:
    enabled: true
    mapping:
      request:
        requestID: 'request.attributes.request.http.headers["x-request-id"]'
        principal:
          id: 'request.attributes.request.http.headers["x-user-id"]'
          roles: '[
            "user"
          ]'
        resource:
          id: '"foo"'
          kind: '"request"'
        action: 'request.attributes.request.http.method'
1 Enable the Envoy Check endpoint on the server
2 Declarative mapping of request and response. See below for mapping reference.

Mapping reference

Documentation about Cerbos request and response formats can be found at https://docs.cerbos.dev/cerbos/latest/api/#_request_and_response_formats. For Envoy Check request and response formats, refer to https://buf.build/envoyproxy/envoy/docs/main:envoy.service.auth.v3#envoy.service.auth.v3.CheckRequest.

Request expressions have access to the incoming HTTP request in the CEL variable request, which has the following fields:

Response expressions have access to the CheckResources result in the CEL variable check which has the following fields:

Using the YAML scalar block syntax > for CEL expressions is recommended to avoid quoting issues. action: "view" would be interpreted as the CEL expression view (which would fail to compile because a variable named view is not defined), when the desired setting was the CEL expression "view" (which just returns the intended string literal).

Minimal configuration

Customizing the response

extensions:
  envoyExternalAuthz:
    enabled: true
    mapping:
      request:
        requestID: 'request.attributes.request.http.headers["x-request-id"]'
        principal:
          id: 'request.attributes.request.http.headers["x-user-id"]'
          roles: '[
            "user"
          ]'
        resource:
          id: '"foo"'
          kind: '"request"'
        action: 'request.attributes.request.http.method'
      response: >
        check.allow ? {"status": {"code": google.rpc.Code.OK }} : {
            "status": {"code": google.rpc.Code.OK },
            "deniedResponse": {
               "status": {"code": 401 },
               "body": json.encode(check.outputs["resource.example.v1#route"].body)
             }
        }

Programmatic mapping

extensions:
  envoyExternalAuthz:
    enabled: true
    extension:
      extensionURL: /extensions/envoy.wasm
      configuration:
        environment: staging
1 Enable the Envoy Check endpoint.
2 URL to fetch the extension from. See extension URL format for more information.
3 Configuration values needed by the extension. [Optional]

Building an Envoy extension

See Building custom Synapse extensions.