Configuring SSL with Cert Manager and Let’s Encrypt

Configuring SSL with Cert Manager and Let’s Encrypt
Photo by Rubén García / Unsplash

Most modern web applications use a Secure Sockets Layer (SSL) for establishing an encrypted link between a server and a client. What is more, in particular cases SSL can be enforced. This mechanism is known as HTTP Strict Transport Security (HSTS). A very good example of such enforcement is the entire .dev top-level domain. It is incorporated on the HSTS preload list, requiring HTTPS on all .dev domains without individual HSTS enlistment. As a matter of fact, my domain belongs to .dev top-level domain as well.

In order to enable HTTPS (SSL/TLS) for websites, we have to obtain a digital certificate. For that purpose, we can use Let's Encrypt.

Let's Encrypt

Let’s Encrypt is a free, automated, and open certificate authority (CA), run for the public’s benefit. It is a service provided by the Internet Security Research Group (ISRG).

The key principles behind Let’s Encrypt are:

  • Free: Anyone who owns a domain name can use Let’s Encrypt to obtain a trusted certificate at zero cost.
  • Automatic: Software running on a web server can interact with Let’s Encrypt to painlessly obtain a certificate, securely configure it for use, and automatically take care of renewal.
  • Secure: Let’s Encrypt will serve as a platform for advancing TLS security best practices, both on the CA side and by helping site operators properly secure their servers.
  • Transparent: All certificates issued or revoked will be publicly recorded and available for anyone to inspect.
  • Open: The automatic issuance and renewal protocol is published as an open standard that others can adopt.
  • Cooperative: Much like the underlying Internet protocols themselves, Let’s Encrypt is a joint effort to benefit the community, beyond the control of any one organization.
Let’s Encrypt
Let’s Encrypt is a free, automated, and open certificate authority brought to you by the nonprofit Internet Security Research Group (ISRG).

For automated Let's Encrypt certificate obtaining and renewal we can use Cert Manager.

Installing Cert Manager

cert-manager is a powerful and extensible X.509 certificate controller for Kubernetes and OpenShift workloads. It will obtain certificates from a variety of Issuers, both popular public Issuers as well as private ones, ensure the certificates are valid and up-to-date, and will attempt to renew certificates at a configured time before expiry.

Key features:

  • Automated issuance and renewal of certificates to secure Ingress with TLS.
  • Fully integrated Issuers from recognized public and private Certificate Authorities.
  • Secure pod-to-pod communication with mTLS using private PKI Issuers.
  • Supports certificate use cases for web-facing and internal workloads.
  • Open source add-ons for enhanced cloud-native service mesh security.
  • Backed by major cloud service providers and distributions.

The most convenient way of installing cert-manager into the Kubernetes cluster is to use Helm Chart. First, we have to add a new repository.

❯ helm repo add jetstack https://charts.jetstack.io
"jetstack" has been added to your repositories

Once the repository has been added we are ready to install cert-manager.

❯ helm upgrade --install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --version v1.7.3 \
  --set installCRDs=true

When the installation finishes, 3 new Pods will be created.

❯ kubectl get pods
NAME                                      READY   STATUS    RESTARTS   AGE
cert-manager-5f9d99bd9-z92p8              1/1     Running   0          51d
cert-manager-cainjector-f6b49bddd-b48w9   1/1     Running   0          51d
cert-manager-webhook-58b5f99b69-wst8t     1/1     Running   0          51d

At this point, we are almost ready to request a certificate. But before going further make sure that you have a working Ingress controller.

NGINX as Ingress controller
After we install applications into the cluster we usually want some of them to be seen outside of the cluster. For that purpose, Kubernetes provides a concept of Service and gives us control over how Service is published using different Service types. In a previous post, I have shown what

Requesting a certificate

To request a certificate, we need to add Certificate Authority (CA), and we will use Let's Encrypt for that.

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
  namespace: cert-manager
spec:
  acme:
    email: blog@slys.dev
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-prod-secret
    solvers:
    - http01:
        ingress:
          class: nginx

After a while Cluster Issuer will become ready.

❯ kubectl get clusterissuers.cert-manager.io
NAME                      READY   AGE
letsencrypt-prod          True    87d

Setting up SSL is as simple as adding a few annotations to an Ingress resource and TLS section.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    kubernetes.io/tls-acme: "true"
    nginx.ingress.kubernetes.io/permanent-redirect: https://blog.slys.dev
  name: ghost-slys-dev
  namespace: ghost
spec:
  ingressClassName: nginx
  rules:
  - host: slys.dev
    http:
      paths:
      - backend:
          service:
            name: ghost
            port:
              name: https
        path: /
        pathType: ImplementationSpecific
  tls:
  - hosts:
    - slys.dev
    secretName: slys.dev-tls

So we added cluster-issuer that references to letsencrypt-prod. We also added a tls-acme annotation and a tls section. After a while, the cert-manager should obtain from CA a certificate for us.

❯ kubectl get certificates.cert-manager.io
NAME                         READY   SECRET                       AGE
slys.dev-tls                 True    slys.dev-tls                 87d

Here we can find the issued certificate as well as the name of the secret that holds the certificate. Now we can enjoy using an encrypted link between a server and a client.

Conclusion

Setting up TLS/SSL encryption using Cert Manager and Let's Encrypt is a really pleasant and easy task. It requires creating Issuer and adding a few annotations to an Ingress resource, but the rest happens automagically. 😂