Proof of concept Envoy WASM-based HTTP filter that can augment requests with additional headers automatically discovered from a 3rd party endpoint at regular intervals.
The header-providing 3rd party service can be any configured Envoy cluster. In an Istio context, this could be another sidecar available over loopback in the same pod, or some external centralised service perhaps in the mesh authorising based on SPIFFE identity, with circuit breakers, retries, load balancing and all the usual Istio Envoy goodness.
A potential use case of a filter like this would be to automatically gather and add IdP tokens to outbound requests on behalf of mesh workloads, to federate identity beyond the mesh itself.
See envoy.yaml for a full example. Defaults:
{
"header_providing_service_cluster": "sidecar",
"header_providing_service_authority": "sidecar",
"header_providing_service_path": "/headers",
"header_cache_expiry": "360s"
}
The header-providing service is expected to return a simple JSON map of headers. These will all be added to HTTP requests passing through the filter.
The Envoy filter will poll the service using the
header_providing_service_cluster
at header_providing_service_path
,
presenting as header_providing_service_authority
.
Valid headers returned from this service are cached by the Envoy filter,
renewing every header_cache_expiry
interval. This polling and caching action
is happening out-of-band on the filter root context rather than the request path
as the WASM workers process them.
There is a docker-compose.yaml stack for testing the filter locally and also a
sample of how to deploy it to an Istio-enabled Kubernetes cluster (using a
Kube ConfigMap
to host the WASM binary and Istio’s EnvoyFilter
combined with
volume mount annotations to load it into the sidecar).
Any sufficiently modern Rust toolchain wired with the WASM target should be able to compile the filter.
The shell.nix contains a Nix expression that when evaluated will give you a pure
environment with everything you need. Lorri and direnv
can additionally be
used for caching.
A build target is available in the Makefile:
# Optionally: nix-shell --pure
# OR
# Optionally: direnv allow && lorri shell
make build
- [X] TODO Test locally with a
docker-compose
stack emulating a pod with sidecars - [X] TODO Test remotely in an Istio-enabled Kube cluster
- [-] TODO WASM binary size shrinking
Attempt 1: 1.7mb –> 372kb with
lto
set to true andopt-level
set to ‘s’ Attempt 2: 372kb –> 131kb withwasm-pack
More than good enough for shipping to a binary Kube config map.