ingress-nginx: nginx.ingress.kubernetes.io/cors-allow-origin doesn't seem to work?
When I enable the cors header using this annotation:
nginx.ingress.kubernetes.io/enable-cors: “true” nginx.ingress.kubernetes.io/cors-allow-methods: “GET”
I will get the * domain annotation and all the methods allowed. I am able to use this annotation to only allow for GETs, which also works. But when I try to add this:
nginx.ingress.kubernetes.io/cors-allow-origin: http://localhost:3000
(Or any other domain for that matter), I get no cors headers at all. When that is removed, the cors headers show up again.
NGINX Ingress controller Release: v1.1.3 Build: 9d3a285f19a704524439c75b947e2189406565ab Repository: https://github.com/kubernetes/ingress-nginx nginx version: nginx/1.19.10
Kubernetes version (use kubectl version
):
Client Version: version.Info{Major:“1”, Minor:“23”, GitVersion:“v1.23.5”, GitCommit:“c285e781331a3785a7f436042c65c5641ce8a9e9”, GitTreeState:“clean”, BuildDate:“2022-03-16T15:58:47Z”, GoVersion:“go1.17.8”, Compiler:“gc”, Platform:“linux/amd64”} Server Version: version.Info{Major:“1”, Minor:“23”, GitVersion:“v1.23.3”, GitCommit:“816c97ab8cff8a1c72eccca1026f7820e93e0d25”, GitTreeState:“clean”, BuildDate:“2022-01-25T21:19:12Z”, GoVersion:“go1.17.6”, Compiler:“gc”, Platform:“linux/amd64”}
Environment:
-
Cloud provider or hardware configuration: minikube on local hardware, virtualbox provider
-
OS (e.g. from /etc/os-release): Ubuntu 21.10
-
Kernel (e.g.
uname -a
): victory 5.13.0-39-lowlatency -
Install tools:
Please mention how/where was the cluster created like kubeadm/kops/minikube/kind etc.
-
Basic cluster related info:
kubectl version
kubectl get nodes -o wide
-
How was the ingress-nginx-controller installed: ArgoCD / Helm
Helm values: ingress-nginx: controller: config: compute-full-forwarded-for: “true” large-client-header-buffers: “4 64k” proxy-body-size: “100m” proxy-buffer-size: “64k” ssl-redirect: “true” use-forwarded-headers: “true” service: type: ClusterIP hostNetwork: true dnsPolicy: ClusterFirstWithHostNet admissionWebhooks: enabled: false extraArgs: default-ssl-certificate: ingress-nginx/ingress-certificate podLabels: gafaelfawr.lsst.io/ingress: “true” hub.jupyter.org/network-access-proxy-http: “true” metrics: enabled: true service: annotations: prometheus.io/port: “10254” prometheus.io/scrape: “true”
- Current State of the controller:
kubectl describe ingressclasses
Name: nginx Labels: app.kubernetes.io/component=controller app.kubernetes.io/instance=ingress-nginx app.kubernetes.io/managed-by=Helm app.kubernetes.io/name=ingress-nginx app.kubernetes.io/part-of=ingress-nginx app.kubernetes.io/version=1.1.3 argocd.argoproj.io/instance=ingress-nginx helm.sh/chart=ingress-nginx-4.0.19 Annotations: <none> Controller: k8s.io/ingress-nginx Events: <none>
Here’s my ingress yaml:
apiVersion: v1
items:
- apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
meta.helm.sh/release-name: sherlock-dev
meta.helm.sh/release-namespace: sherlock-dev
nginx.ingress.kubernetes.io/auth-method: GET
nginx.ingress.kubernetes.io/auth-response-headers: X-Auth-Request-User,X-Auth-Request-Email,X-Auth-Request-Token
nginx.ingress.kubernetes.io/auth-signin: https://minikube.lsst.codes/login
nginx.ingress.kubernetes.io/auth-url: https://minikube.lsst.codes/auth?scope=exec:admin
nginx.ingress.kubernetes.io/cors-allow-methods: GET
nginx.ingress.kubernetes.io/enable-cors: "true"
creationTimestamp: "2022-04-13T00:49:04Z"
generation: 1
labels:
app.kubernetes.io/instance: sherlock-dev
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: sherlock
app.kubernetes.io/version: 0.1.6
helm.sh/chart: sherlock-0.1.11
name: sherlock-dev
namespace: sherlock-dev
resourceVersion: "82836"
uid: afd005c3-ba99-4477-bc0a-cdc166e17398
spec:
rules:
- host: minikube.lsst.codes
http:
paths:
- backend:
service:
name: sherlock-dev
port:
number: 8080
path: /sherlock
pathType: ImplementationSpecific
status:
loadBalancer:
ingress:
- ip: 10.98.0.156
kind: List
metadata:
resourceVersion: ""
selfLink: ""
About this issue
- Original URL
- State: open
- Created 2 years ago
- Reactions: 8
- Comments: 22 (10 by maintainers)
In my case was that the backend was returning wrong CORS headers (Allow *) and nginx is not overwritting them. If backend sends an *, nginx just append it to the nginx.ingress.kubernetes.io/cors-allow-origin response header. Is there a way to overwrite this behaviour without modifying the backend?
Is there any movement on this? It looks like there’s a PR… I really need this working.
I had a similar issue (getting CORS issues in Burp Suite Vulnerability test) and, it finally worked with this:
If I Remove any cors related annotation, and add:
it returns the right header (Access-Control-Allow-Origin: https://*.example.com) but fails in Burp Suite Vulnerability test.
If I add also
nginx.ingress.kubernetes.io/enable-cors: 'true'
Returns also the ‘Access-Control-Allow-Origin: *’ header but passes the Vulnerability test.
I hope that this maybe helps someone
@rudolfbyker case3 & case4 are a cause of concern.
I will try to take a look at this when I have time Until then feel free to comment 😃
The expected behavior for the CORS preflight request (the OPTIONS request) is that the server responds to all requests, regardless of origin, to indicate what type of requests are allowed on the resource. Browsers use the results of preflight requests to determine if the actual requests should be sent. The Mozilla CORS documentation describes this requirement. Without responding to the preflight request for non-allowed origins, the browser cannot decide that it is unsafe to send the original request, which is the purpose of setting up CORS in nginx.
To handle multiple allowed origins, the server also needs to set the
Vary
response header toOrigin
to indicate to browsers that the response can change based on theOrigin
request header. This way different allowed-origins can be returned and the browser can handle caching the information appropriately.What is not clear is how origins with wildcarded subdomains should be handled because it doesn’t appear that
https://*.example.com
is a valid value forAccess-Control-Allow-Origin
. I think it’s unclear how a browser might choose to handle such a response. Maybe anginx.ingress.kubernetes.io/cors-default-allow-origin
value is required when wildcarded subdomains are used? For a strict list of valid allowed origins, I think it’s acceptable just to return one of them as long as theVary
header is set.Thanks for the pointer to the e2e tests. I think what’s missing are the tests for the preflight requests specifically, which is the
trueoptions
branch in the current implementation. I don’t see coverage for OPTIONS requests from either an allowed origin or a non-allowed origin. I think what we need here is essentially afalseoptions
branch that can handle multiple allowed origins and wildcarded subdomains and then all the e2e tests.I opened https://github.com/kubernetes/ingress-nginx/pull/10490 that may fix the issue with multiple allowed origins. Please have a look. Thank you @michaelliau for the heads-up!
I’m having the same, or similar issue. Let me demonstrate what I get in the /etc/nginx/nginx.conf in the controller pod in response to various annotations:
Case 1: All origins, no credentials.
This works.
Case 2: All origins, with credentials
This does not work, because of line
set $http_origin *;
. This discards theOrigin
value set in the browser and uses the literal “*”, which is only supported whenAccess-Control-Allow-Credentials
isfalse
. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin#directives .Case 3: Specific origin, with credentials
This does not work, because the
$cors
variable is never set, only read. This must surely be a bug!Case 4: Specific origin, without credentials
Same issue as case 3 above.
I came across this issue while I was battling with CORS deployed in ingress-nginx because a web server I deployed did not ship it in its configuration, so I wanted to add it in nginx instead.
I was confused when I did not get the expected CORS behaviour when enabling cors and setting the expected allowed-origin(s) when testing with cURL:
Setting the allowed origins to
*
made it work (as reported here as well). However, when I read the generated config posted here https://github.com/kubernetes/ingress-nginx/issues/8469#issuecomment-1194784059, I see that the first line requires the request to contain theOrigin
header to match the query and therefore respond appropriately. I added this in my cURL request and voilá, the CORS headers I expected:Not sure if this is the case for anyone here, but in case it is, I thought I’d share. 😃
Annotations for this ingress:
I’m experiencing the same behavior. For OPTIONS requests coming from origins which do not match the allowed-origins configured through
nginx.ingress.kubernetes.io/cors-allow-origin
, there are no returned CORS headers. This is resulting in browsers thinking CORS is disabled.I believe the issue is with how
nginx.conf
is being generated. Here’s what I get generated forcors-allow-origin=https://*.mydomain.com
:The issue is that there’s no handling for non-allowed-origin matching OPTIONS requests. I see the OPTIONS requests from non-allowed origins falling through to my API servers, resulting in 404s because OPTIONS is not supported at that layer. The generated configuration needs to handle these requests and return a valid value for
Access-Control-Allow-Origin
. I believe the issue was introduced when support for multiple allowed origins was added. Maybe @larivierec has some insight here.