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.

could you add the rbac debug log? It should include the headers as well which can tell if the authorization header is being forwarded from ingress gw.

Also the error code is 503 which seems unrelated to authorization deny (it should be 403 if it was), so it could also be due to something else.