ingress-nginx
ingress-nginx copied to clipboard
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 versionkubectl 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 ingressclassesName: 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:Controller: k8s.io/ingress-nginx Events:
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: ""
@cbanek: 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.
/remove-kind bug
Is it possible to reproduce this on a kind or a Minikube cluster. If yes, can you write a step-by-step guide so that someone can copy/paste and reproduce on a kind or a Minikube cluster.
I'm experiencing an issue where I set nginx.ingress.kubernetes.io/cors-allow-origin: "https://www.example.com" but in the response headers I see access-control-allow-origin: https://subdomain.example.com when requesting from https://subdomain.example.com. So effectively nginx.ingress.kubernetes.io/cors-allow-origin seems to be still *.
@cbanek Can you please share the exact command that you are using to make the request to the ingress and see the response headers?
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 for cors-allow-origin=https://*.mydomain.com:
if ($http_origin ~* ((https://[A-Za-z0-9\-]+\.mydomain\.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: accept,allow,x-my-custom-header';
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: accept,allow,x-my-custom-header';
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;
}
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.
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.
Isn't this intended behavior?
You issue an OPTIONS request from origins which are not in the list of allowed origins, therefore you shouldn't receive CORS headers?
I'm experiencing an issue where I set
nginx.ingress.kubernetes.io/cors-allow-origin: "https://www.example.com"but in the response headers I seeaccess-control-allow-origin: https://subdomain.example.comwhen requesting fromhttps://subdomain.example.com. So effectivelynginx.ingress.kubernetes.io/cors-allow-originseems to be still*.
I do find that this is weird however. In this example I would've expected a failure.
I'd have to look it up, it's been awhile :sweat:
Also, have you looked at the e2e tests for examples, I wrote a lot of e2e tests when I wrote the default cors for ingress-nginx. Perhaps I have missed of few edge cases? -> CORS e2e tests
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 to Origin to indicate to browsers that the response can change based on the Origin 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 for Access-Control-Allow-Origin. I think it's unclear how a browser might choose to handle such a response. Maybe a nginx.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 the Vary 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 a falseoptions branch that can handle multiple allowed origins and wildcarded subdomains and then all the e2e tests.
/kind bug
Following up here to see if any additional information is required for triage. I've added the bug label to this issue as the code path for handling CORS requests from non-allowed origins does not exist (and was removed in https://github.com/kubernetes/ingress-nginx/pull/7614). This seems like a vulnerability in the current implementation where requests from undesirable origins, that should be handled at ingress by nginx, are being forwarded.
I will try to take a look at this when I have time Until then feel free to comment :)
Hi
I'm experiencing exactly the same problem. I deploy following ingress (anonymized):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: internal
meta.helm.sh/release-name: api
meta.helm.sh/release-namespace: namespace
nginx.ingress.kubernetes.io/cors-allow-origin: https://www.somehost.com
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/rewrite-target: /api/$2
creationTimestamp: "2022-06-22T13:29:09Z"
generation: 1
labels:
app: api
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: api
helm.sh/chart: mychart-2.2.0
name: ingress-api
namespace: namespace
spec:
rules:
- host: www.somehost.com
http:
paths:
- backend:
service:
name: api-service
port:
name: http
path: /api/([vV][1-9]/)?(.*)
pathType: ImplementationSpecific
tls:
- hosts:
- www.somehost.com
and I get no CORS headers when calling it.
The value of the "nginx.ingress.kubernetes.io/cors-allow-origin" could be a single value, multiple values, hosts with wildcard (e.g. https://*.somehost.com) or full host names - it does not work in those scenarios.
The only scenario that I get CORS headers back is when either:
- the annotation is missing
- the annotation has the value "*" - exactly as types - in quotes.
Of course in all scenarios "nginx.ingress.kubernetes.io/enable-cors" is set to "true".
Used Nginx container: k8s.gcr.io/ingress-nginx/controller:v1.2.0
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:
❯ curl -i -XOPTIONS https://qa.example.org/api
HTTP/2 405
date: Tue, 09 Aug 2022 11:39:25 GMT
content-length: 0
allow: GET
x-api-version: foo-service
x-response-time-ms: 0
strict-transport-security: max-age=15724800; includeSubDomains
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 the Origin header to match the query and therefore respond appropriately. I added this in my cURL request and voilá, the CORS headers I expected:
❯ curl -i -XOPTIONS -H "Origin: https://qa.example.org" https://qa.example.org/api
HTTP/2 204
date: Tue, 09 Aug 2022 11:39:35 GMT
strict-transport-security: max-age=15724800; includeSubDomains
access-control-allow-origin: https://qa.example.org
access-control-allow-credentials: true
access-control-allow-methods: GET, PUT, POST, DELETE, PATCH, 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-expose-headers: x-api-version,x-response-time-ms
access-control-max-age: 1728000
Not sure if this is the case for anyone here, but in case it is, I thought I'd share. :)
Annotations for this ingress:
{
"kubernetes.io/ingress.class": "nginx",
"nginx.ingress.kubernetes.io/cors-allow-credentials": "true",
"nginx.ingress.kubernetes.io/cors-allow-origin": "https://qa.example.org,https://subdomain.qa.example.org",
"nginx.ingress.kubernetes.io/cors-expose-headers": "x-api-version,x-response-time-ms",
"nginx.ingress.kubernetes.io/enable-cors": "true",
"nginx.ingress.kubernetes.io/service-upstream": "true"
}
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?
The Kubernetes project currently lacks enough contributors to adequately respond to all issues and PRs.
This bot triages issues and PRs according to the following rules:
- After 90d of inactivity,
lifecycle/staleis applied - After 30d of inactivity since
lifecycle/stalewas applied,lifecycle/rottenis applied - After 30d of inactivity since
lifecycle/rottenwas applied, the issue is closed
You can:
- Mark this issue or PR as fresh with
/remove-lifecycle stale - Mark this issue or PR as rotten with
/lifecycle rotten - Close this issue or PR with
/close - Offer to help out with Issue Triage
Please send feedback to sig-contributor-experience at kubernetes/community.
/lifecycle stale
After I put the default values append my custom configs into annotations, my ingress works good. The key configs as below:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: cncf
namespace: default
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
more_set_headers "Access-Control-Allow-Origin: $http_origin";
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-Project-Key"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "GET, PUT, POST, DELETE, PATCH, OPTIONS"
# nginx.ingress.kubernetes.io/cors-allow-origin: "*"
nginx.ingress.kubernetes.io/cors-expose-headers: "*, X-Project-Key"
nginx.ingress.kubernetes.io/cors-max-age: "1728000"
nginx.ingress.kubernetes.io/enable-cors: "true"
spec:
ingressClassName: nginx
rules:
# ...... The other configs...
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.
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, PATCH, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-origin: "*"
nginx.ingress.kubernetes.io/cors-allow-credentials: "false"
set $http_origin *;
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-Methods: PUT, GET, POST, 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-Methods: PUT, GET, POST, 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;
}
Case 2: All origins, with credentials
This does not work, because of line set $http_origin *;. This discards the Origin value set in the browser and uses the literal "*", which is only supported when Access-Control-Allow-Credentials is false. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin#directives .
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, PATCH, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-origin: "*"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
set $http_origin *;
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: PUT, GET, POST, 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: PUT, GET, POST, 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;
}
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!
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, PATCH, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-origin: {{ .Values.global.domain }}
nginx.ingress.kubernetes.io/cors-allow-credentials: "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: PUT, GET, POST, 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: PUT, GET, POST, 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;
}
Case 4: Specific origin, without credentials
Same issue as case 3 above.
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, PATCH, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-origin: {{ .Values.global.domain }}
nginx.ingress.kubernetes.io/cors-allow-credentials: "false"
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-Methods: PUT, GET, POST, 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-Methods: PUT, GET, POST, 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;
}
The code that generates all of this is here: https://github.com/kubernetes/ingress-nginx/blob/3916f7b8b72ce5da7e3ba2377adfb1d06d4bcae8/internal/ingress/controller/template/template.go#L1789
@rudolfbyker case3 & case4 are a cause of concern.
- There has been at least 1 change to harden the use of CORS in the past year
- Could you kindly write a step-by-step doc that someone can copy/paste from to reproduce on a minikube or a kind cluster. I think its important that we clarify the status in clear unambiguous data
- The project is in a stabilization phase but close to completing the stabilization work. So if this is a bug, then it will be taken up after ending the stabilization work that is in progress now
- In case this is an issue and in case a PR comes in from community, it will be appreciated and reviewed sooner
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:
nginx.ingress.kubernetes.io/server-snippet: |
add_header Access-Control-Allow-Origin "https://*.example.com";
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
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!
/remove-lifecycle stale
I had a similar issue and fixed it by removing all cors headers from the upstream server. As cors headers from upstream are not removed automatically when enabling cors in nginx-ingress.
nginx-ingress config:
hide-headers: "Server,X-Powered-By,Access-Control-Allow-Origin,Access-Control-Allow-Credentials,Access-Control-Allow-Methods,Access-Control-Allow-Headers,Access-Control-Max-Age"
After this, cors managed by nginx-ingress worked as expected.