mTLS setup using self-signed cert in Kubernetes and NGINX

7/22/2020

I have a Kubernetes cluster (AKS) that is hosting a REST echo service. The service runs fine via HTTP. I am using NGINX ingress to route traffic. I now want to set up this service via HTTPS and with mTLS, so forcing the client to specify a certificate to be able to communicate with the echo service. This is a POC, so I am using a self-signed cert.

What Kubernetes components do I need to set up to be able to pull this off? I read NGINX documentation but wasn't able to understand if I need to create a Certificate Authority/Cert-manager in the Kubernetes cluster and use that to configure an ingress service to perform the mTLS step. I am OK with terminating the SSL at ingress (after mTLS has been performed) and allow an unsecured channel from ingress to the echo-service.

I am hoping someone with experience with this kind of setup can provide some guidance.

Thanks!

-- wntrsux
kubernetes
mtls
nginx
nginx-ingress
ssl

1 Answer

7/22/2020

First, mTLS and TLS/SSL termination are not exactly the same thing. mTLS is mutual authentication 🤝 meaning the client authenticates the server and the server authenticates the client.

Typically the SSL termination takes care of the server authenticating the client but it takes client support for the server to be able to authenticate the client.

Also, the Certificate Authority and what I believe you are referring to as certificate manager are 2 different things.

For Kubernetes, you can set up TLS/SSL termination on an Ingress using an ingress controller like Nginx. You can totally use a self-signed certificate with your own Certificate Authority with this. The only thing is that your requests will not be verified but your client/browser unless the CA (Certificate Authority) is added as a trusted entity.

Now with respect to mTLS you don't necessarily care if you use exactly the same CA, Cert, and Key to authenticate both ways. However, you would have to force your ingress to authenticate the client and with the Nginx ingress controller you can do it with these annotations:

nginx.ingress.kubernetes.io/auth-tls-verify-client: "on"
nginx.ingress.kubernetes.io/auth-tls-secret: "default/mycerts"

You would create the above secret in K8s with something like this:

kubectl create secret generic mycerts --from-file=tls.crt=server.crt --from-file=tls.key=server.key --from-file=ca.crt=ca.crt

Some more details in this blog.

Note: Service meshes like Istio, Linkerd, and Consul support mTLS out the box between your services.

✌️

-- Rico
Source: StackOverflow