I am unable to get the TLS termination at nginx ingress controller working on my kubernetes cluster.
my ingress rule looks as the following :
Christophers-MacBook-Pro-2:acme-microservice cjaime$ kubectl describe ing myapp-ingress-1
Name: myapp-ingress-1
Namespace: default
Address:
Default backend: default-http-backend:80 (<none>)
TLS:
acme-io terminates myapp-default.acme.io
Rules:
Host Path Backends
---- ---- --------
myapp-default.acme.io
/ myapp:80 (<none>)
Annotations:
ingress.kubernetes.io/ssl-redirect: true
kubernetes.io/ingress.class: nginx
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal UPDATE 53m (x2 over 1h) nginx-ingress-controller Ingress default/myapp-ingress-1
Normal UPDATE 53m (x2 over 1h) nginx-ingress-controller Ingress default/myapp-ingress-1
Normal UPDATE 53m (x2 over 1h) nginx-ingress-controller Ingress default/myapp-ingress-1
Normal UPDATE 53m (x2 over 1h) nginx-ingress-controller Ingress default/myapp-ingress-1
Whenever I try to access this from the browser I get the back the following server certificate
Server certificate
subject=/O=Acme Co/CN=Kubernetes Ingress Controller Fake Certificate
issuer=/O=Acme Co/CN=Kubernetes Ingress Controller Fake Certificate
This is preventing me from creating a valid SSL connection. I know my secret is correct because when using openssl I get a valid connection as follows
openssl s_client -servername myapp-default.acme.io -connect us1a-k8s-4.acme.io:31443 -showcerts
CONNECTED(00000003)
<content omitted>
Start Time: 1528241749
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
However If I run the same command with the servername omitted I get the same fake certificate and a connection error
openssl s_client -connect us1a-k8s-4.acme.io:31443 -showcerts
CONNECTED(00000003)
depth=0 O = Acme Co, CN = Kubernetes Ingress Controller Fake Certificate
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 O = Acme Co, CN = Kubernetes Ingress Controller Fake Certificate
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
0 s:/O=Acme Co/CN=Kubernetes Ingress Controller Fake Certificate
i:/O=Acme Co/CN=Kubernetes Ingress Controller Fake Certificate
<content omitted>
Start Time: 1528241957
Timeout : 300 (sec)
Verify return code: 21 (unable to verify the first certificate)
It works as below now :
Prior to termination of SSL at the ingress controller, the successful http request from browser was to the ingress controller with a host header set :
Chrome Browser
http://us1a-k8s-4.acme.io:31443/index.html
Host : myapp-default.acme.io
*us1a-k8s-4.acme.io is the node where nginx ingress controller
lives.*
After updating the ingress definition to use a cert, we got this to work
curl --resolve myapp-default.acme.io:31443:172.31.0.18 https://myapp-
default.acme.io:31443/index.html
*where 172.31.0.18 would be the IP for us1a-k8s-4.acme.io*
but from browser, using a host header the way we were using it before for the http request didn't work.
however when we made an entry as below to /etc/hosts file
172.31.0.18 myapp-default.acme.io
and hit the below url via browser :
http://myapp-default.acme.io:31443/index.html
IT WORKED!
Seems like the host header is not known to nginx, and it uses the URL to look up the correct certificate.
Check this https://www.claudiokuenzler.com/blog/693/curious-case-of-curl-ssl-tls-sni-http-host-header
Your tests with openssl are executed correctly and they show that nginx does offer the valid certificate for myapp-default.acme.io when that hostname is provided in the request via SNI. This is in harmony with what you configured in the Ingress.
For other hostnames or requests without a hostname the default certificate is sent. That certificate is to be stored in a Secret and configured via a command line parameter to the ingress controller (--default-ssl-certificate=$(POD_NAMESPACE)/tls-ingress
).
Your browser warning was either because of a mismatch in the hostname or a cached fake certificate in your browser. I suggest you look up how flush the certificate cache in your b browser and/or redo the test with curl:
curl -v https://myapp-default.acme.io
If it still does not work correctly, you may be affected by #1954 - update nginx-ingress-controller.