Featured image of post Mutual TLS (mTLS) In a Nutshell

Mutual TLS (mTLS) In a Nutshell

How to eliminate API keys in service to service communication

1. What is Mutual TLS (mTLS)?

Mutual TLS (mTLS) is an authentication mechanism where both the client and the server verify each other’s identity using TLS certificates.

How mTLS Differs from Regular TLS

FeatureTLS (One-Way)Mutual TLS (mTLS)
AuthenticationServer onlyClient & Server
Security LevelMediumHigh
Use CaseHTTPS websitesMicroservices Security
Certificate ValidationOnly server cert checkedBoth client & server certs checked

mTLS eliminates the need for API keys and ensures secure service-to-service communication.


2. Why Use mTLS in Kubernetes?

  • πŸ” Zero Trust Security - Services must authenticate before communicating
  • πŸ›‘ Prevents Man-in-the-Middle (MITM) attacks
  • βœ… Removes reliance on shared secrets & API keys
  • πŸš€ Works seamlessly with Service Meshes (Istio, Linkerd)

Now, let’s implement mTLS inside a Kubernetes pod!


3. Setting Up Mutual TLS in Kubernetes

We’ll implement mTLS with Istio.

Step 1: Install Istio

1
2
3
4
curl -L https://istio.io/downloadIstio | sh -
cd istio-*
export PATH=$PWD/bin:$PATH
istioctl install --set profile=demo -y

Verify Istio installation:

1
kubectl get pods -n istio-system

Step 2: Enable mTLS Strict Mode

Apply a PeerAuthentication policy to enforce mTLS:

1
2
3
4
5
6
7
8
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: default
spec:
  mtls:
    mode: STRICT

Apply it:

1
kubectl apply -f mtls-policy.yaml

Now, all services in the namespace must communicate over mTLS. πŸš€

Step 3: Deploy a Sample Service with mTLS

Create a secure Nginx deployment:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
apiVersion: apps/v1
kind: Deployment
metadata:
  name: secure-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: secure-nginx
  template:
    metadata:
      labels:
        app: secure-nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest

Apply it:

1
kubectl apply -f nginx-deployment.yaml

Check if mTLS is working:

1
kubectl exec -it secure-nginx-xxx -- curl http://secure-nginx

If mTLS is enforced, requests will be blocked without certificates.


4. Implementing mTLS with Linkerd

Linkerd also supports mTLS by default.

Step 1: Install Linkerd CLI

1
2
curl -sL run.linkerd.io/install | sh
export PATH=$HOME/.linkerd2/bin:$PATH

Step 2: Deploy Linkerd in Kubernetes

1
2
linkerd install | kubectl apply -f -
linkerd check

Step 3: Inject Linkerd into Your Service

1
kubectl get deploy -o yaml | linkerd inject - | kubectl apply -f -

Now, Linkerd automatically encrypts traffic with mTLS.

Verify:

1
linkerd viz dashboard

5. Customizing mTLS Certificates

Generate Self-Signed Certificates

Use OpenSSL to create a root CA and client certificates:

1
2
3
4
5
openssl genrsa -out rootCA.key 2048
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 365 -out rootCA.crt -subj "/CN=root-ca"
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr -subj "/CN=client"
openssl x509 -req -in client.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out client.crt -days 365 -sha256

Apply Certificates in Kubernetes

Create a Secret:

1
2
3
4
5
6
7
8
apiVersion: v1
kind: Secret
metadata:
  name: mtls-secret
type: Opaque
data:
  tls.crt: $(base64 rootCA.crt)
  tls.key: $(base64 rootCA.key)

Apply it:

1
kubectl apply -f mtls-secret.yaml

6. Best Practices for mTLS Security

βœ… Rotate certificates regularly to prevent compromise
βœ… Use a Certificate Authority (CA) instead of self-signed certs
βœ… Enable strict mTLS mode to enforce encrypted communication
βœ… Monitor logs for failed authentication attempts
βœ… Integrate mTLS with a Service Mesh (Istio/Linkerd)


Key Ideas

βœ… mTLS eliminates API keys and passwords
βœ… Istio and Linkerd simplify mTLS deployment
βœ… mTLS protects against MITM attacks
βœ… Use strong certificate management practices