Configuring CORS

I have problem configuring CORS for the service exposed by ingress gateway.
My goal is to get CORS headers when sending OPTION request.
I’m migrating from Nginx-ingress and for nginx it was as easy as setting the annotation nginx.ingress.kubernetes.io/enable-cors: "true" in the ingress.

My configuration:
Gateway:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: example
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 80
        name: http
        protocol: HTTP
      hosts:
        - example.com
    - port:
        number: 443
        name: https
        protocol: HTTPS
      tls:
        mode: SIMPLE
        credentialName: example-tls
      hosts:
        - example.com

Virtualservice:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: example
spec:
  hosts:
    - "example.com"
  gateways:
    - example
  http:
    - match:
        - uri:
            prefix: /api/graphql
      route:
        - destination:
            host: example.default.svc.cluster.local
            port:
              number: 9999
      corsPolicy:
        allowMethods:
          - POST
          - OPTIONS
        allowOrigin:
          - https://example.com
        allowHeaders:
          - authorization
          - content-type
    - route:
        - destination:
            host: example-ui.default.svc.cluster.local
            port:
              number: 80

When I try to run the curl I get:

curl -X OPTIONS https://example.com/api/graphql -I
HTTP/2 404
content-type: text/plain; charset=UTF-8
date: Fri, 10 Jul 2020 14:31:52 GMT
content-length: 9
x-envoy-upstream-service-time: 4
server: istio-envoy

What I expect is something like this (this is output from Nginx-ingress)

curl -X OPTIONS https://example.com/api/graphql -I
HTTP/2 204
server: nginx/1.17.8
date: Fri, 10 Jul 2020 14:57:39 GMT
strict-transport-security: max-age=15724800; includeSubDomains
access-control-allow-origin: *
access-control-allow-credentials: true
access-control-allow-methods: POST, OPTIONS
access-control-allow-headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization
access-control-max-age: 1728000

Can someone please point what I’m doing wrong?

1 Like

If you use istio 1.6+ you might need to change allowOrigin to allowOrigins with exact as mentioned here.

Thank you @jt97 for this link. Making such change indeed changed the Istio-proxy config when I check it with istioctl proxy-config.

It’s a shame this change is not documented.
Unfortunately, it didn’t solve my problem.
I still don’t see any of the access-control-* headers.
Instead, I still get 404 error if I send a request with OPTIONS method as shown in my original post.

Oof, that’s several frustrating hours of my life that I won’t be getting back :confused:

Would be great if the old examples were updated also. For example:

I ran into the same situation with Istio 1.6.10, have you been able to solve this issue?

I finally figured it out. Two things you need to pay attention:

  1. You need to add the allowed origins in the allowOrigins field.
  2. You need to specify the “Origin” header in the curl command to indicate that it’s a cors request.

Otherwise, the access-control-allow-* headers won’t show up.
For instance:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: cors-rule
spec:
 hosts:
 - http-server.default.svc.cluster.local
 http:
 - route:
   - destination:
       host: http-server.default.svc.cluster.local
   corsPolicy:
     allowOrigins:
     - exact: http://www.example.com
     allowMethods:
     - POST
     - GET
     allowHeaders:
     - X-Custom-Header
     exposeHeaders:
     - X-Expose-Header
     maxAge: 24h
     allowCredentials: false

k exec http-server-6cc8fd5c68-cnp9h - curl -sv -H “Origin: http://www.example.com” http-server.default.svc.cluster.local/test

1 Like

Sorry I haven’t answered, I wasn’t able to make it working as expected.
Thank you for sharing working solution!