diff --git a/pkg/provider/kubernetes/ingress-nginx/kubernetes.go b/pkg/provider/kubernetes/ingress-nginx/kubernetes.go index 7946c9b5f..1eb184ee8 100644 --- a/pkg/provider/kubernetes/ingress-nginx/kubernetes.go +++ b/pkg/provider/kubernetes/ingress-nginx/kubernetes.go @@ -942,39 +942,50 @@ func applySSLRedirectConfiguration(routerName string, ingressConfig ingressConfi sslRedirect := ptr.Deref(ingressConfig.SSLRedirect, hasTLS) - if !forceSSLRedirect && !sslRedirect { - if hasTLS { - httpRouter := &dynamic.Router{ - Rule: rt.Rule, - // "default" stands for the default rule syntax in Traefik v3, i.e. the v3 syntax. - RuleSyntax: "default", - Middlewares: rt.Middlewares, - Service: rt.Service, - } + if hasTLS { + // An Ingress with TLS configuration creates only a Traefik router with a TLS configuration, + // so no Non-TLS router exists to handle HTTP traffic, and we should create it. + httpRouter := &dynamic.Router{ + Rule: rt.Rule, + // "default" stands for the default rule syntax in Traefik v3, i.e. the v3 syntax. + RuleSyntax: "default", + Middlewares: rt.Middlewares, + Service: rt.Service, + } + conf.HTTP.Routers[routerName+"-http"] = httpRouter - conf.HTTP.Routers[routerName+"-http"] = httpRouter + // If either forceSSLRedirect or sslRedirect are enabled, + // the HTTP router needs to redirect to HTTPS. + if forceSSLRedirect || sslRedirect { + redirectMiddlewareName := routerName + "-redirect-scheme" + conf.HTTP.Middlewares[redirectMiddlewareName] = &dynamic.Middleware{ + RedirectScheme: &dynamic.RedirectScheme{ + Scheme: "https", + ForcePermanentRedirect: true, + }, + } + httpRouter.Middlewares = []string{redirectMiddlewareName} + httpRouter.Service = "noop@internal" } return } - redirectRouter := &dynamic.Router{ - Rule: rt.Rule, - // "default" stands for the default rule syntax in Traefik v3, i.e. the v3 syntax. - RuleSyntax: "default", - Service: "noop@internal", + // An Ingress with no TLS configuration and forceSSLRedirect annotation should always redirect on HTTPS, + // even if no route exists for HTTPS. + if forceSSLRedirect { + redirectMiddlewareName := routerName + "-redirect-scheme" + conf.HTTP.Middlewares[redirectMiddlewareName] = &dynamic.Middleware{ + RedirectScheme: &dynamic.RedirectScheme{ + Scheme: "https", + ForcePermanentRedirect: true, + }, + } + rt.Middlewares = append([]string{redirectMiddlewareName}, rt.Middlewares...) } - redirectMiddlewareName := routerName + "-redirect-scheme" - conf.HTTP.Middlewares[redirectMiddlewareName] = &dynamic.Middleware{ - RedirectScheme: &dynamic.RedirectScheme{ - Scheme: "https", - ForcePermanentRedirect: true, - }, - } - redirectRouter.Middlewares = append(redirectRouter.Middlewares, redirectMiddlewareName) - - conf.HTTP.Routers[routerName+"-redirect"] = redirectRouter + // An Ingress that is not forcing sslRedirect and has no TLS configuration does not redirect, + // even if sslRedirect is enabled. } func applyForwardAuthConfiguration(routerName string, ingressConfig ingressConfig, rt *dynamic.Router, conf *dynamic.Configuration) error { diff --git a/pkg/provider/kubernetes/ingress-nginx/kubernetes_test.go b/pkg/provider/kubernetes/ingress-nginx/kubernetes_test.go index df325c8a2..86df0e777 100644 --- a/pkg/provider/kubernetes/ingress-nginx/kubernetes_test.go +++ b/pkg/provider/kubernetes/ingress-nginx/kubernetes_test.go @@ -175,7 +175,7 @@ func TestLoadIngresses(t *testing.T) { TLS: &dynamic.RouterTLSConfig{}, Service: "default-ingress-with-ssl-redirect-whoami-80", }, - "default-ingress-with-ssl-redirect-rule-0-path-0-redirect": { + "default-ingress-with-ssl-redirect-rule-0-path-0-http": { Rule: "Host(`sslredirect.localhost`) && Path(`/`)", RuleSyntax: "default", Middlewares: []string{"default-ingress-with-ssl-redirect-rule-0-path-0-redirect-scheme"}, @@ -193,15 +193,10 @@ func TestLoadIngresses(t *testing.T) { Service: "default-ingress-without-ssl-redirect-whoami-80", }, "default-ingress-with-force-ssl-redirect-rule-0-path-0": { - Rule: "Host(`forcesslredirect.localhost`) && Path(`/`)", - RuleSyntax: "default", - Service: "default-ingress-with-force-ssl-redirect-whoami-80", - }, - "default-ingress-with-force-ssl-redirect-rule-0-path-0-redirect": { Rule: "Host(`forcesslredirect.localhost`) && Path(`/`)", RuleSyntax: "default", Middlewares: []string{"default-ingress-with-force-ssl-redirect-rule-0-path-0-redirect-scheme"}, - Service: "noop@internal", + Service: "default-ingress-with-force-ssl-redirect-whoami-80", }, }, Middlewares: map[string]*dynamic.Middleware{