Karl
Karl

Reputation: 5822

EnvoyFilter: Apply ExtAuthz filter followed by Lua filter

I am trying to figure out out to contruct an EnvoyFilter (using v3 API) to be used in conjunction with Istio and OAuth2-Proxy (as external Authz service).

Essentially I need a setup that will call an ExtAuthz in order to authenticate, and also retrieve the header x-auth-request-email and rename it to kubeflow-userid. I am having quite a bit of difficulty understanding how Envoy chains filters.

My current attempt is as follows:

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: istio-ingressgateway
  namespace: istio-system
spec:
  filters:
  - applyTo: HTTP_FILTER
    match:
      context: GATEWAY
      listener:
        filterChain:
          filter:
            name: envoy.filters.network.http_connection_manager
            subFilter:
              name: envoy.filters.http.jwt_authn
    patch:
      operation: INSERT_BEFORE
      value:
        name: envoy.filters.http.ext_authz
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
          http_service:
            server_uri:
              uri: http://oauth2-proxy.oauth2-proxy.svc.cluster.local:4180
              cluster: outbound|4180||oauth2-proxy.oauth2-proxy.svc.cluster.local
              timeout: 10s              
            authorizationRequest:
              allowedHeaders:
                patterns:
                - exact: cookie
              authorizationResponse:
                allowedUpstreamHeaders:
                  patterns:
                    # - exact: "kubeflow-userid"
                    - exact: "authorization"
                    - exact: "x-auth-request-email"    
  - applyTo: HTTP_FILTER # should this be NETWORK_FILTER instead?
    match: # how do I define the context here?
      #context: GATEWAY
      listener:
        filterChain:
          filter:
            name: envoy.filters.network.http_connection_manager
            subFilter:
              name: envoy.filters.http.jwt_authn
    patch:
      operation: MERGE # what should this be?
      value:
        name: envoy.filters.http.lua
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
          inline_code: |
            function envoy_on_request(request_handle)
              headers = request_handle:headers()
              request_handle:headers():add("kubeflow-userid", headers:get("x-auth-request-email))
            end

Upvotes: 0

Views: 1414

Answers (1)

Chris
Chris

Reputation: 5663

In your case the filter chain is defined by

  • the subFilter.name you define in the match part
  • the name of your filter in the patch part

I find it easier to understand it as two separat filters (I adjusted the names):

Your ExtAuthz filter is inserted before the filter envoy.filters.http.router with the name custom.ext_authz.

[...]
    match:
      context: GATEWAY
      listener:
        filterChain:
          filter:
            name: envoy.filters.network.http_connection_manager
            subFilter:
              name: envoy.filters.http.router
    patch:
      operation: INSERT_BEFORE
      value:
        name: custom.ext_authz

and the lua filter is inserted after the custom.ext_authz filter with the name custom.lua.

    match: 
      context: GATEWAY
      listener:
        filterChain:
          filter:
            name: envoy.filters.network.http_connection_manager
            subFilter:
              name: custom.ext_authz
    patch:
      operation: INSERT_AFTER
      value:
        name: custom.lua
[...]

So the filter chain looks something like:

~ -> custom.ext_authz -> custom.lua -> envoy.filters.http.router -> ~

You can verify your setup with the envoy dashboard:

  • Run istioctl dashboard envoy ingress-gateway-<id>.istio-system
  • Open your browser on the url if it doesn't open automatically
  • Press config_dump

There all filters are shown (search them by name), so you can verify your setup and the order.

Upvotes: 0

Related Questions