<p>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.</p>
<p>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.</p>
<p>I am hoping someone with experience with this kind of setup can provide some guidance.</p>
<p>Thanks!</p>

<p>First, mTLS and TLS/SSL termination are not exactly the same thing. mTLS is <a href="https://en.wikipedia.org/wiki/Mutual_authentication" rel="noreferrer">mutual authentication</a> 🤝 meaning the client authenticates the server and the server authenticates the client.</p>
<p>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.</p>
<p>Also, the <a href="https://en.wikipedia.org/wiki/Certificate_authority" rel="noreferrer">Certificate Authority</a> and what I believe you are referring to as <a href="https://cert-manager.io/docs/" rel="noreferrer">certificate manager</a> are 2 different things.</p>
<p>For Kubernetes, you can set up <a href="https://kubernetes.io/docs/concepts/services-networking/ingress/#tls" rel="noreferrer">TLS/SSL termination on an Ingress</a> using an <a href="https://kubernetes.github.io/ingress-nginx/examples/tls-termination/" rel="noreferrer">ingress controller like Nginx</a>. You can <a href="https://stackoverflow.com/questions/10175812/how-to-create-a-self-signed-certificate-with-openssl">totally use a self-signed certificate with your own Certificate Authority with this</a>. 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.</p>
<p>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:</p>
<pre class="lang-yaml prettyprint-override"><code>nginx.ingress.kubernetes.io/auth-tls-verify-client: &quot;on&quot;
nginx.ingress.kubernetes.io/auth-tls-secret: &quot;default/mycerts&quot;
</code></pre>
<p>You would create the above secret in K8s with something like this:</p>
<pre class="lang-sh prettyprint-override"><code>kubectl create secret generic mycerts --from-file=tls.crt=server.crt --from-file=tls.key=server.key --from-file=ca.crt=ca.crt
</code></pre>
<p>Some more details in this <a href="https://medium.com/@awkwardferny/configuring-certificate-based-mutual-authentication-with-kubernetes-ingress-nginx-20e7e38fdfca" rel="noreferrer">blog</a>.</p>
<p>Note: Service meshes like <a href="https://istio.io/latest/docs/tasks/security/authentication/authn-policy/" rel="noreferrer">Istio</a>, <a href="https://linkerd.io/2/features/automatic-mtls/" rel="noreferrer">Linkerd</a>, and <a href="https://www.consul.io/docs/connect/connect-internals" rel="noreferrer">Consul</a> support mTLS out the box between your services.</p>
<p>✌️</p>
