Description
NGINX Ingress controller version: v.0.44.0
Kubernetes version (use kubectl version
): v1.19.9-gke-1400
Environment:
- Cloud provider or hardware configuration: GKE
- Install tools: Helm v3
- Others: certificates are issued by
cert-manager
What happened:
Essentially the same issue as in #5675 except we're trying to redirect from www.
to naked domain and not the other way around. Trying to load https://www.example.com
in Chrome produces NET::ERR_CERT_AUTHORITY_INVALID
error.
In Firefox, it's MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT
and clicking Accept the Risk and Continue
proceeds to correctly follow redirects and load the site. Subsequent requests then also work fine.
What you expected to happen:
Redirect from www.
to naked domain works without errors.
How to reproduce it:
Ingress is configured in line with what was suggested by aledbf: no backend for www.
but www.
domain is included in TLS hosts. According to several threads on the topic I've perused, that approach should work.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-front
namespace: example
annotations:
cert-manager.io/cluster-issuer: letsencrypt
nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($host = example.co.uk) {
return 301 https://example.com$request_uri;
}
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
- path: /
pathType: ImplementationSpecific
backend:
service:
name: example-front
port:
number: 80
- host: example.co.uk
http:
paths:
- path: /
pathType: ImplementationSpecific
backend:
service:
name: example-front
port:
number: 80
tls:
- hosts:
- example.com
- www.example.com
- example.co.uk
- www.example.co.uk
secretName: example-front-tls
Anything else we need to know:
-
Ingress controller logs mention:
the server www.example.com has SSL configured but the SSL certificate does not contains a CN for example.com. Redirects will not work for HTTPS to HTTPS
. This is false, I've checked and the certificate does contain CN forexample.com
. -
The logs have the same warning for
https://www.example.co.uk
(we own a.co.uk
version of our domain just to rewrite it to.com
) but navigating tohttps://www.example.co.uk
works exactly as expected: there is a308
redirecting tohttps://example.co.uk
and then a301
tohttps://example.com
. Why is this not happening forhttps://www.example.com
? (Note that adding the same301
redirectif
block fromwww.example.com
toexample.com
does not fix the issue, nor should it be the solution.) -
On the first request after opening private browsing, requesting
www.example.com
orhttp://www.example.com
in Chrome or Firefox will proceed as follows:- first
308
fromwww.
to naked domain - then
308
fromhttp
tohttps
Immediately after though, requesting either of these in a new tab results in the same error again. Firefox network console shows nothing, but Chrome logs a
307
fromhttp
tohttps
and then fails on the next request which asks forhttps://www.example.com
. (Manually prefixing the URL withhttps://
always results in the error, even on the first request.) Notice how on the first attempt,www.
to naked domain happened first, and the issue did not occur. This mirrors the behaviour described in 2043, which is apparently not fixed to this date. - first
-
The issue can be bypassed by adding
www.example.com
as ahost
tospec.rules
. I don't consider this a valid configuration or a solution to this issue for several reasons:-
Documentation states:
For HTTPS to HTTPS redirects is mandatory the SSL Certificate defined in the Secret, located in the TLS section of Ingress, contains both FQDN in the common name of the certificate.
This directive is fulfilled by my configuration. There is nothing about having to add the
www.
domain as a backend. -
It defeats the point of
from-to-www-redirect
annotation -
It complicates ingress Helm templates and bloats the resulting manifest
-
It does not actually result in a redirect (it merely handles requests on
www.
as another backend), as evidenced by the following warnings in the logs:Already exists an Ingress with "www.example.com" hostname. Skipping creation of redirection from "www.example.com" to "example.com".
Already exists an Ingress with "example.com" hostname. Skipping creation of redirection from "example.com" to "www.example.com".
-
Based on these findings, it appears that there is a long-existing bug with this annotation. People are using workarounds such as a conditional rewrite
block and they really shouldn't need to. It would be really amazing to have this actually fixed and put all the relevant discussions to rest once and for all.
I've also noticed that the annotation documentation claims:
If at some point a new Ingress is created with a host equal to one of the options (like
domain.com
) the annotation will be omitted.
How exactly will it be "omitted"? My cluster does have other Ingress objects with example.com
as a host (without www.
or from-to-www-redirect
on them) but the generated nginx.conf
still has redirect blocks for example.com
location so it does not look like anything was "omitted":
set_by_lua_block $redirect_to {
local request_uri = ngx.var.request_uri
if string.sub(request_uri, -1) == "/" then
request_uri = string.sub(request_uri, 1, -2)
end
return string.format("%s://%s%s", ngx.var.scheme, "example.com", request_uri)
}
return 308 $redirect_to;