Advanced usage of Envoy ext-proc gRPC filter demonstration.
This project is testing in depth how you can work with Envoy ext-proc filter, especially when it comes to share data between processing steps.
This provides:
- a simple golang service, just returning in JSON the received request headers
- a Envoy proxy exposing the service, and enabling an ext-proc filter
- a golang gRPC external processor that will be used by the ext-proc filter to manipulate the request & response of the service
The intent (example to test ext-proc capabilities):
- we want to extract a CSRF value and add it in a dedicated
X-Extracted-Csrfresponse header - this CSRF can come directly form a
X-Csrfheader - or from a form post, in the
csrffield
The workflow:
- a request comes arrives on envoy (http://localhost:10000)
- envoy starts a gRPC connection, via the ext-proc filter, to our external processor (:50051)
- envoy streams the request headers to the external processor
- if the request contains a
X-Csrfheader, it's stored in a variable and the request if propagated downstream to the service - if not, the external processor asks to be streamed with the request body, and the
csrfpost field is stored in a variable, and the request if propagated downstream to the service - the downstream service processes the request and generates a response
- envoy stream the response to the external processor
- the external processor add a new
X-Extracted-Csrfresponse header with the csrf variable content
To test the stack, simply start the provided docker-compose stack:
docker-compose up -dThen you can interact with the service through envoy on [POST] http://localhost:10000
- by sending the
X-Csrfheader and check you get it back in theX-Extracted-Csrfresponse header - or by sending the
csrfform post field and check you get it back in theX-Extracted-Csrfresponse header
The main goal of this project is to ensure that this pattern does not come with concurrency issues, especially because of the use, external processor side, of high scope variables across gRPC stream handling.
To validate there is actually no concurrency issues, the project provides 2 K6 benchmarking scripts (response code + header assertions) :
- headerBench.js: to test under traffic the CSRF provided via header
- bodyBench.js: to test under traffic the CSRF provided via form post
To run the scripts, you can run for example:
k6 run --vus 50 --iterations 100 k6/headerBench.js