Envoy Integration

Envoy is a high performance distributed proxy designed for single services and applications, as well as a communication bus and “universal data plane” designed for large microservice “service mesh” architectures. When operating heimdall in Decision Operation Mode, integration with Envoy can be achieved by making use of an External Authorization filter. In such setup, Envoy delegates authentication and authorization to heimdall. If heimdall answers with a 200 OK HTTP code, Envoy grants access and forwards the original request to the upstream service. Otherwise, the response from heimdall is treated as an error and is returned to the client.

To achieve this, configure Envoy

  • to have heimdall instances referenced in a cluster

    Following snippet provides an example on how to create a cluster instance referencing heimdall. It assumes, you have just one heimdall instance deployed, which is also available via heimdall DNS name.

    clusters:
      # other cluster entries
      - name: ext-authz
        type: strict_dns
        load_assignment:
          cluster_name: ext-authz
          endpoints:
            - lb_endpoints:
                - endpoint:
                    address:
                      socket_address:
                        address: heimdall
                        port_value: 4456
      # other cluster entries
  • to include an External Authorization HTTP filter in the definition of the HTTP connection manager, as well as to let that filter contain the required header name(s), heimdall sets in the HTTP responses (depends on your Contextualizers and Unifiers configuration).

    The following snipped shows, how an External Authorization can be defined to let Envoy communicating with heimdall by making use of the previously defined cluster (see snippet from above) as well as forwarding all request headers to heimdall and to let it forward headers, set by heimdall in its responses (here the Authorization header) to the upstream services.

    http_filters:
      # other http filter
      - name: envoy.filters.http.ext_authz
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
          transport_api_version: V3
          http_service:
            server_uri:
              uri: heimdall:4456
              cluster: ext-authz
              timeout: 0.25s
            authorization_request:
              allowed_headers:
                patterns:
                  - safe_regex:
                      google_re2: {}
                      regex: ".*"
            authorization_response:
              allowed_upstream_headers:
                patterns:
                  - exact: authorization
      # other http filter
Envoy does not set X-Forwarded-* headers, as long as the envoy.filters.http.dynamic_forward_proxy is not configured. That means, matching of URLs happens based on those URLs, used by Envoy while communicating with heimdall. That means your rules should ignore the scheme and host parts, respectively use the values specific for heimdall and not of the domain.

Demo Setup

The Envoy configuration file shown below can be used to create a fully working setup based on the Decision Service Quickstart. Just update the docker-compose.yaml file used in that guide and replace the entry for proxy service, with the one shown below. You can also remove all labels configurations, as these will have no effect.

# docker-compose.yaml

services:
  proxy:
    image: envoyproxy/envoy:v1.24.1
    volumes:
      - ./envoy.yaml:/envoy.yaml:ro
    ports:
      - 9090:9090
    command: -c /envoy.yaml

  # other services from the guide
# envoy.yaml

static_resources:
  listeners:
    - name: listener_0
      address:
        socket_address:
          address: 0.0.0.0
          port_value: 9090
      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
              stat_prefix: edge
              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
                    http_service:
                      server_uri:
                        uri: heimdall:4456
                        cluster: ext-authz
                        timeout: 0.25s
                      authorization_request:
                        allowed_headers:
                          patterns:
                            - safe_regex:
                                google_re2: {}
                                regex: ".*"
                      authorization_response:
                        allowed_upstream_headers:
                          patterns:
                            - exact: authorization
                - name: envoy.filters.http.router
                  typed_config:
                    "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
              route_config:
                virtual_hosts:
                  - name: direct_response_service
                    domains: ["*"]
                    routes:
                      - match:
                          prefix: "/"
                        route:
                          cluster: services

  clusters:
    - name: ext-authz
      type: strict_dns
      load_assignment:
        cluster_name: ext-authz
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: heimdall
                      port_value: 4456
    - name: services
      connect_timeout: 5s
      type: strict_dns
      dns_lookup_family: V4_ONLY
      load_assignment:
        cluster_name: services
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: upstream
                      port_value: 80

After starting the docker compose environment, you can run the curl commands shown in the referenced guide. This time however against envoy by using port 9090. E.g. $ curl -v 127.0.0.1:9090/anonymous.

Last updated on Jan 2, 2023