diff --git a/docs/user-guide/configmap.md b/docs/user-guide/configmap.md index e4930400b..4e50fc228 100644 --- a/docs/user-guide/configmap.md +++ b/docs/user-guide/configmap.md @@ -133,6 +133,7 @@ The following table shows a configuration option's name, type, and the default v |[http-redirect-code](#http-redirect-code)|int|308| |[proxy-buffering](#proxy-buffering)|string|"off"| |[limit-req-status-code](#limit-req-status-code)|int|503| +|[no-tls-redirect-locations](#no-tls-redirect-locations)|string|"/.well-known/acme-challenge"| ## add-headers @@ -731,3 +732,8 @@ Enables or disables [buffering of responses from the proxied server](http://ngin ## limit-req-status-code Sets the [status code to return in response to rejected requests](http://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req_status).Default: 503 + +## no-tls-redirect-locations + +A comma-separated list of locations on which http requests will never get redirected to their https counterpart. +Default: "/.well-known/acme-challenge" diff --git a/internal/ingress/controller/config/config.go b/internal/ingress/controller/config/config.go index 6baa1b1fc..0be277a54 100644 --- a/internal/ingress/controller/config/config.go +++ b/internal/ingress/controller/config/config.go @@ -490,6 +490,10 @@ type Configuration struct { SyslogHost string `json:"syslog-host"` // SyslogPort port SyslogPort int `json:"syslog-port",omitempty` + + // NoTLSRedirectLocations is a comma-separated list of locations + // that should not get redirected to TLS + NoTLSRedirectLocations string `json:"no-tls-redirect-locations"` } // NewDefault returns the default nginx configuration @@ -587,6 +591,7 @@ func NewDefault() Configuration { JaegerSamplerParam: "1", LimitReqStatusCode: 503, SyslogPort: 514, + NoTLSRedirectLocations: "/.well-known/acme-challenge", } if glog.V(5) { diff --git a/internal/ingress/controller/template/template.go b/internal/ingress/controller/template/template.go index efea1bec7..5fd486a00 100644 --- a/internal/ingress/controller/template/template.go +++ b/internal/ingress/controller/template/template.go @@ -129,6 +129,7 @@ var ( "buildRateLimit": buildRateLimit, "buildResolvers": buildResolvers, "buildUpstreamName": buildUpstreamName, + "isLocationInLocationList": isLocationInLocationList, "isLocationAllowed": isLocationAllowed, "buildLogFormatUpstream": buildLogFormatUpstream, "buildDenyVariable": buildDenyVariable, @@ -513,6 +514,28 @@ func buildRateLimit(input interface{}) []string { return limits } +func isLocationInLocationList(location interface{}, rawLocationList string) bool { + loc, ok := location.(*ingress.Location) + if !ok { + glog.Errorf("expected an '*ingress.Location' type but %T was returned", location) + return false + } + + locationList := strings.Split(rawLocationList, ",") + + for _, locationListItem := range locationList { + locationListItem = strings.Trim(locationListItem, " ") + if locationListItem == "" { + continue + } + if strings.HasPrefix(loc.Path, locationListItem) { + return true + } + } + + return false +} + func isLocationAllowed(input interface{}) bool { loc, ok := input.(*ingress.Location) if !ok { diff --git a/internal/ingress/controller/template/template_test.go b/internal/ingress/controller/template/template_test.go index f430144fd..8f76be975 100644 --- a/internal/ingress/controller/template/template_test.go +++ b/internal/ingress/controller/template/template_test.go @@ -645,3 +645,26 @@ func TestBuildAuthSignURL(t *testing.T) { } } } + +func TestIsLocationInLocationList(t *testing.T) { + + testCases := []struct { + location *ingress.Location + rawLocationList string + expected bool + }{ + {&ingress.Location{Path: "/match"}, "/match", true}, + {&ingress.Location{Path: "/match"}, ",/match", true}, + {&ingress.Location{Path: "/match"}, "/dontmatch", false}, + {&ingress.Location{Path: "/match"}, ",/dontmatch", false}, + {&ingress.Location{Path: "/match"}, "/dontmatch,/match", true}, + {&ingress.Location{Path: "/match"}, "/dontmatch,/dontmatcheither", false}, + } + + for _, testCase := range testCases { + result := isLocationInLocationList(testCase.location, testCase.rawLocationList) + if result != testCase.expected { + t.Errorf(" expected %v but return %v, path: '%s', rawLocation: '%s'", testCase.expected, result, testCase.location.Path, testCase.rawLocationList) + } + } +} diff --git a/rootfs/etc/nginx/template/nginx.tmpl b/rootfs/etc/nginx/template/nginx.tmpl index 8f6010c47..46cf10c13 100644 --- a/rootfs/etc/nginx/template/nginx.tmpl +++ b/rootfs/etc/nginx/template/nginx.tmpl @@ -137,7 +137,7 @@ http { {{ if $cfg.EnableOpentracing }} opentracing on; {{ end }} - + {{ buildOpentracing $cfg }} include /etc/nginx/mime.types; @@ -779,6 +779,7 @@ stream { {{/* redirect to HTTPS can be achieved forcing the redirect or having a SSL Certificate configured for the server */}} {{ if (or $location.Rewrite.ForceSSLRedirect (and (not (empty $server.SSLCertificate)) $location.Rewrite.SSLRedirect)) }} + {{ if not (isLocationInLocationList $location $all.Cfg.NoTLSRedirectLocations) }} # enforce ssl on server side if ($redirect_to_https) { {{ if $location.UsePortInRedirects }} @@ -792,6 +793,7 @@ stream { {{ end }} } {{ end }} + {{ end }} {{ if $all.Cfg.EnableModsecurity }} modsecurity on;