diff --git a/nginx-controller/nginx/configurator.go b/nginx-controller/nginx/configurator.go index 3279c90614..9db225f72f 100644 --- a/nginx-controller/nginx/configurator.go +++ b/nginx-controller/nginx/configurator.go @@ -29,6 +29,7 @@ func NewConfigurator(nginx *NginxController, config *Config) *Configurator { return &cnf } +// AddOrUpdateDHParam - @TODO func (cnf *Configurator) AddOrUpdateDHParam(content string) (string, error) { return cnf.nginx.AddOrUpdateDHParam(content) } @@ -87,6 +88,8 @@ func (cnf *Configurator) generateNginxCfg(ingEx *IngressEx, pems map[string]stri wsServices := getWebsocketServices(ingEx) rewrites := getRewrites(ingEx) sslServices := getSSLServices(ingEx) + corsEnabled := getCorsEnabled(ingEx) + corsDomains := getCorsDomains(ingEx) if ingEx.Ingress.Spec.Backend != nil { name := getNameForUpstream(ingEx.Ingress, emptyHost, ingEx.Ingress.Spec.Backend.ServiceName) @@ -122,6 +125,8 @@ func (cnf *Configurator) generateNginxCfg(ingEx *IngressEx, pems map[string]stri ProxyHideHeaders: ingCfg.ProxyHideHeaders, ProxyPassHeaders: ingCfg.ProxyPassHeaders, ServerSnippets: ingCfg.ServerSnippets, + CorsEnabled: corsEnabled, + CorsDomains: corsDomains, } if pemFile, ok := pems[serverName]; ok { @@ -175,6 +180,8 @@ func (cnf *Configurator) generateNginxCfg(ingEx *IngressEx, pems map[string]stri ProxyHideHeaders: ingCfg.ProxyHideHeaders, ProxyPassHeaders: ingCfg.ProxyPassHeaders, ServerSnippets: ingCfg.ServerSnippets, + CorsEnabled: corsEnabled, + CorsDomains: corsDomains, } if pemFile, ok := pems[emptyHost]; ok { @@ -322,6 +329,29 @@ func getWebsocketServices(ingEx *IngressEx) map[string]bool { return wsServices } +func getCorsEnabled(ingEx *IngressEx) bool { + cors := false + + // If cors is enabled + if _, exists := ingEx.Ingress.Annotations["nginx.org/enable-cors"]; exists { + cors = true + } + return cors +} + +func getCorsDomains(ingEx *IngressEx) string { + // Default to all Origins + corsDomains := "*" + + // Whitelist certain domains + if domains, exists := ingEx.Ingress.Annotations["nginx.org/cors-domains"]; exists { + parsed := strings.Replace(domains, ",", "|", -1) + corsDomains = parsed + } + + return corsDomains +} + func getRewrites(ingEx *IngressEx) map[string]string { rewrites := make(map[string]string) diff --git a/nginx-controller/nginx/ingress.tmpl b/nginx-controller/nginx/ingress.tmpl index 84de46208c..fae74c12e3 100644 --- a/nginx-controller/nginx/ingress.tmpl +++ b/nginx-controller/nginx/ingress.tmpl @@ -45,6 +45,26 @@ server { {{$value}}{{end}} {{- end}} + {{- if $server.CorsEnabled}} + set $cors "false"; + + {{- if eq $server.CorsDomains "*"}} + set $cors "true"; + {{- else}} + if ($http_origin ~* (https?:\/\/([a-zA-Z0-9]*\.)?({{$server.CorsDomains}})(:[0-9]+)?)) { + set $cors "true"; + } + {{- end}} + + set $corsmethod "${cors}nonoptions"; + + if ($request_method = 'OPTIONS') { + set $corsmethod "${cors}options"; + } + {{- end}} + + + {{range $location := $server.Locations}} location {{$location.Path}} { proxy_http_version 1.1; @@ -53,11 +73,33 @@ server { proxy_set_header Connection $connection_upgrade; {{end}} + {{- if $location.LocationSnippets}} {{range $value := $location.LocationSnippets}} {{$value}}{{end}} {{- end}} + {{if $server.CorsEnabled}} + if ($corsmethod = "truenonoptions") { + add_header 'Access-Control-Allow-Origin' "$http_origin" always; + add_header 'Access-Control-Allow-Credentials' 'true' always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, PATCH, PUT, DELETE, OPTIONS' always; + add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since'; + add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range'; + } + + if ($corsmethod = "trueoptions") { + add_header 'Access-Control-Allow-Origin' "$http_origin"; + add_header 'Access-Control-Allow-Credentials' 'true'; + add_header 'Access-Control-Max-Age' 1728000; + add_header 'Access-Control-Allow-Methods' 'GET, POST, PATCH, PUT, DELETE, OPTIONS'; + add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since'; + add_header 'Content-Length' 0; + add_header 'Content-Type' 'text/plain charset=UTF-8'; + return 204; + } + {{end}} + proxy_connect_timeout {{$location.ProxyConnectTimeout}}; proxy_read_timeout {{$location.ProxyReadTimeout}}; client_max_body_size {{$location.ClientMaxBodySize}}; diff --git a/nginx-controller/nginx/nginx.go b/nginx-controller/nginx/nginx.go index 57f5e28d74..eb231d4180 100644 --- a/nginx-controller/nginx/nginx.go +++ b/nginx-controller/nginx/nginx.go @@ -55,6 +55,8 @@ type Server struct { HSTSIncludeSubdomains bool ProxyHideHeaders []string ProxyPassHeaders []string + CorsEnabled bool + CorsDomains string // http://nginx.org/en/docs/http/ngx_http_realip_module.html RealIPHeader string