Skip to content

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

Notifications You must be signed in to change notification settings

aerOS-Project/aerOS-Domain-TLS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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

TLS

High-Level Overview

  • 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.

Pre-Requirements

  • A record DNS name
  • Ports open: 80 for HTTP and 443 for HTTPS
  • Helm v3.12.1 or above
  • Nginx Ingress controller
  • Cert-Manager

Deployment

Install Helm if it's not already installed in your Kubernetes cluster: Helm Installation Guide

Nginx Ingress Controller:

helm upgrade --install ingress-nginx ingress-nginx \
  --repo https://kubernetes.github.io/ingress-nginx \
  --namespace ingress-nginx --create-namespace

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

After deploying the Nginx Ingress controller, it automatically receives an external IP address because its service is configured as a LoadBalancer by default. If the cluster uses MetalLB for its bare metal infrastructure, MetalLB assigns an external IP from its pool. Alternatively, in cloud-based environments, the external IP is provided by the cloud provider's load-balancing service. This external IP, allocated to the Ingress controller, becomes the destination for all incoming traffic, directing it to the appropriate services within the cluster.

kubectl get svc -n ingress-nginx

Output:

NAME                                 TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   10.96.56.90    10.220.2.210    80:31578/TCP,443:31600/TCP   20h 

Implementation

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

kuard

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

get-ing

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

cert

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

secret

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

References

About

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

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published