Hello,
I am not sure if it is a bug, but still I can't https redirect naked domain to www subdomain using from-to-www-redirect annotation. I did lot of tests checking the ingress-controller logs and resulted Nginx config, and I will show you what is going on. AFAIK I need one server block for naked domain and one for www subdomain in order to handle SSL handshake.
// Not what I want because would redirect to naked but attempted anyway
// Not what I want because would redirect to naked but attempted anyway
So the next question is, what am I doing wrong and how people normally do HTTPS to HTTPS redirection?! I can't be the first person to came across this.
To be able to redirect HTTPS to HTTPS the secret defined in the ingress must contain a CN for both hosts, otherwise, you will see something like this in the log:
W0607 14:28:14.027827 8 nginx.go:1208] the server www.foo.192.168.1.193.xip.io has SSL configured but the SSL certificate does not contains a CN for foo.192.168.1.193.xip.io. Redirects will not work for HTTPS to HTTPS
You can test this with the next script
#!/bin/bash
# kind
cat <<EOF | kind create cluster --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 80
hostPort: 80
protocol: TCP
- containerPort: 443
hostPort: 443
protocol: TCP
EOF
# ingress controller
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/kind/deploy.yaml
# dashboard
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/docs/examples/http-svc.yaml
# change the IP address
export MY_IP=192.168.1.193
# create a SSL cert
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
-keyout foo.key -out foo.crt \
-subj "/C=US/ST=CA/O=MyOrg, Inc./CN=$MY_IP.xip.io" \
-addext "subjectAltName=DNS:www.foo.$MY_IP.xip.io,DNS:foo.$MY_IP.xip.io,IP:$MY_IP"
kubectl create secret tls foo-xip-tls --cert=foo.crt --key=foo.key
echo "
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: http-svc
annotations:
nginx.ingress.kubernetes.io/from-to-www-redirect: 'true'
spec:
tls:
- hosts:
- $MY_IP.xip.io
- www.$MY_IP.xip.io
secretName: foo-xip-tls
rules:
- host: foo.$MY_IP.xip.io
http:
paths:
- path: /
backend:
serviceName: http-svc
servicePort: 80
" | kubectl apply -f -
curl https://www.foo.192.168.1.193.xip.io -v -k
* Trying 192.168.1.193:443...
* TCP_NODELAY set
* Connected to www.foo.192.168.1.193.xip.io (192.168.1.193) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
* subject: C=US; ST=CA; O=MyOrg, Inc.; CN=192.168.1.193.xip.io
* start date: Jun 7 14:29:10 2020 GMT
* expire date: Jun 5 14:29:10 2030 GMT
* issuer: C=US; ST=CA; O=MyOrg, Inc.; CN=192.168.1.193.xip.io
* SSL certificate verify result: self signed certificate (18), continuing anyway.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x56171b475db0)
> GET / HTTP/2
> Host: www.foo.192.168.1.193.xip.io
> user-agent: curl/7.68.0
> accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 308
< server: nginx/1.17.10
< date: Sun, 07 Jun 2020 14:33:39 GMT
< content-type: text/html
< content-length: 172
< location: https://foo.192.168.1.193.xip.io/
<
<html>
<head><title>308 Permanent Redirect</title></head>
<body>
<center><h1>308 Permanent Redirect</h1></center>
<hr><center>nginx/1.17.10</center>
</body>
</html>
* Connection #0 to host www.foo.192.168.1.193.xip.io left intact
Most helpful comment
You can test this with the next script