Decode and modify base64 request headers

You can decode and modify incoming headers before sending the request to an upstream by using Gloo transformations.

Setup

This guide assumes that you installed the following components:

You also need an upstream service to serve as the target for the requests that you send to test the Gloo Gateway configurations in this tutorial. You can use the publicly available Postman Echo service. Postman Echo exposes a set of endpoints that are very useful for inspecting both the requests sent upstream and the resulting responses. For more information about this service, see the Postman Echo documentation.

Create a static upstream to represent the postman-echo.com remote service.

apiVersion: gloo.solo.io/v1
kind: Upstream
metadata:
  name: postman-echo
  namespace: gloo-system
spec:
  static:
    hosts:
    - addr: postman-echo.com
      port: 80

Next, create a simple Virtual Service that matches any path and routes all traffic to the Upstream.


apiVersion: gateway.solo.io/v1
kind: VirtualService
metadata:
  name: decode-and-modify-header
  namespace: gloo-system
spec:
  virtualHost:
    domains:
    - '*'
    routes:
    - matchers:
       - prefix: /
      routeAction:
        single:
          upstream:
            name: postman-echo
            namespace: gloo-system

Finally, test that Gloo Gateway picked up the configuration by sending a request with a base64-encoded header.

curl -v -H "x-test: $(echo -n 'testprefix.testsuffix' | base64)" $(glooctl proxy url)/get | jq

Review the JSON output similar to the following 200 status response. Note that the x-test header in the payload response from postman-echo has the base64 representation of the string literal testprefix.testsuffix that you passed in the request.

{
  "args": {},
  "headers": {
    "x-forwarded-proto": "http",
    "x-forwarded-port": "80",
    "host": "localhost",
    "x-amzn-trace-id": "Root=1-6336f537-6c0a1f3d6c6849b10f65409c",
    "user-agent": "curl/7.64.1",
    "accept": "*/*",
    "x-test": "dGVzdHByZWZpeC50ZXN0c3VmZml4",
    "x-request-id": "7b1e64fe-e30a-437f-a826-ca5e349f50d4",
    "x-envoy-expected-rq-timeout-ms": "15000"
  },
  "url": "http://localhost/get"
}

Modifying the request header

As confirmed in the test request of the setup, the upstream service echoes the headers that you include in the request inside the headers response body attribute. Now, you can configure Gloo Gateway to decode and modify the value of this header before sending it to the upstream.

Update the Virtual Service

To implement this behavior, add a responseTransformation stanza to the original Virtual Service definition. Note that the request_header, base64_decode, and substring functions are used in an Inja template to:

The output of this chain of events is injected into a new request header x-decoded-test.

apiVersion: gateway.solo.io/v1
kind: VirtualService
metadata:
  name: decode-and-modify-header
  namespace: gloo-system
spec:
  virtualHost:
    domains:
    - '*'
    routes:
    - matchers:
       - prefix: /
      routeAction:
        single:
          upstream:
            name: postman-echo
            namespace: gloo-system
    options:
      transformations:
        requestTransformation:
          transformationTemplate:
            headers:
              x-decoded-test:
                text: '{{substring(base64_decode(request_header("x-test")), 11)}}'

Test the modified configuration

Test the modified Virtual Service by issuing a curl request.

curl -v -H "x-test: $(echo -n 'testprefix.testsuffix' | base64)" $(glooctl proxy url)/get | jq

Review the output similar to the following JSON response. Note that the value of the inject header x-decoded-test has a substring of the decoded base64 value that was sent in the x-test header.

{
  "args": {},
  "headers": {
    "x-forwarded-proto": "http",
    "x-forwarded-port": "80",
    "host": "localhost",
    "x-amzn-trace-id": "Root=1-6336f482-164a3d207b026fe358de000f",
    "user-agent": "curl/7.64.1",
    "accept": "*/*",
    "x-test": "dGVzdHByZWZpeC50ZXN0c3VmZml4",
    "x-request-id": "1fbed7be-0089-4d19-a9c2-221ca088e40b",
    "x-decoded-test": "testsuffix",
    "x-envoy-expected-rq-timeout-ms": "15000"
  },
  "url": "http://localhost/get"
}

Congratulations! You successfully used a request transformation to decode and modify a request header!

Cleanup

You can clean up the resources that you created in this tutorial.

kubectl delete virtualservice -n gloo-system decode-and-modify-header
kubectl delete upstream -n gloo-system postman-echo