Conditional Istio EnvoyFilter based on Cookie presence

12/3/2021

Currently we're using an EnvoyFilter to add an authentication check. This filter makes use of the envoy ext_authz filter.

We have a GraphQL endpoint that is used for both anonymus and authorised calls. Since the public calls don't need an auth check/filter I would like to be able to skip this filter based on a cookie. I tried searching for a solution online but wasn't able to find one.

See the configuration for the filter below:

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: oathkeeper
  namespace: istio-system
spec:
  workloadSelector:
    labels:
      istio: ingressgateway
  configPatches:
    - applyTo: HTTP_FILTER
      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: envoy.filters.http.ext_authz
          typed_config:
            '@type': type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
            failure_mode_allow: false
            http_service:
              path_prefix: /decisions
              server_uri:
                uri: http://oathkeeper-api.default.svc.cluster.local:4456
                cluster: outbound|4456||oathkeeper-api.default.svc.cluster.local
                timeout: 10s
              authorization_request:
                allowed_headers:
                  patterns:
                  - exact: accept
                  - exact: authorization
                  - exact: cookie
                  - exact: content-type
                  - exact: x-forwarded-for
                  - exact: x-forwarded-proto
                  - exact: x-forwarded-host
              authorization_response:
                allowed_upstream_headers:
                  patterns:
                  - exact: authorization
-- toonvanstrijp
envoyproxy
istio
istio-gateway
kubernetes

1 Answer

12/4/2021

You could configure a second VirtualService route for the endpoint that matches on missing cookie

[...]
  http:
  - name: secured-graph-ql-endpoint
    match:
    - headers:
        cookie:
          regex: <some-regex>
      uri:
        prefix: /graph-ql-endpoint
    route:
    - destination:
        host: graph-ql-endpoint
        port:
          number: 8000
  - name: public-graph-ql-endpoint
    match:
    - uri:
        prefix: /graph-ql-endpoint
    route:
    - destination:
        host: graph-ql-endpoint
        port:
          number: 8000

with a regex (<some-regex>) depending on your cookie. You could also have a header like authenticated: true and match on that, instead of a (missing) cookie.

Create an EnvoyFilter to disable the ExtAuthz for that route.

apiVersion​: ​networking.istio.io/v1alpha3 
kind​: ​EnvoyFilter 
metadata​: 
  name​: bypass-ext-authz 
  namespace​: ​istio-system 
spec​: 
  workloadSelector​: 
    labels​: 
      istio​: ​ingressgateway 
  configPatches​: 
   - ​applyTo​: ​HTTP_ROUTE 
     ​match​: 
       ​routeConfiguration​: 
         vhost​: 
           route​: 
             #​from virtual service http route name 
             name​: public-graph-ql-endpoint
     ​patch​: 
       ​operation​: ​MERGE 
       ​value​: 
         ​name​: ​custom.bypass_extauthz 
         ​typed_per_filter_config​: 
           ​envoy.ext_authz​: 
             ​"​@type​"​: ​type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthzPerRoute 
             ​disabled​: ​true

You could also add the configPatch to your existing EnvoyFilter.

Having said that:

From a design/security perspective I would rather have a different application that is publicly exposed and that queries the secured GraphQL endpoint for the anonymous user. That gives you much more control over traffic like rate limiting for external user, easier dos protection, etc.

-- Chris
Source: StackOverflow