I'd like to understand in which order RequestAuthentications
and AuthorizationPolicies
are executed for an istio-ingressgateway
.
In a PoC, I'm defining the following RequestAuthentication
and AuthorizationPolicy
for the istio-ingressgateway, where the AuthorizationPolicy
uses the CUSTOM
action (external authorizer):
apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
name: ingress-reguest-authentication
namespace: istio-system
spec:
jwtRules:
-
issuer: "https://<my-issuer>"
jwksUri: "https://<my-issuer>/oauth2/jwks"
forwardOriginalToken: true
outputPayloadToHeader: x-forwarded-jwt-payload
selector:
matchLabels:
istio: ingressgateway
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: ingress-ext-authz
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway
action: CUSTOM
provider:
name: ext-authz-http
rules: [{}]
With the RequestPolicy
I'd like to let Istio handle the basic token validation before the external authorizer performs additional checks, for which Istio doesn't provide configuration (in my case I want to verify that the mTLS client certificate and JWT token for an incoming request match according to RFC 8705). Since I don't want to validate the token again in the external authorizer, I'm using the outputPayloadToHeader
to forward the payload of the validated JWT.
However, to my surprise, it looks like the external authorizer is actually called before the request authentication happens:
x-forwarded-jwt-payload
header defined in the RequestAuthentication
is not arriving at the external authorizer (I ended up using the Authorization header instead to extract the JWT payload myself).This is not what I had expected, given that ALLOW
/DENY
actions for authorization policies support rules which inspect JWT claims, which I assumed would be evaluated for an already validated JWT.
Is this the order in which Istio processes RequestAuthentication
and AuthorizationPolicy
in general or is it specific to the CUSTOM
action?
Or is there simply something wrong in my configuration?
In the end, what helped to get the order right was configuring the external authorizer through an envoy filter that is plugged into the http_connection_manager
filter chain right before http router filter.
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: ingress-ext-authz
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
failureModeAllow: false
httpService:
serverUri:
cluster: outbound|8000||ext-authz.default.svc.cluster.local
timeout: 1s
uri: http://ext-authz.default.svc.cluster.local
authorizationRequest:
allowedHeaders:
patterns:
- exact: x-forwarded-jwt-payload
- exact: x-forwarded-client-cert