Securing Microservices Communication

In this tutorial, we will explore how to secure communication between microservices using TLS (Transport Layer Security) and mTLS (Mutual TLS). We will use Let’s Encrypt, a free certificate authority, to obtain and manage our TLS certificates. This guide is designed for beginners, so we will break down each concept step-by-step.

What is TLS?

TLS is a protocol that provides privacy and data integrity between two communicating applications. When you use a secure website (look for "https" in the URL), it’s likely using TLS to encrypt data transferred between your browser and the server. In microservices, TLS helps ensure that the data exchanged between services is secure and cannot be intercepted by unauthorized parties.

What is mTLS?

mTLS is an extension of TLS that adds an extra layer of security by requiring both the client and server to present certificates to authenticate each other. This is particularly useful in microservices where services need to communicate securely with one another.

What is Let's Encrypt?

https://letsencrypt.org/

Let’s Encrypt is a free, automated, and open certificate authority that provides SSL/TLS certificates. This means you can obtain certificates for your services without any cost, and it can automate the process of renewing them.

lets-encrypt

Why Secure Communication is Important

  1. Data Protection: Securing communication ensures that sensitive data (like user credentials and personal information) remains confidential.
  2. Authentication: mTLS ensures that only trusted clients can communicate with your services.
  3. Integrity: TLS helps ensure that data is not tampered with during transmission.

Setting Up the Environment

Before we dive into the implementation, you will need the following:

  1. Kubernetes Cluster: A running Kubernetes environment to deploy our microservices.
  2. Nginx: We will use Nginx as an API Gateway to manage traffic between our microservices.
  3. Cert-Manager: A Kubernetes tool to automate the management of TLS certificates.

mTLS Process

TLS Process

Request

Verify TLS/mTLS

Issue Certificate

Forward Request

Send Client Cert

Verify Client Cert

Validate with Let's Encrypt

Client

Nginx with TLS/mTLS

Cert-Manager

Let's Encrypt

Backend Service

Step 1: Install Cert-Manager

Cert-Manager helps manage certificates automatically. We can install it in our Kubernetes cluster with the following command:

kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.7.1/cert-manager.yaml

Verify that Cert-Manager is running:

kubectl get pods -n cert-manager

Step 2: Create Let's Encrypt Issuer

An Issuer in Cert-Manager tells it how to obtain certificates. Here’s how to create a Let’s Encrypt Issuer for our setup:

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: letsencrypt-prod
  namespace: default
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: your-email@example.com
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
    - http01:
        ingress:
          class: nginx
  • email: Replace your-email@example.com with your email. Let’s Encrypt uses this for notifications.
  • solvers: This section defines how Cert-Manager will solve the ACME challenge to prove control of your domain.

Apply this configuration with:

kubectl apply -f issuer.yaml

Step 3: Create a Certificate Resource

Now we will create a Certificate resource that requests a certificate from Let’s Encrypt:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: my-service-tls
  namespace: default
spec:
  secretName: my-service-tls-secret
  issuerRef:
    name: letsencrypt-prod
    kind: Issuer
  commonName: my-service.example.com
  dnsNames:
  - my-service.example.com
  • secretName: This is where the certificate and key will be stored.
  • commonName: The domain you want to secure (replace with your service domain).
  • dnsNames: List of domains covered by this certificate.

Apply the Certificate configuration:

kubectl apply -f certificate.yaml

Step 4: Configure Nginx for TLS

Next, we will configure Nginx to use the TLS certificate obtained from Let’s Encrypt. Here’s a sample Nginx configuration for our service:

server {
    listen 443 ssl;
    server_name my-service.example.com;

    ssl_certificate /etc/nginx/tls/my-service-tls-secret.crt;
    ssl_certificate_key /etc/nginx/tls/my-service-tls-secret.key;

    location / {
        proxy_pass http://my-service;
    }
}
  • ssl_certificate and ssl_certificate_key: Paths where the certificates are stored in the Nginx container.

Step 5: Implementing mTLS

To implement mTLS, both the client and server need to authenticate each other.

1. Generate Client Certificates

You need to create client certificates for mTLS. Here’s a basic example of how to do this:

openssl req -newkey rsa:2048 -nodes -keyout client.key -out client.csr
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365
  • client.key: The private key for the client.
  • client.crt: The client certificate signed by the CA.

2. Configure Nginx for mTLS

Update your Nginx configuration to enable mTLS:

server {
    listen 443 ssl;
    server_name my-service.example.com;

    ssl_certificate /etc/nginx/tls/my-service-tls-secret.crt;
    ssl_certificate_key /etc/nginx/tls/my-service-tls-secret.key;
    ssl_client_certificate /etc/nginx/tls/ca.crt;
    ssl_verify_client on;

    location / {
        proxy_pass http://my-service;
    }
}
  • ssl_client_certificate: Specifies the CA certificate for client verification.
  • ssl_verify_client on: Enables mTLS by requiring the client to provide a certificate.

Best Practices for Using Let’s Encrypt with TLS and mTLS

  1. Automatic Certificate Renewal: Set up Cert-Manager to renew your certificates automatically.
  2. Use Staging Environment for Testing: Always use the staging environment for testing configurations before deploying them in production.
  3. Store Certificates Securely: Use Kubernetes secrets to manage your certificates safely.
  4. Implement mTLS for Internal Services: Use mTLS for communication between your internal microservices to enhance security.
  5. Use Strong Encryption Protocols: Stick to TLS 1.2 or higher for secure communications.

FAQs

Q1: How does Let’s Encrypt work?

  • Let’s Encrypt provides free SSL/TLS certificates through an automated process that verifies domain ownership and issues certificates.

Q2: What is the difference between TLS and mTLS?

  • TLS encrypts communication between a client and server, while mTLS adds mutual authentication, requiring both parties to present certificates.

Q3: Can I use Let’s Encrypt in production?

  • Yes, Let’s Encrypt certificates are designed for production use, but make sure to manage certificate renewals properly.

Q4: How often do I need to renew Let’s Encrypt certificates?

  • Let’s Encrypt certificates are valid for 90 days. It is recommended to renew them every 60 days.

Q5: What is Cert-Manager and why should I use it?

  • Cert-Manager is a Kubernetes add-on that automates the management and issuance of TLS certificates from Let’s Encrypt, simplifying certificate lifecycle management.

Summary

By integrating Let’s Encrypt with TLS and mTLS, microservices can achieve secure communication. The automated nature of Let’s Encrypt and Cert-Manager simplifies the management of TLS certificates, ensuring that your services communicate securely and reliably.

Clap here if you liked the blog