Adding JWT authorization to an ingress gateway

Hello,

I’m trying to authorize incoming requests on a gateway using a JWT. Here’s what my Gateway / VirtualService look like:

# Ingress GW
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: my-ingress-gateway
spec:
  selector:
    istio: ingressgateway # use Istio default gateway implementation
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "httpbin.myhost.com"
---
# Routes mapping for the GW
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: my-httpbin-virtual-service
spec:
  hosts:
  - "httpbin.myhost.com"
  gateways:
  - my-ingress-gateway
  http:
  - match:
    - uri:
        prefix: /httpbin
    route:
    - destination:
        port:
          number: 80
        host: my-app-service
    rewrite:
      uri: /

It works just fine without authn/authz.

Now, if I add my RequestAuthentication and AuthorizationPolicy as follows:

---
apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
  name: my-service-req-authn
spec:
  selector:
    matchLabels:
      app: my-app
  jwtRules:
  - issuer: christophe
    jwks: >
      { "keys":[ {"e":"AQAB","kid":"DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-envvQ","kty":"RSA","n":"xAE7eB6qugXyCAG3yhh7pkDkT65pHymX-P7KfIupjf59vsdo91bSP9C8H07pSAGQO1MV_xFj9VswgsCg4R6otmg5PV2He95lZdHtOcU5DXIg_pbhLdKXbi66GlVeK6ABZOUW3WYtnNHD-91gVuoeJT_DwtGGcp4ignkgXfkiEm4sw-4sfb4qdt5oLbyVpmW6x9cfa7vs2WTfURiCrBoUqgBo_-4WTiULmmHSGZHOjzwa8WtrtOQGsAFjIbno85jp6MnGGGZPYZbDAa_b3y5u-YpW7ypZrvD8BgtKVjgtQgZhLAGezMt0ua3DRrWnKqTZ0BJ_EyxOGuHJrLsn00fnMQ"}]}
    
    
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: my-app
spec:
  selector:
    matchLabels:
      app: my-app
  action: ALLOW
  rules:
  - to:
    - operation:
        methods: ["GET"]
    from:
    - source:
        requestPrincipals: ["*"]
    when:
    - key: request.auth.claims[scope]
      values: ["myapp.read"]
  - to:
    - operation:
        methods: ["POST"]
    from:
    - source:
        requestPrincipals: ["*"]
    when:
    - key: request.auth.claims[scope]
      values: ["myapp.write"]

Then here’s what happens:

  • JWT authn/authz works just fine from inside the cluster.

      $ export JWT=eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE2MjE4NzI5NjYsImlhdCI6MTYyMTg2OTM2NiwiaXNzIjoiY2hyaXN0b3BoZSIsInNjb3BlIjpbIm15YXBwLnJlYWQiLCJteWFwcC53cml0ZSJdLCJzdWIiOiJqb2huLmRvZSJ9.vFOR4DMEBCa8owMw1f_y5opcIQK1z6hWprbr3pXbP-ZmgT9kCSvbEw15m8AA-k4fUg8TWP-yjzkExiJkgusELQbLwwDzTVUDw72M4dbfhthlVir7bBknAiwwFZRJd8l5kL6-9Pj5R8dtHNFbTgVzrfaJLMA_QNMXU7qu2_HM-FHRQnaQBEnlBUrSiavXuQ7V8a0XxXiXPXkv_8kn2fm5iTACQDm_cDlX7SVYjdh7SsY1Jsh1TXVhDpxJtgM3Oi0t0kDh3G2w14FR-pvIZEesX5tIewmvC-zneeaGehTKG1th16dfnmaq2TdOsBO7kIljt129FucotulLsknLLCQntA
    
      $ curl my-app-service/get -H "Authorization: Bearer $JWT"
      {
        "origin": "127.0.0.6"
      }
    
  • Accessing the service via the ingress gateway stops working:

      $ curl -H "Host: httpbin.myhost.com" 188.166.135.254/httpbin/get -H "Authorization: Bearer $JWT" -v
      < HTTP/1.1 503 Service Unavailable
      < content-length: 95
      < content-type: text/plain
      < date: Mon, 24 May 2021 15:33:53 GMT
      < server: istio-envoy
      < 
      * Connection #0 to host 188.166.135.254 left intact
      upstream connect error or disconnect/reset before headers. reset reason: connection termination
    

This is the RBAC logger’s error message in my sidecar (after setting its level to debug):

debug envoy rbac checking connection: requestedServerName: outbound_.80_._.my-app-service.default.svc.cluster.local, sourceIP: 10.244.0.93:54180, …

debug envoy rbac enforced denied, matched policy none

I suspect this might be related with the Authorization header not being forwarded by the ingress gateway (?)

Any idea?

Thank you!

cc @YangminZhu for authorization on gateway.