Forward headers with EnvoyFilters

Hi-

I’m trying find a way to forward an inbound header value to a service

that is, an inbound request for an istio service svc1 contains header “foo=bar”, i’d like to automatically forward that header to an upstream service like svc2

At the moment, i have to read that key/value in code and then reemit that to the outbound call.

Is it possible to do this automatically using something like EnvoyFilter and LUA?

I made some progress below by using both a filter that reads the header using SIDECAR_INBOUND and then emits some other header to upstream using SIDECAR_OUTBOUND:

What i can’t figure out is how to use the inbound_header variable in one filter in another one in the chain later on (i.,e read it in SIDECAR_INBOUND and use that in SIDECAR_OUTBOUND both of whih are envoy.lua

Here’s the yaml i’ve setup so far:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name:  httpbin-virtualservice
spec:
  hosts:
  - "httpbin.example.com"
  gateways:
  - my-gateway
  http:      
  - route:
    - destination:
        host: httpbin
    headers:
      request:
        add:                  
          added: "header"
        set:                  
          test: "true"          
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: httpbin-destination
spec:
  host: httpbin
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL  
    loadBalancer:
      simple: ROUND_ROBIN
---
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: httpbin-lua-inbound
spec:
  workloadLabels:
    app: httpbin
  filters:
  - listenerMatch:
      listenerType: ANY
    insertPosition:
      index: FIRST
    filterName: envoy.lua
    filterType: HTTP
    filterConfig:    
      inlineCode: |
        local inbound_header
        function envoy_on_request(request_handle)
          request_handle:logInfo(">>>> SIDECAR_INBOUND envoy_on_request called  ")
          inbound_header = request_handle:headers():get("foo")
        end

  - listenerMatch:
      listenerType: SIDECAR_OUTBOUND
    insertPosition:
      index: BEFORE
      relativeTo: envoy.router
    filterName: envoy.lua
    filterType: HTTP
    filterConfig:    
      inlineCode: |
        function envoy_on_request(request_handle)
          request_handle:logInfo(">>>> SIDECAR_OUTBOUND envoy_on_request called  ")
          -- somehow read inbound_header and add that to the request header here 
          request_handle:headers():add("foo", inbound_header)       
        end

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: httpbin
---
apiVersion: v1
kind: Service
metadata:
  name: httpbin
  labels:
    app: httpbin
spec:
  ports:
  - name: http
    port: 8080
    targetPort: 8080
  selector:
    app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
  template:
    metadata:
      labels:
        app: httpbin
    spec:
      serviceAccountName: httpbin
      containers:
      - image: salrashid123/httpbin-remote:1
        imagePullPolicy: IfNotPresent
        name: httpbin
        ports:
        - containerPort: 8080

note, the image salrashid123/httpbin-remote:1 just makes an http GET call to httpbin (which means if you tail the logs on that cotnainer while testing, it’ll print out the headers svc1 sent out (externally outside of istio)

Is there any easier way to do this (i tried using dynamic metadata in LUA but didn’t make any progress)