diff --git a/README.md b/README.md index 79c2f78f6..7b58a0090 100644 --- a/README.md +++ b/README.md @@ -245,6 +245,7 @@ The following parameters are supported: ||[`https-to-http-port`](#https-to-http-port)|port number|0 (do not listen)| |`[0]`|[`load-server-state`](#load-server-state) (experimental)|[true\|false]|`false`| ||[`max-connections`](#max-connections)|number|`2000`| +|`[1]`|[`no-tls-redirect-locations`](#no-tls-redirect-locations)|comma-separated list of url|`/.well-known/acme-challenge`| ||[`proxy-body-size`](#proxy-body-size)|number of bytes|unlimited| ||[`ssl-ciphers`](#ssl-ciphers)|colon-separated list|[link to code](https://github.com/jcmoraisjr/haproxy-ingress/blob/v0.4/pkg/controller/config.go#L35)| ||[`ssl-dh-default-max-size`](#ssl-dh-default-max-size)|number|`1024`| @@ -406,6 +407,14 @@ Defaults to `2000` connections, which is also the HAProxy default configuration. http://cbonte.github.io/haproxy-dconv/1.8/configuration.html#3.2-maxconn +### no-tls-redirect-locations + +Define a comma-separated list of URLs that should be removed from the TLS redirect. +Requests to `:80` http port and starting with one of the URLs from the list will +not be redirected to https despite of the TLS redirect configuration. + +This option defaults to `/.well-known/acme-challenge`, used by ACME protocol. + ### proxy-body-size Define the maximum number of bytes HAProxy will allow on the body of requests. Default is diff --git a/pkg/controller/config.go b/pkg/controller/config.go index fb45513dd..5274b06c7 100644 --- a/pkg/controller/config.go +++ b/pkg/controller/config.go @@ -51,9 +51,11 @@ type haConfig struct { } func newControllerConfig(ingressConfig *ingress.Configuration, haproxyController *HAProxyController) (*types.ControllerConfig, error) { - cfg := &haConfig{} - cfg.ingress = ingressConfig - cfg.haproxyController = haproxyController + cfg := &haConfig{ + ingress: ingressConfig, + haproxyController: haproxyController, + haproxyConfig: newHAProxyConfig(haproxyController), + } cfg.createUserlists() cfg.createHAProxyServers() err := cfg.createDefaultCert() @@ -69,7 +71,7 @@ func newControllerConfig(ingressConfig *ingress.Configuration, haproxyController TCPEndpoints: cfg.ingress.TCPEndpoints, UDPEndpoints: cfg.ingress.UDPEndpoints, PassthroughBackends: cfg.ingress.PassthroughBackends, - Cfg: newHAProxyConfig(haproxyController), + Cfg: cfg.haproxyConfig, }, nil } @@ -105,6 +107,7 @@ func newHAProxyConfig(haproxyController *HAProxyController) *types.HAProxyConfig BackendCheckInterval: "2s", Forwardfor: "add", MaxConn: 2000, + NoTLSRedirect: "/.well-known/acme-challenge", SSLHeadersPrefix: "X-SSL", HealthzPort: 10253, HTTPStoHTTPPort: 0, @@ -172,7 +175,7 @@ func (cfg *haConfig) createHAProxyServers() { continue } haLocations, haRootLocation := cfg.newHAProxyLocations(server) - sslRedirect := serverSSLRedirect(server) + sslRedirect := serverSSLRedirect(haLocations) isDefaultServer := server.Hostname == "_" isCACert := server.CertificateAuth.AuthSSLCert.CAFileName != "" haServer := types.HAProxyServer{ @@ -246,6 +249,7 @@ func (cfg *haConfig) newHAProxyLocations(server *ingress.Server) ([]*types.HAPro HSTS: location.HSTS, Rewrite: location.Rewrite, Redirect: location.Redirect, + SSLRedirect: location.Rewrite.SSLRedirect && cfg.allowRedirect(location.Path), Proxy: location.Proxy, RateLimit: location.RateLimit, } @@ -278,6 +282,15 @@ func (cfg *haConfig) newHAProxyLocations(server *ingress.Server) ([]*types.HAPro return haLocations, haRootLocation } +func (cfg *haConfig) allowRedirect(path string) bool { + for _, restrictPath := range strings.Split(cfg.haproxyConfig.NoTLSRedirect, ",") { + if restrictPath != "" && strings.HasPrefix(path, restrictPath) { + return false + } + } + return true +} + func labelizeHostname(hostname string) string { if hostname == "_" { return "default-backend" @@ -389,9 +402,9 @@ func readUsers(fileName string, listName string) ([]types.AuthUser, error) { // serverSSLRedirect Configure a global (per hostname) ssl redirect only if // all locations also configure ssl redirect. -func serverSSLRedirect(server *ingress.Server) bool { - for _, location := range server.Locations { - if !location.Rewrite.SSLRedirect { +func serverSSLRedirect(locations []*types.HAProxyLocation) bool { + for _, location := range locations { + if !location.SSLRedirect { return false } } diff --git a/pkg/types/types.go b/pkg/types/types.go index 3337e53d9..839d18340 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -64,6 +64,7 @@ type ( BackendCheckInterval string `json:"backend-check-interval"` Forwardfor string `json:"forwardfor"` MaxConn int `json:"max-connections"` + NoTLSRedirect string `json:"no-tls-redirect-locations"` SSLHeadersPrefix string `json:"ssl-headers-prefix"` HealthzPort int `json:"healthz-port"` HTTPStoHTTPPort int `json:"https-to-http-port"` @@ -136,6 +137,7 @@ type ( Userlist Userlist `json:"userlist,omitempty"` Proxy proxy.Configuration `json:"proxy,omitempty"` RateLimit ratelimit.RateLimit `json:"rateLimit,omitempty"` + SSLRedirect bool `json:"sslRedirect,omitempty"` HAMatchPath string `json:"haMatchPath"` HAMatchTxnPath string `json:"haMatchTxnPath"` HAWhitelist string `json:"whitelist,omitempty"` diff --git a/rootfs/etc/haproxy/template/haproxy.tmpl b/rootfs/etc/haproxy/template/haproxy.tmpl index 3ea45486c..4c4879b3a 100644 --- a/rootfs/etc/haproxy/template/haproxy.tmpl +++ b/rootfs/etc/haproxy/template/haproxy.tmpl @@ -345,7 +345,7 @@ frontend httpfront-{{ if $isShared }}shared-frontend{{ else if $isDefault }}defa redirect scheme https if !from-https {{ $server.ACLLabel }} {{- else }} {{- range $location := $server.Locations }} -{{- if $location.Rewrite.SSLRedirect }} +{{- if $location.SSLRedirect }} redirect scheme https if !from-https {{ $server.ACLLabel }}{{ $location.HAMatchTxnPath }} {{- end }} {{- end }}