Skip to content

CORS Annotation Not Behaving as Expected #10267

Open
@benosmond

Description

@benosmond

I added CORS annotations to my chart, but the CORS headers are only being returned from OPTIONS requests. GET requests are missing the headers, which causes errors in the browser.

Annotations added:
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "*"
nginx.ingress.kubernetes.io/cors-allow-credentials: "false"
nginx.ingress.kubernetes.io/cors-allow-headers: (...headers)

OPTIONS requests to (my API URL) are working as I expect, with the CORS headers being returned.
GET requests to (my API URL) are not behaving as expected, with no CORS headers in the response at all.

I was expecting that all allowed request methods would be returned with CORS response headers e.g.:
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: (...headers)
Access-Control-Allow-Methods: ...
Etc.

Without these on the GET request the browser seems to give a CORS error for every request, making the API unusable.

I considered applying the individual headers I want manually using snippets but it seems like this configuration should be possible using the CORS annotations? Any help much appreciated.

Activity

added
needs-triageIndicates an issue or PR lacks a `triage/foo` label and requires one.
on Aug 1, 2023
k8s-ci-robot

k8s-ci-robot commented on Aug 1, 2023

@k8s-ci-robot
Contributor

This issue is currently awaiting triage.

If Ingress contributors determines this is a relevant issue, they will accept it by applying the triage/accepted label and provide further guidance.

The triage/accepted label can be added by org members by writing /triage accepted in a comment.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

simplyzee

simplyzee commented on Aug 3, 2023

@simplyzee

I dealt with the same problem yesterday with Access-Control-Allow-Origin: * always returning based on the backend logic that NGINX generates for service via the nginx.conf as soon as I specified the annotation: nginx.ingress.kubernetes.io/cors-allow-origin: <host>

I had to take an alternative approach using the nginx.ingress.kubernetes.io/configuration-snippet annotation, setting headers with the more_set_headers function.

Here's what works for me - I updated the logic to support multiple origins - https://serverfault.com/a/1036160 (Thank you Marcel!)
This is a temporary workaround for me until the annotation logic works again.

annotations:
  nginx.ingress.kubernetes.io/configuration-snippet: |-
    if ($http_origin ~* "^https?://(example.com|example2.com)$") {
        set $allow_origin $http_origin;
    }

    more_set_headers 'Access-Control-Allow-Origin: $allow_origin';
    more_set_headers 'Access-Control-Allow-Credentials: true';
    more_set_headers 'Access-Control-Allow-Methods: GET , OPTIONS, POST';
    more_set_headers 'Access-Control-Allow-Headers: Authorization,Content-Type';
    # Cors Preflight methods needs additional options and different Return Code - UPDATED
    if ($request_method = 'OPTIONS') {
        more_set_headers 'Access-Control-Max-Age: 1728000';
        more_set_headers 'Content-Type: text/plain charset=UTF-8';
        more_set_headers 'Content-Length: 0';
        return 204;
    }
strongjz

strongjz commented on Aug 3, 2023

@strongjz
Member

Can provide the nginx.conf? The version of the controller, deployment and other logs that might be helpful, and the ingress resource you are using to test?

-James

benosmond

benosmond commented on Aug 3, 2023

@benosmond
Author

I had to take an alternative approach using the nginx.ingress.kubernetes.io/configuration-snippet annotation, setting headers with the more_set_headers function.

I opted for a similar workaround in the end, but it's still disappointing to not be able to use the annotation.

Can provide the nginx.conf? The version of the controller, deployment and other logs that might be helpful, and the ingress resource you are using to test?

@strongjz can I ask what you mean by 'the ingress resource you are using to test'?

github-actions

github-actions commented on Sep 3, 2023

@github-actions

This is stale, but we won't close it automatically, just bare in mind the maintainers may be busy with other tasks and will reach your issue ASAP. If you have any question or request to prioritize this, please reach #ingress-nginx-dev on Kubernetes Slack.

added
lifecycle/frozenIndicates that an issue or PR should not be auto-closed due to staleness.
on Sep 3, 2023
sinacek

sinacek commented on Apr 5, 2024

@sinacek
Contributor

Hi @strongjz,
I have similar question problem.

TLDR: This configuration send cors headers only when origin is equal https://mysite.com. In all other case it sends no cors, so the source doesn't say to browser for which origin is intended.

Image: registry.k8s.io/ingress-nginx/controller:v1.10.0
Logs: doesn't contains any error.

Nginx.conf

set $proxy_alternative_upstream_name "";

# Cors Preflight methods needs additional options and different Return Code

if ($http_origin ~* ((https://mysite\.com))$ ) { set $cors 'true'; }

if ($request_method = 'OPTIONS') {
	set $cors ${cors}options;
}

if ($cors = "true") {
	more_set_headers 'Access-Control-Allow-Origin: $http_origin';
	more_set_headers 'Access-Control-Allow-Credentials: true'; 
	more_set_headers 'Access-Control-Allow-Methods: GET, PUT, POST, DELETE, PATCH, OPTIONS';
	more_set_headers 'Access-Control-Allow-Headers: DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization';
	
	more_set_headers 'Access-Control-Max-Age: 1728000';
}

if ($cors = "trueoptions") {
	more_set_headers 'Access-Control-Allow-Origin: $http_origin';
	more_set_headers 'Access-Control-Allow-Credentials: true'; 
	more_set_headers 'Access-Control-Allow-Methods: GET, PUT, POST, DELETE, PATCH, OPTIONS';
	more_set_headers 'Access-Control-Allow-Headers: DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization';
	
	more_set_headers 'Access-Control-Max-Age: 1728000';
	more_set_headers 'Content-Type: text/plain charset=UTF-8';
	more_set_headers 'Content-Length: 0';
	return 204;
}

client_max_body_size                    1m;

proxy_set_header Host                   $best_http_host;

Ingess

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    acme.cert-manager.io/http01-edit-in-place: "true"
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/cors-allow-origin: https://mysite.com
    nginx.ingress.kubernetes.io/enable-cors: "true"

Related code rows:

patog

patog commented on Aug 1, 2024

@patog

same problem in 1.9.4, is anything new with this issue?

elizabeth-dev

elizabeth-dev commented on Nov 21, 2024

@elizabeth-dev
Member

@benosmond @patog could you share the yaml for the Ingress resource that is causing your issue? I've just tried to reproduce it with this config:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/cors-allow-credentials: "false"
    nginx.ingress.kubernetes.io/cors-allow-headers: x-forwarded-for,foo
    nginx.ingress.kubernetes.io/cors-allow-origin: '*'
    nginx.ingress.kubernetes.io/enable-cors: "true"
  name: demo-localhost
  namespace: default
spec:
  ingressClassName: nginx
  rules:
  - host: demo.localdev.me
    http:
      paths:
      - backend:
          service:
            name: demo
            port:
              number: 80
        path: /
        pathType: Prefix

and I got this response on a GET request (note the Access-Control-Allow-Headers header present in the response):

~ curl -v --location 'http://demo.localdev.me'                                                                        20:50:00
* Host demo.localdev.me:80 was resolved.
* IPv6: (none)
* IPv4: 192.168.64.2
*   Trying 192.168.64.2:80...
* Connected to demo.localdev.me (192.168.64.2) port 80
> GET / HTTP/1.1
> Host: demo.localdev.me
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< Date: Thu, 21 Nov 2024 19:50:11 GMT
< Content-Type: text/html
< Content-Length: 50
< Connection: keep-alive
< Last-Modified: Thu, 21 Nov 2024 19:50:02 GMT
< ETag: "673f8eea-32"
< Accept-Ranges: bytes
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: GET, PUT, POST, DELETE, PATCH, OPTIONS
< Access-Control-Allow-Headers: x-forwarded-for,foo
< Access-Control-Max-Age: 1728000
<
HOSTNAME=demo-c879b6c47-tftbm
* Connection #0 to host demo.localdev.me left intact
elizabeth-dev

elizabeth-dev commented on Nov 21, 2024

@elizabeth-dev
Member

/triage not-reproducible

17 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

needs-kindIndicates a PR lacks a `kind/foo` label and requires one.needs-priorityneeds-triageIndicates an issue or PR lacks a `triage/foo` label and requires one.triage/needs-informationIndicates an issue needs more information in order to work on it.triage/not-reproducibleIndicates an issue can not be reproduced as described.

Type

No type

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

    Development

    Participants

    @icy@sinacek@strongjz@longwuyuan@simplyzee

    Issue actions

      CORS Annotation Not Behaving as Expected · Issue #10267 · kubernetes/ingress-nginx