Securing aerOS Domain with TLS Using Cert-Manager and Let’s Encrypt

Introduction

aerOS provisions access to (each) domain APIs over a secure and private channel. Encrypted communication among aerOS domains or access from third party clients to aerOS APIs are foreseen. TLS (Transport Layer Security) is the standard protocol for securing these communications and aerOS leverages Cert-Manager (supporting Let’s Encrypt or self-signed certificates) to manage and automate the TLS certificate issuance.

aerOS integrates Cert-Manager and foresees certificate issuance and management either using Let’s Encrypt, which is a widely trusted Certificate Authority (CA), when a public IP and a FQDN are available or self-signed method when aerOS domains are framed in private networks and not interfacing the outer world.

This guide provides a comprehensive walkthrough on deploying Cert-Manager on aerOS, K8s based cluster, domain, configuring it to work with Let’s Encrypt, and automating the issuance and renewal of TLS certificates. This ensures that all external traffic to aerOS domain is encrypted, maintaining the confidentiality and integrity of data transmitted between clients and services.

TLS

Features

  • Request Certificate: When the Ingress resource is applied and includes the appropriate annotations for Cert-Manager, Cert-Manager notices the request for a certificate and creates a Certificate resource in Kubernetes to manage it.

  • ACME Protocol: Cert-Manager then uses the ACME (Automated Certificate Management Environment) protocol to communicate with Let’s Encrypt, requesting a certificate for the specified domain name.

  • Domain Validation: Let’s Encrypt requires proof that you control the domain for which you’re requesting a certificate. Cert-Manager automates this by creating a temporary Pod or configuring the Ingress (via a challenge, such as HTTP-01) to prove ownership of the domain to Let’s Encrypt.

  • Certificate Issuance: Once domain validation is successful, Let’s Encrypt issues the certificate to Cert-Manager, which then stores it in a Kubernetes Secret.

  • Certificate Injection: The Nginx Ingress controller is configured to use this Secret for TLS termination, meaning it decrypts incoming HTTPS traffic and forwards it to the appropriate backend service as HTTP.

Place in architecture

In a Kubernetes-based architecture, securing the communication channels is crucial. The integration of Cert-Manager and Let’s Encrypt within the aerOS domain plays a pivotal role in achieving this. Here’s how these components fit into the overall architecture:

  1. Ingress Controller: - Role: Acts as the entry point for all external HTTP/HTTPS traffic, directing it to the appropriate services within the Kubernetes cluster. - Integration: The Ingress Controller, such as Nginx, is configured to use TLS certificates managed by Cert-Manager for secure communication.

  2. Cert-Manager: - Role: Automates the process of acquiring, renewing, and managing TLS certificates within the Kubernetes cluster. - Integration: Cert-Manager requests certificates from Let’s Encrypt and stores them as Kubernetes Secrets, which are then used by the Ingress Controller to terminate TLS connections.

  3. Let’s Encrypt: - Role: Provides a trusted Certificate Authority (CA) for issuing free SSL/TLS certificates. - Integration: Cert-Manager uses the ACME (Automated Certificate Management Environment) protocol to communicate with Let’s Encrypt for certificate issuance and renewal.

  4. Kubernetes Secrets: - Role: Securely store the issued TLS certificates and keys. - Integration: These secrets are referenced by the Ingress Controller to handle secure HTTPS connections.

  5. KrakenD API Gateway (if used): - Role: Acts as a gateway that handles API requests, providing features such as rate limiting, request transformation, and more. - Integration: The Ingress Controller routes traffic to KrakenD, which then directs it to the appropriate backend services. KrakenD can also be configured to support TLS, ensuring secure API communications.

By integrating these components, the architecture ensures that all external traffic entering the Kubernetes cluster is securely encrypted. This not only protects the data in transit but also builds trust with clients by providing secure and verifiable communication channels. In summary, the combination of Cert-Manager, Let’s Encrypt, Ingress Controller, and Kubernetes Secrets forms a robust system for managing TLS certificates and ensuring secure communication within the aerOS domain.

User guide

Prerequisities

  • A record DNS name

  • Ports open: 80 for HTTP and 443 for HTTPS

  • Helm v3.12.1 or above

  • Nginx Ingress controller

  • Cert-Manager

  • KrakenD (optional)

Note

The following installation prerequisites installing KrakenD in the aerOS Domain. To secure the connection without KrakenD, visit https://cert-manager.io/docs/tutorials/acme/nginx-ingress/

Installation

Cert-Manager:

helm repo add jetstack https://charts.jetstack.io --force-update
helm repo update
helm install \
  cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --version v1.14.2 \
  --set installCRDs=true

Configuration options

Step 1: Deploying a Web Server

To verify ownership with Let’s Encrypt, it’s necessary to deploy a simple Pod running a small HTTP server to respond to the HTTP-01 challenge. In the example provided, we use a demo application named kuard (Kubernetes Up and Running) to fulfill this challenge. This involves deploying both a simple Pod and a corresponding service within the cluster.

Deployment:

kubectl apply -f https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/acme/example/deployment.yaml

Service:

kubectl apply -f https://raw.githubusercontent.com/cert-manager/website/master/content/docs/tutorials/acme/example/service.yaml

Step 2: KrakenD

Let’s Encrypt issues a token to your ACME client (Cert-Manager), which then places a file containing the token and a thumbprint of your account key on your web server at http://<YOUR_DOMAIN>/.well-known/acme-challenge/<TOKEN>. After informing Let’s Encrypt that the file is in place, Let’s Encrypt attempts to retrieve it. To facilitate this retrieval, proper routing must be configured to allow Let’s Encrypt access to the web server. Routing passes through Nginx and Krakend before reaching the kuard web server. Therefore, configuring the Krakend API gateway to direct traffic to the web server is a crucial first step.

To ensure the incoming request http://<YOUR_DOMAIN>/.well-known/acme-challenge/<TOKEN> reaches the web server, add a path in Krakend as shown below.

krakend

Note

The kuard application is deployed in the default namespace http://kuard.default.svc.cluster.local. If deployed in a different namespace, adjust the FQDN accordingly, for example, http://kuard.<yournamespace>.svc.cluster.local.

Step 3: Nginx Ingress Controller

To expose the Krakend service outside of the cluster, we define a rule in the Ingress resource to route all the incoming traffic to the Krakend service.

ingress
kubectl apply -f krakend-ingress.yaml

Verify it was deployed:

kubectl get ing

Output:

NAME              CLASS   HOSTS                               ADDRESS        PORTS
krakend-ingress   nginx   ncsrd-mvp-domain.aeros-project.eu   10.220.2.210   80, 443

Step 4: Creating and Verifying the Issuer

An Issuer in Cert-Manager defines the method by which TLS certificates are requested. In Kubernetes, Issuers are scoped to a single namespace, allowing for namespace-specific certificate management. Alternatively, ClusterIssuer offers a cluster-wide solution, applicable across all namespaces.

In ncsrd Domain, we utilized an Issuer within the default namespace, as demonstrated in the example below:

issuer

Note: If opting to use a ClusterIssuer for cluster-wide certificate management, remember to annotate your Ingress resources with cert-manager.io/cluster-issuer to specify the ClusterIssuer to be used.

Creating the Issuer:

Execute the following command to apply the Issuer configuration:

kubectl apply -f issuer.yaml

Verifying the Issuer Status:

To check the status and ensure the Issuer has been correctly set up, use:

kubectl describe issuer letsencrypt-prod

Cert-Manager will interpret the annotation (cert-manager.io/issuer: "letsencrypt-prod") from the Ingress resource and proceed to create a TLS certificate accordingly. You can verify the existence and status of requested certificates by:

kubectl get certificates

Output:

NAME          READY   SECRET        AGE
ingress-tls   True    ingress-tls   73d

Important Note on Secrets:

The Kubernetes Secret used in the Ingress must match the name of the secret defined in the certificate configuration. This ensures the Ingress controller can successfully retrieve and use the certificate for TLS.

Upon successful certificate issuance, Cert-Manager creates a Secret containing the certificate details, matching the secret name specified in the Ingress resource configuration.

To view the created Secret:

kubectl get secret ingress-tls

Output:

NAME          TYPE                DATA   AGE
ingress-tls   kubernetes.io/tls   2      154d

Following the steps outlined above, your domain name is now secured with TLS. This encryption ensures that the data transmitted to and from your domain is protected. You can verify the successful implementation of TLS in two ways:

From the Terminal:

Verify the TLS setup by executing a curl command that makes a verbose request to your domain, specifically requesting to use TLS version 1.2:

curl https://your-domain.example.com --verbose --tlsv1.2 --tls-max 1.2

For example, to check the TLS configuration for the ncsrd domain ncsrd-mvp-domain.aeros-project.eu, use the following command:

curl https://ncsrd-mvp-domain.aeros-project.eu/types?details=true --verbose --tlsv1.2 --tls-max 1.2

From the Browser:

https://ncsrd-mvp-domain.aeros-project.eu/types?details=true

Developer guide

Authors

This module is developed and maintained as part of the aerOS project, aiming to enhance cybersecurity measures in IoT environments.

License

Notice (dependencies)