istioistio-gateway

Using jwt_authn_filter claim_to_headers in VirtualService routing


I have an ingress gateway set up which all works perfectly and can route traffic to services through VirtualServices. I've also set up an EnvoyFilter using the jwt_authn_filter to perform some authentication on certain routes for incoming traffic to my cluster. This EnvoyFilter also adds a custom header to traffic based on one of the claims within the JWT:

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: jwt-auth-filter
  namespace: istio-system
spec:
  workloadSelector:
    labels:
      istio: ingress-gateway
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: GATEWAY
      listener:
        portNumber: 443
        filterChain:
          filter:
            name: envoy.filters.network.http_connection_manager
            subFilter:
              name: envoy.filters.http.router
    patch:
      operation: INSERT_FIRST
      value:
        name: envoy.filters.http.jwt_authn
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication
          providers:
            x:
              ...
              claim_to_headers:
                - header_name: x-custom
                  claim_name: custom
          ...

This all works fine, I can see the header being added in the logs and my services that are routed to receive this header. However, if I try to use this header in a Virtual Service, it doesn't work, I get a 404 NR route_not_found error.

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: vs1
  namespace: ns1
spec:
  gateways:
    - istio-system/ingress-gateway
  hosts:
    - 'mydomain.com'
  http:
    - name: vs1
      match:
        - headers:
            x-custom:
              exact: value
      route:
      - destination:
          host: s1.ns1.svc.cluster.local
          port:
            number: 80

It seems like the headers for routing are determined before the above filter runs. Is this correct, and if so, is there a better alternative approach?

The VirtualService itself is working fine, if I manually set that header on requests to the ingress gateway it gets routed correctly so there aren't any issues there.


Solution

  • Turns out there is an undocumented option clear_route_cache which solves this issue.

    https://github.com/envoyproxy/go-control-plane/blob/5d9168428a5cdac76212030e15f47093b0c45a8a/envoy/extensions/filters/http/jwt_authn/v3/config.pb.go#L306