user2309838
user2309838

Reputation: 307

simple envoy filter not being used

Hi I'm new to Envoy and Istio. I'm trying to write an envoy filter to rewrite/redirect HTTP(s) requests. Below is my configuration (yes, a toy example) and it's not working.

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: lua-filter
spec:
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: SIDECAR_OUTBOUND
      listener:
        filterChain:
          filter:
            name: "envoy.http_connection_manager"
            subFilter:
              name: "envoy.router"
    patch:
      operation: INSERT_BEFORE
      value:
       name: envoy.lua
       typed_config:
         "@type": "type.googleapis.com/envoy.config.filter.http.lua.v2.Lua"
         inlineCode: |
            function envoy_on_request(request_handle)
                request_handle:headers():add("authorization", "it works!")
            end
            function envoy_on_response(response_handle)
                  filter_name = "ENVOY"
                  response_handle:headers():add("my_Filter", filter_name)
            end

after I deploy the app (listening on port 443 for https, behind Cloudflare) and envoy filter, I do curl -v <my_app>. I don't see either the added request header or the response header. I also tried adding xff_num_trusted_hops: 2 suggested by some other answers but to not avail. What did I do incorrect?

Upvotes: 3

Views: 5241

Answers (1)

Jakub
Jakub

Reputation: 8830

To apply the filter to a single pod you have to add workloadSelector for your app.

  workloadSelector:
    labels:
      xxx: xxx

For example, there is an nginx deployment and your envoy filter with appropriate workloadSelector .

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx1
spec:
  selector:
    matchLabels:
      run: nginx1
  replicas: 1
  template:
    metadata:
      labels:
        run: nginx1
        app: frontend
    spec:
      containers:
      - name: nginx1
        image: nginx
        ports:
        - containerPort: 80


apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: lua-filter
  namespace: default
spec:
  workloadSelector:
    labels:
      run: nginx1
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: SIDECAR_INBOUND
      listener:
        filterChain:
          filter:
            name: "envoy.http_connection_manager"
            subFilter:
              name: "envoy.router"
    patch:
      operation: INSERT_BEFORE
      value:
       name: envoy.lua
       typed_config:
         "@type": "type.googleapis.com/envoy.config.filter.http.lua.v2.Lua"
         inlineCode: |
            function envoy_on_request(request_handle)
                request_handle:headers():add("authorization", "it works!")
            end
            function envoy_on_response(response_handle)
                  filter_name = "ENVOY"
                  response_handle:headers():add("my_Filter", filter_name)
            end

To apply the filter to all requests going through your istio ingress gateway.

1.Change change context from SIDECAR_INBOUND to GATEWAY .

2.Set a workloadSelector.

  workloadSelector:
    labels:
      istio: ingressgateway

3.Set istio-system namespace.

  namespace: istio-system

4.There is your example after few edits.

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: lua-filter
  namespace: istio-system
spec:
  workloadSelector:
    labels:
      istio: ingressgateway
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: GATEWAY
      listener:
        filterChain:
          filter:
            name: "envoy.http_connection_manager"
            subFilter:
              name: "envoy.router"
    patch:
      operation: INSERT_BEFORE
      value:
       name: envoy.lua
       typed_config:
         "@type": "type.googleapis.com/envoy.config.filter.http.lua.v2.Lua"
         inlineCode: |
            function envoy_on_request(request_handle)
                request_handle:headers():add("authorization", "it works!")
            end
            function envoy_on_response(response_handle)
                  filter_name = "ENVOY"
                  response_handle:headers():add("my_Filter", filter_name)
            end

5.I checked it with curl

curl -s -I -X HEAD xx.xx.xx.xx/productpage

HTTP/1.1 200 OK
content-type: text/html; charset=utf-8
content-length: 5179
server: istio-envoy
date: Tue, 10 Nov 2020 08:28:30 GMT
x-envoy-upstream-service-time: 60
my_filter: ENVOY    <---

AND

I checked it with config_dump in istio ingress-gateway pod.

I exec there with

kubectl exec -ti istio-ingressgateway-86f88b6f6-2tv64 -n istio-system -- /bin/bash

Results from config_dump

curl 0:15000/config_dump | grep my_Filter
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  140k    0  140k    0     0   9.7M      0 --:--:-- --:--:-- --:--:--  9.7M
               "inline_code": "function envoy_on_request(request_handle)\n    request_handle:headers():add(\"authorization\", \"it works!\")\nend\nfunction envoy_on_response(response_handle)\n      filter_name = \"ENVOY\"\n      response_handle:headers():add(\"my_Filter\", filter_name)\nend\n"

Additional resources:

Upvotes: 6

Related Questions