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

Feature Request: multi-origin support for cors-allow-origin #5496

Closed
matthewhartstonge opened this issue May 3, 2020 · 42 comments
Closed

Feature Request: multi-origin support for cors-allow-origin #5496

matthewhartstonge opened this issue May 3, 2020 · 42 comments
Assignees
Labels
help wanted Denotes an issue that needs help from a contributor. Must meet "help wanted" guidelines. kind/feature Categorizes issue or PR as related to a new feature.

Comments

@matthewhartstonge
Copy link

matthewhartstonge commented May 3, 2020

Feature Request

In a world of a single API used by multiple SPAs .... 🌏
It would be really helpful to be able to specify a list of origins/domains/subdomains in the nginx.ingress.kubernetes.io/cors-allow-origin annotation. Especially for subdomains serving media: media1.site.com, media2.site.com, media3.site.com

Intriguingly, this case was put forward in the initial feature request, but looks like it got reduced to an MVP of a single domain? But since the initial merge the thread has continued with many code blocks of how-to config snippet hacks to enable the support of multiple domain handling. This of course gets very messy - especially when having to apply to each microservice's ingress definition.

Linked Issues

Initial Feature Request: #1171

Prior Art?

/kind feature

@matthewhartstonge matthewhartstonge added the kind/feature Categorizes issue or PR as related to a new feature. label May 3, 2020
@matthewhartstonge matthewhartstonge changed the title Feature Request: Feature Request: multi-origin support for cors-allow-origin May 3, 2020
@pauln
Copy link

pauln commented May 3, 2020

As it currently stands, if you attempt to specify a comma-separated list of allowed origins in the nginx.ingress.kubernetes.io/cors-allow-origin annotation, it won't validate and will therefore fall back to the default of *.

This may give the false impression that the list is actually being obeyed, since all listed origins will work... but so will all other origins, since it's ending up as Access-Control-Allow-Origin: *.

@bhvishal9
Copy link

Having this feature would be great, we are also struggling to do it. As a workaround, we are using configuration snippet with custom nginx config which is working but still an ugly solution.

@jroper
Copy link

jroper commented Jul 23, 2020

Here's my ugly configuration snippet to work around:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: foo
  annotations:
    kubernetes.io/ingress.class: "nginx"
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      if ($http_origin ~* "^https?://((?:www\.exactmatch\.com)|(?:.*\.regexmatch\.com))$") {
        set $cors "true";
      }
      if ($request_method = 'OPTIONS') {
        set $cors "${cors}options";
      }

      if ($cors = "true") {
        add_header 'Access-Control-Allow-Origin' "$http_origin" always;
        add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, DELETE, PATCH, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization' always;
        add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
      }

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

@ivoribeiro
Copy link

Here's my ugly configuration snippet to work around:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: foo
  annotations:
    kubernetes.io/ingress.class: "nginx"
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      if ($http_origin ~* "^https?://((?:www\.exactmatch\.com)|(?:.*\.regexmatch\.com))$") {
        set $cors "true";
      }
      if ($request_method = 'OPTIONS') {
        set $cors "${cors}options";
      }

      if ($cors = "true") {
        add_header 'Access-Control-Allow-Origin' "$http_origin" always;
        add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, DELETE, PATCH, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization' always;
        add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
      }

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

What is the expected behavior in this case if the $http_origin is not on whitelist ?

@jroper
Copy link

jroper commented Aug 31, 2020

No headers added, which means no CORS policy so all CORS requests blocked by the browser.

@kamelotnsk
Copy link

kamelotnsk commented Sep 29, 2020

Hi all
Here's my configuration snippet to don't work, where is the problem?

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
    nginx.ingress.kubernetes.io/enable-access-log: "true"
    nginx.ingress.kubernetes.io/enable-rewrite-log: "true"
    nginx.ingress.kubernetes.io/proxy-body-size: 100m
    ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      if ($http_origin ~* "^https?://((?:ui|uia)\.stand01\.example\.com)$") {
        set $cors "true";
      }
      if ($cors = "true") {
        add_header 'Access-Control-Allow-Origin' "$http_origin";
        add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, DELETE, PATCH, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
        add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
      }
  name: ui-https-cors-ing
spec:
  tls:
  - hosts: 
    - ui.stand01.example.com
    secretName: stand01-06-example-com-crt-fullchain
  rules:
  - host: ui.stand01.example.com
    http:
      paths:
      - backend:
          serviceName: ui-svc
          servicePort: 8080
        path: /

@jfbrennan
Copy link

jfbrennan commented Oct 22, 2020

This would be really good!
Currently blocked and having to look into writing a snippet 👎

Support for wildcard subdomains would be really nice:

nginx.ingress.kubernetes.io/cors-allow-origin: "https://*.domain.com"

because "https://app1.domain.com", "https://app2.domain.com", "https://app3.domain.com" all needing to call "https://api.domain.com" is a common need.

@shubhrajoy2109
Copy link

shubhrajoy2109 commented Nov 2, 2020

Hello Guys,
I am facing Multiple "Access control allow origin" issue while I am using the below mentioned configuration snippet in k8s annotations: -

annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($http_origin ~* ((https?://(.+.)*(domain1|domain2).(?:net|com)$)) {
set $cors "true";
}

  # Determine the HTTP request method used
  if ($request_method = 'OPTIONS') {
      set $cors "${cors}options";
  }

  if ($request_method = 'GET') {
      set $cors "${cors}get";
  }

  if ($request_method = 'POST') {
      set $cors "${cors}post";
  }

  if ($cors = "true") {
      # Catch all incase there's a request method we're not dealing with properly
      add_header 'Access-Control-Allow-Origin' "$http_origin";
  }
  if ($cors = "trueget") {
      add_header 'Access-Control-Allow-Origin' "$http_origin";
      add_header 'Access-Control-Allow-Credentials' 'true';
      add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
      add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
  }
  if ($cors = "trueoptions") {
      add_header 'Access-Control-Allow-Origin' "$http_origin";
      #
      # Om nom nom cookies
      #
      add_header 'Access-Control-Allow-Credentials' 'true';
      add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
      #
      # Custom headers and headers various browsers *should* be OK with but aren't
      #
      add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
      #
      # Tell client that this pre-flight info is valid for 20 days
      #
      add_header 'Access-Control-Max-Age' 1728000;
      add_header 'Content-Type' 'text/plain charset=UTF-8';
      add_header 'Content-Length' 0;
      return 204;
  }
  if ($cors = "truepost") {
      add_header 'Access-Control-Allow-Origin' "$http_origin";
      add_header 'Access-Control-Allow-Credentials' 'true';
      add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
      add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
  }

Please find the attached error: -
image

Please suggest where am I doing wrong.

@jony89
Copy link

jony89 commented Jan 20, 2021

The problem with the workaround:

nginx.ingress.kubernetes.io/configuration-snippet: |
   add_header 'Access-Control-Allow-Origin' "$http_origin";
   .....

is that in case the pod is down for some reason, these headers will not be included and the request will be blocked instead of getting 503. so you must add always see #6782

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

@hipages-leimiao
Copy link

hipages-leimiao commented Mar 3, 2021

What is the expected behavior in this case if the $http_origin is not on whitelist ?

This is a case:
https://stackoverflow.com/questions/19743396/cors-cannot-use-wildcard-in-access-control-allow-origin-when-credentials-flag-i

@matteocusinato
Copy link

Hi, any news for CORS support for wildcard subdomains?

@tokers
Copy link
Contributor

tokers commented May 12, 2021

CORS support for wildcard subdomains

Welcome to submit a new issue to track it.

@jfbrennan
Copy link

jfbrennan commented May 13, 2021

CORS support for wildcard subdomains

Welcome to submit a new issue to track it.

@tokers this is the issue "Feature Request: multi-origin support for cors-allow-origin". The op suggested comma-separated list, I suggested wildcard subdomains, or maybe both? I don't think any of us really care that much about those differences we just want a simple way to get multi-origin support w/o writing snippets.

@tokers
Copy link
Contributor

tokers commented May 14, 2021

CORS support for wildcard subdomains

Welcome to submit a new issue to track it.

Ignore this message, I'm not sorry that I misunderstood some stuff there.

@tokers
Copy link
Contributor

tokers commented May 14, 2021

Extend the cors-allow-origin to be a comma-separated string so that multiple origins can be supported is a good point, I will look through the current code base and judge whether this is feasible, if so, I will submit a PR to support it, or, I will explain the reason here.

@tokers
Copy link
Contributor

tokers commented May 14, 2021

/assign

@tokers
Copy link
Contributor

tokers commented May 14, 2021

See #7134 for details :)

@iamNoah1
Copy link
Contributor

iamNoah1 commented Aug 3, 2021

@matthewhartstonge @tokers can we consider to close this one?

@matthewhartstonge
Copy link
Author

@tokers
Copy link
Contributor

tokers commented Aug 4, 2021

@matthewhartstonge @tokers can we consider to close this one?

PR was reverted as the implementation is not right 😂

@jfbrennan
Copy link

@tokers It has to resolve to a single origin or *. What we're asking for is some magic that does this resolution for us either from a csv or regex.

@constb
Copy link

constb commented Aug 13, 2021

I think this needs to change:

corsOriginRegex = regexp.MustCompile(`^(https?://[A-Za-z0-9\-\.]*(:[0-9]+)?|\*)?$`)

@gtskaushik
Copy link

This is a much needed implementation

@iamNoah1
Copy link
Contributor

iamNoah1 commented Aug 17, 2021

@tokers @matthewhartstonge @jfbrennan @constb @gtskaushik we accept and are happy for any contributions.

@arvtiwar
Copy link

arvtiwar commented Sep 5, 2021

Yep, we are also looking for this capability.

@arvtiwar
Copy link

arvtiwar commented Sep 5, 2021

Hi Guys, please suggest how to achieve this use case. We have Cloudflare, which proxies all the requests to our backend based on K8S Nginx ingress. We need to support multiple subdomains (subd01.mydomain.com, subd02.mydomain.com, .....) for our clients, and all should hit the same API backend (api.mydomain.com).
Any workaround/idea how to address it? Thanks in advance

@iamNoah1
Copy link
Contributor

iamNoah1 commented Sep 8, 2021

/help

@k8s-ci-robot
Copy link
Contributor

@iamNoah1:
This request has been marked as needing help from a contributor.

Please ensure the request meets the requirements listed here.

If this request no longer meets these requirements, the label can be removed
by commenting with the /remove-help command.

In response to this:

/help

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 the help wanted Denotes an issue that needs help from a contributor. Must meet "help wanted" guidelines. label Sep 8, 2021
@larivierec
Copy link
Contributor

larivierec commented Sep 9, 2021

I have no idea if this is a good way to do it but it works. Let me know if there is something that can be done better.

#7614

@arvtiwar
Copy link

arvtiwar commented Sep 9, 2021

IMHO, below are the two solutions wd be perfect

  1. there has to be a way to enforce user-defined policy (e.g. nginx.ingress.kubernetes.io/cors-allow-origin-policy: "user-defined regex") to match "http_origin"
  2. User should list all the subdomains (foo.bar.com, foo1.bar.com, yar.bar.com, bkar.foo.bar.com ......) in NginX ConfigMap for ingress to exact match.

@AlbertMarashi
Copy link

Any news?

@jfbrennan
Copy link

@arvtiwar there are enterprises where that list would be HUGE. Being able to * is really important and it looks like the PR supports that

k8s-ci-robot pushed a commit that referenced this issue Nov 2, 2021
* Add Initial support for multiple cors origins in nginx

- bump cluster version for `make dev-env`
- add buildOriginRegex function in nginx.tmpl
- add e2e 4 e2e tests for cors.go
- refers to feature request #5496

* add tests + use search to identify '*' origin

* add tests + use search to identify '*' origin

Signed-off-by: Christopher Larivière <[email protected]>

* fix "should enable cors test" looking at improper values

* Modify tests and add some logic for origin validation

- add origin validation in cors ingress annotations
- add extra tests to validate regex
- properly escape regex using "QuoteMeta"
- fix some copy/paste errors

* add TrimSpace and length validation before adding a new origin

* modify documentation for cors and remove dangling comment

* add support for optional port mapping on origin

* support single-level wildcard subdomains + tests

* Remove automatic `*` fonctionality from incorrect origins

- use []string instead of basic string to avoid reparsing in template.go
- fix typo in docs
- modify template to properly enable only if the whole block is enabled
- modify cors parsing
- test properly by validating that the value returned is the proper
  origin
- update unit tests and annotation tests

* Re-add `*` when no cors origins are supplied + fix tests

- fix e2e tests to allow for `*`
- re-add `*` to cors parsing if trimmed cors-allow-origin is empty
(supplied but empty) and if it wasn't supplied at all.

* remove unecessary logic for building cors origin + remove comments

- add some edge cases in e2e tests
- rework logic for building cors origin

there was no need for logic in template.go for buildCorsOriginRegex
if there is a `*` it ill be short-circuited by first if.

if it's a wildcard domain or any domain (without a wildcard), it MUST
match the main/cors.go regex format.

if there's a star in a wildcard domain, it must be replaced with
`[A-Za-z0-9]+`

* add missing check in e2e tests
@larivierec
Copy link
Contributor

merged, but build isn't ready yet.

@larivierec
Copy link
Contributor

/assign

@villesau
Copy link

@larivierec just stumbled upon this issue. Any timeline for the release? :)

@larivierec
Copy link
Contributor

larivierec commented Nov 10, 2021

you'll have to wait for the official release from the maintainer @rikatz
it should be soon

Update: I'll close once version is released

@k8s-ci-robot
Copy link
Contributor

@larivierec: You can't close an active issue/PR unless you authored it or you are a collaborator.

In response to this:

/close

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.

@rikatz
Copy link
Contributor

rikatz commented Nov 16, 2021

/close
Thanks :)

@k8s-ci-robot
Copy link
Contributor

@rikatz: Closing this issue.

In response to this:

/close
Thanks :)

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.

@patsevanton
Copy link

Please share code with multi-origin support for cors-allow-origin

@kszafran
Copy link
Contributor

kszafran commented Sep 30, 2022

Please share code with multi-origin support for cors-allow-origin

You can now specify multiple, comma-separated domains in cors-allow-origin, e.g.:

nginx.ingress.kubernetes.io/cors-allow-origin: "https://example.com, https://another.com, http://localhost:8000"

rchshld pushed a commit to joomcode/ingress-nginx that referenced this issue May 19, 2023
* Add Initial support for multiple cors origins in nginx

- bump cluster version for `make dev-env`
- add buildOriginRegex function in nginx.tmpl
- add e2e 4 e2e tests for cors.go
- refers to feature request kubernetes#5496

* add tests + use search to identify '*' origin

* add tests + use search to identify '*' origin

Signed-off-by: Christopher Larivière <[email protected]>

* fix "should enable cors test" looking at improper values

* Modify tests and add some logic for origin validation

- add origin validation in cors ingress annotations
- add extra tests to validate regex
- properly escape regex using "QuoteMeta"
- fix some copy/paste errors

* add TrimSpace and length validation before adding a new origin

* modify documentation for cors and remove dangling comment

* add support for optional port mapping on origin

* support single-level wildcard subdomains + tests

* Remove automatic `*` fonctionality from incorrect origins

- use []string instead of basic string to avoid reparsing in template.go
- fix typo in docs
- modify template to properly enable only if the whole block is enabled
- modify cors parsing
- test properly by validating that the value returned is the proper
  origin
- update unit tests and annotation tests

* Re-add `*` when no cors origins are supplied + fix tests

- fix e2e tests to allow for `*`
- re-add `*` to cors parsing if trimmed cors-allow-origin is empty
(supplied but empty) and if it wasn't supplied at all.

* remove unecessary logic for building cors origin + remove comments

- add some edge cases in e2e tests
- rework logic for building cors origin

there was no need for logic in template.go for buildCorsOriginRegex
if there is a `*` it ill be short-circuited by first if.

if it's a wildcard domain or any domain (without a wildcard), it MUST
match the main/cors.go regex format.

if there's a star in a wildcard domain, it must be replaced with
`[A-Za-z0-9]+`

* add missing check in e2e tests
@xtianus79
Copy link

thanks this feature worked great!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Denotes an issue that needs help from a contributor. Must meet "help wanted" guidelines. kind/feature Categorizes issue or PR as related to a new feature.
Projects
None yet
Development

No branches or pull requests