Cors preflight does not work when Jwt Policy targets the Istio Ingress Gateway

Kubernetes: 1.13.5
Istio: 1.2

Cors preflight requests do not work when a Jwt Policy is configured on the istio-ingressgateway target.

OPTIONS preflight request should be passed through according to this merged PR. In my case, the preflight requests are always 401 Unauthorized, even when using the authentication token.

>TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.2/security/tools/jwt/samples/demo.jwt -s)
>curl --head -X OPTIONS -s $INGRESS_URL -H 'Host: httpbinext.foo.svc.cluster.local' -H 'Access-Control-Request-Method: GET' -H 'Access-Control-Request-Headers: Content-Type, Accept' -H 'Origin: example.com' -H "Authorization: Bearer $TOKEN"
HTTP/1.1 401 Unauthorized
content-length: 29
content-type: text/plain
date: Thu, 08 Aug 2019 12:00:28 GMT
server: istio-envoy

Other regular requests (GET POST etc) seem to work as expected with Jwt auth configured on the Istio Ingress Gateway.

Note: The reason that I am configuring Jwt Policy on the istio-ingressgateway target and not on the service name, is because I need to integrate an ExternalName type service with Jwt & Cors through Istio.

Here is the policy that I use:

>cat <<EOF | kubectl apply -n istio-system -f -
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
  name: "jwt-ingress"
spec:
  targets:
  - name: istio-ingressgateway    
  origins:
  - jwt:
      issuer: "testing@secure.istio.io"
      jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.2/security/tools/jwt/samples/jwks.json"
  principalBinding: USE_ORIGIN
EOF

Here is the remaining configuration:

I have configured the following ExternalName service for httpbin.org in Kubernetes.

>kubectl apply -f - <<EOF
apiVersion: v1                                
kind: Service
metadata:
  name: httpbinext
  namespace: foo
spec:
  externalName: httpbin.org
  ports:
  - name: http-httpbinext
    port: 80                           
    protocol: TCP                                                                                              
    targetPort: 80
  sessionAffinity: None
  type: ExternalName
EOF

as well as this Gateway configuration

>kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: httpbinext-gateway
  namespace: foo        
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:                        
      number: 80                                                                                               
      name: http
      protocol: HTTP
    hosts:
    - "httpbinext.foo.svc.cluster.local"
EOF

and the following VirtualService

>kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: httpbinext
  namespace: foo
spec:
  hosts:
  - httpbinext.foo.svc.cluster.local
  gateways:
  - mesh                               
  - httpbinext-gateway                                                                                         
  http:                       
  - route:
    - destination:
        host: httpbinext
    corsPolicy:
      allowOrigin:
      - 'example.com'
      allowMethods:
      - POST
      - GET
      - OPTIONS
      allowCredentials: false
      allowHeaders:
      - X-Foo-Bar
      - X-Bar-Foo
      maxAge: "24h"
EOF

Any help would be appreciated.

1 Like

I have also verified that Cors stops working for any service inside K8s (not only the ExternalName service) when I configure Jwt on the Istio gateway target.

I think @leitang added the preflight support in istio/proxy, could you help take a look, thanks. It seems this is failing in 1.2, @kostas to confirm.

Yes it is failing in 1.2.

By the way, the way that I’ve overcome the problem was to rollout a reverse proxy (Traefik deployed as a pod, not an ingress) inside Kubernetes with a configuration for the external service.
Then I applied a Jwt policy using the reverse proxy svc as a target and not the Istio Ingress gateway.
This worked and I have verified that both Cors and Jwt work as expected together.

Thanks for the information, I filed to track the issue: https://github.com/istio/istio/issues/16171