Search code examples
kubernetescorshttp-status-code-403istio

Preflight (OPTIONS) returns 403, CORS


We are using Kubernetes with Istio and have configured a virtual service:

  http:
  - match:
    - uri:
        prefix: /api
    rewrite:
      uri: /api
    route:
    - destination:
        host: svc-api
        port:
          number: 80
        subset: stable
      weight: 0
    - destination:
        host: svc-api
        port:
          number: 80
        subset: vnext
      weight: 100
    corsPolicy: &apiCorsPolicy
      allowOrigins:
      - exact: '*'
      allowMethods:
      - GET
      - POST
      - OPTIONS
      allowCredentials: true
      allowHeaders:
      - "*"
  - match:
    - uri:
        prefix: /
    rewrite:
      uri: /
    route:
    - destination:
        host: svc-api
        port:
          number: 80
        subset: stable
      weight: 0
    - destination:
        host: svc-api
        port:
          number: 80
        subset: vnext
      weight: 100
    corsPolicy: *apiCorsPolicy

Making a request to https://[host]/api/* from a browser fails on OPTIONS request with 'from origin [request] has been blocked by CORS policy'.

Describing the service in k8 shows the correct configurations.

According to v 1.6.4 the structure using allowOrigins and exact instead of allowOrigin is correct.

What am I missing here?


Solution

  • Few things worth to mention here.


    Recently in older istio versions there were a problem with cors and jwt combined together, take a look at below links:


    There is another github issue about that, in this comment community member have the same issue, maybe it's worth to open a new github issue for that?


    Additionally there is an answer from istio dev @howardjohn

    Hi everyone. Testing CORS using curl can be a bit misleading. CORS is not enforced at the server side; it will not return a 4xx error for example. Instead, headers are returned back which are used by browsers to deny/accept. https://www.envoyproxy.io/docs/envoy/latest/start/sandboxes/cors.html?highlight=cors gives a good demo of this, and https://www.sohamkamani.com/blog/2016/12/21/web-security-cors/#:~:text=CORS%20isn't%20actually%20enforced,header%20in%20all%20its%20responses. is a good explanation.

    So Istio's job here is simply to return these headers. I have added a test showing this works: #26231.


    As I mentioned in comment worth to take a look at another community member configuration here, as he has a working options example, but have a 403 issue with POST.


    Few things I would change in your virtual service

    Use just corsPolicy instead of corsPolicy: &apiCorsPolicy

    corsPolicy:
    

    Instead of exact you can also use regex which may do the trick for wildcards.

    allowOrigins:
    - regex: '*'
    

    About the / and /api paths, I think prefix is enough here, you don't need rewrite.