clusters:
# other cluster entries
- name: ext-authz (1)
type: strict_dns
typed_extension_protocol_options: (2)
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
"@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions"
explicit_http_config:
http2_protocol_options: {}
load_assignment: (3)
cluster_name: ext-authz
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: heimdall
port_value: 4456
# other cluster entries
Envoy Integration
This guide explains how to integrate heimdall with Envoy.
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.
Prerequisites
Integration with Envoy proxy requires heimdall being operated in Decision Operation Mode.
Integration Options
Envoy makes integration with external authorization services, like heimdall possible via an External Authorization filter in two ways
either via HTTP
or via GRPC
In both cases, the filter calls an external gRPC or HTTP service to check whether an incoming HTTP request is authorized or not. If the request is deemed unauthorized, then the request will be denied normally with 403 (Forbidden) response.
Even envoy allows the authorization service sending additional custom metadata to the upstream when GRPC is used, heimdall does not make use of this option. |
Global Configuration
To integrate heimdall with Envoy globally, you need to configure two things:
a
cluster
entry referencing the actual heimdall address, andthe aforesaid filter in the http filter chain
The 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.
1 | The name of our cluster |
2 | Here, we configure envoy to communicate with heimdall by making use of HTTP 2. This configuration is only required if you want to integrate heimdall via Envoy’s grpc_service (see below), as otherwise envoy will use HTTP 1 for GRPC communication, which is actually not allowed by GRPC (only HTTP 2 is supported). |
3 | The endpoints in the cluster. In this example, only one endpoint is configured. |
You can now include an External Authorization HTTP filter in the definition of the HTTP connection manager and depending on the used configuration, either configure the http_service
and let it contain the required header name(s), heimdall sets in the HTTP responses (depends on your Contextualizers and Finalizers configuration), or configure the grpc_service
.
Using HTTP protocol
The following snipped shows, how an External Authorization can be defined using http_service
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" (1)
transport_api_version: V3 (2)
http_service:
server_uri: (3)
uri: heimdall:4456
cluster: ext-authz
timeout: 0.25s
authorization_request:
allowed_headers: (4)
patterns:
- safe_regex:
google_re2: {}
regex: ".*"
authorization_response: (5)
allowed_upstream_headers:
patterns:
- exact: authorization
# other http filter
1 | The type of the filter, we’re going to configure |
2 | Heimdall supports only the version 3 of the GRPC protocol defined by Envoy for that filter. So we set the required version here. |
3 | The reference to our previously configured cluster |
4 | Here, we say envoy to forward all headers from the received request to heimdall |
5 | And here, we instruct envoy to forward the Authorization header set bei heimdall in its response to envoy to the upstream service |
Envoy does not set If you integrate heimdall with envoy via |
Using GRPC protocol
The following snipped shows, how an External Authorization can be defined using grpc_service
to let Envoy communicating with heimdall by making use of the previously defined cluster
(see snippet from above). In that configuration envoy by default forwards all request header to heimdall and also forwards headers, set by heimdall in its responses 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" (1)
transport_api_version: V3 (2)
grpc_service: (3)
envoy_grpc:
cluster_name: ext-authz
# other http filter
1 | The type of the filter, we’re going to configure. Same filter is used for both approaches, communication via HTTP and GRPC |
2 | Heimdall supports only the version 3 of the GRPC protocol defined by Envoy for that filter. So we set the required version here |
3 | The reference to our previously configured cluster |
Route-based Configuration
Route base configuration happens exactly the same way as globally. There is also an option to fine tune or disable the external authorization service if required by making use of the ExtAuthzPerRoute filter. You can find an example in the official Envoy documentation.
Demo Setup
The Envoy configuration file shown below can be used to create a fully working setup based on the quickstart described in Protect an Application and set up to implement Edge-level Authorization Architecture. 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
.
Additional Resources
The demo setup shown above is also available on GitHub.
Last updated on Apr 8, 2025