Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CORS Annotation Not Behaving as Expected #10267

Open
benosmond opened this issue Aug 1, 2023 · 15 comments · May be fixed by #12424
Open

CORS Annotation Not Behaving as Expected #10267

benosmond opened this issue Aug 1, 2023 · 15 comments · May be fixed by #12424
Assignees
Labels
needs-kind Indicates a PR lacks a `kind/foo` label and requires one. needs-priority needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. triage/needs-information Indicates an issue needs more information in order to work on it. triage/not-reproducible Indicates an issue can not be reproduced as described.

Comments

@benosmond
Copy link

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.

@k8s-ci-robot k8s-ci-robot added the needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. label Aug 1, 2023
@k8s-ci-robot
Copy link
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.

@k8s-ci-robot k8s-ci-robot added needs-kind Indicates a PR lacks a `kind/foo` label and requires one. needs-priority labels Aug 1, 2023
@simplyzee
Copy link

simplyzee commented Aug 3, 2023

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
Copy link
Member

strongjz commented Aug 3, 2023

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
Copy link
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
Copy link

github-actions bot commented Sep 3, 2023

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.

@github-actions github-actions bot added the lifecycle/frozen Indicates that an issue or PR should not be auto-closed due to staleness. label Sep 3, 2023
@sinacek
Copy link
Contributor

sinacek commented Apr 5, 2024

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
Copy link

patog commented Aug 1, 2024

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

@elizabeth-dev
Copy link
Contributor

@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
Copy link
Contributor

/triage not-reproducible

@k8s-ci-robot k8s-ci-robot added the triage/not-reproducible Indicates an issue can not be reproduced as described. label Nov 21, 2024
@longwuyuan
Copy link
Contributor

/remove-lifecycle frozen
/triage needs-information

@k8s-ci-robot k8s-ci-robot added triage/needs-information Indicates an issue needs more information in order to work on it. and removed lifecycle/frozen Indicates that an issue or PR should not be auto-closed due to staleness. labels Nov 21, 2024
@elizabeth-dev
Copy link
Contributor

/assign

@benosmond
Copy link
Author

@elizabeth-dev

@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:

Unfortunately it's been a while and I no longer have the YAML I was using to test this. I ended up using a configuration snippet to add in the headers I wanted to every request, which worked fine at the cost of a few extra lines.

From what I remember, the chart I was using looked pretty much the same as your example, so maybe this is working now.

@elizabeth-dev
Copy link
Contributor

@benosmond yeah, sorry about that... happy to see that the issue seems to be solved though!

@awoimbee
Copy link
Contributor

awoimbee commented Nov 25, 2024

I have the same problem when I have this configuration snipped also applied on my ingress (from this issue):

nginx.ingress.kubernetes.io/configuration-snippet: |
            set $forwarded_scheme $http_x_forwarded_proto;
            if ($forwarded_scheme = "") {
                set $forwarded_scheme $scheme;
            }
            if ($forwarded_scheme = "http") {
              return 403 "This endpoint is only accessible via HTTPS. You are currently using plaintext HTTP.";
            }

curl -i -X OPTIONS https://... returns CORS headers but not curl -i -X GET https://...

Full definition:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/configuration-snippet: |-
      set $forwarded_scheme $http_x_forwarded_proto;
      if ($forwarded_scheme = "") {
          set $forwarded_scheme $scheme;
      }
      if ($forwarded_scheme = "http") {
        return 403 "This endpoint is only accessible via HTTPS. You are currently using plaintext HTTP.";
      }
    nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
    nginx.ingress.kubernetes.io/cors-allow-headers: DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Org
    nginx.ingress.kubernetes.io/cors-allow-methods: GET, POST, PUT, PATCH, DELETE,
      OPTIONS
    nginx.ingress.kubernetes.io/cors-allow-origin: https://toto.example.com, https://*.toto.example.com
    nginx.ingress.kubernetes.io/cors-expose-headers: Location, x-pagination, Link
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/modsecurity-snippet: |-
      SecRuleRemoveById 920220
  name: super-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: api.toto.example.com
    http:
      paths:
      - backend:
          service:
            name: toto-api
            port:
              number: 8080
        path: /
        pathType: Prefix

@elizabeth-dev
Copy link
Contributor

@awoimbee thank you for sharing that specific case, because I've been able to pinpoint the underlying issue.

basically, it seems like if directives in Nginx behave... in an interesting way (to say something), and it seems the code for the CORS headers was sometimes affected (not always it seems)

in any case, fix is on its way!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs-kind Indicates a PR lacks a `kind/foo` label and requires one. needs-priority needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. triage/needs-information Indicates an issue needs more information in order to work on it. triage/not-reproducible Indicates an issue can not be reproduced as described.
Projects
Development

Successfully merging a pull request may close this issue.

9 participants