Automatic Certificate generation on Kubernetes with Cert-manager on OVH Cloud

Gabin Chambon
6 min readAug 31, 2020

--

Recently I had to deploy a Baremetal Kubernetes Cluster for a Client.

Since I configured a Traefik ingress for the cluster, I decided to use it’s native integration with Lets’ Encrypt certificate, by installing Cert-Manager and configure the automatic renewal of certificate.

As we will discuss in this article, configuring automatic Let’s-Encrypt certificate renewal depends on where your domain is hosted. The Domain I have been working with was hosted on OVH cloud and I didn’t find any source on the correct way to do so, I am writting this post to help any lot souls that may be in the same situation !

I will soon write a Post on how I configured the network and Traefik Ingress on a Baremetal Cluster but for now, the concept that you need to be aware of is that on a baremetal Kbernetes Cluster, you loose the ability to crate and use a LoadBalancer.

As you lose this capabilty, you have little option left to expose service in your cluster to the internet.

So, How can you manage networking in a On premise Cluster ?

You can expose endpoints using hostPort or nodePort. Since hostPort are a loophole, as much in security as in resilience, the common practice in a production context is to use Nodeport.

But using nodePort in Kuberntes as one big flaw : you can only expose port from range 30000–32767.

Using Nodeport crate other challenges, as well in term of networking management (the port range is not really common, and not really practical, you will likely have to make a port translation at some point) and in security (as a port on your cluster is open).

I give you this link that list flaws of nodePort.

But since your are on premise, you have no other choice but to use nodePort, and to enforce strong security policy on your network, host and front Load-Balancer.

Now , for the Let’s Encrypt certificate manager, if you want to generate your certificate using Let’s Encrypt (and not provide by hand certificate generated by PKI) you will have to pass challenge for Let’s encrypt to provide to certificate to you.

More info here, as this is outside the scope of this blog post:

There is two type of challenge HTTP01 and DNS01. More info of the two type of challenge here : https://letsencrypt.org/docs/challenge-types/

Since we cannot use the port 80 or 443, it is impossible for us to use the HTTP01 challenge, as, for security reasons can only use the the 80/443 port. But in a “normal” situation, using the HTTPS01 is the most straightforward and simple way to generate certificate

We are bound to use the other challenge type : DNS01.

The DNS01 challenge need to create a TXT record in the domain to verify that we own the domain we want to generate a certificate for. So, setting up a DNS01 challenge heavily depend on your setup, on where your domain is hosted.

Since the domain I had to work with was with OVH, this blog post will explain how to configure a challenge with this provider.

Here is the link listing cloud providers and how to create challenges for them:

For our scenario, here are the steps taken:

  1. Installation of Cert-manager
  2. Generation of a token that have the GET,PUT and DELETE on the domain we want to create certificate for
  3. Installation of the OVH webhook for Cert-Manager
  4. Configuration of an issuer containing the token and the domain
  5. Creation of the certificate

The procedure can vary, from domain provider to domain provider, but the step will roughly be:

  1. Géneration of a token/application access that have the right on the domain
  2. Creation of the issuer , containing the token/application access
  3. Generation of the certificate.

So, to setup Cert-manager with OVH integration, we need to install cert-manager in our cluster, and then install the OVH webhook.

Once everything is done, we can create the Issuer and the Certificate.

Installation of Cert-Manager

We will deploy Cert-Manager using the official Helm chart

Only one instance of cert-manager can run on a Kubernetes Cluster, launching more can lead to unwanted behavior.

We set the value installCRDs as true to install the Custom Ressources of Cert-Manager, so we can create certificates by calling the Kubernetes API.

#First we add the cert-manager helm repo
helm repo add jetstack https://charts.jetstack.io
helm repo update
# We create the cert-manager namespace
kubectl create namespce cert-manager
# and Then we deploy the cert-manager helm chart
helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--version v0.16 \
--set installCRDs=true

Configuration of the Cert-Manager OVH Webhook

First, huge thanks to the user baard who created this webhook. Second, clone his git repo https://github.com/baarde/cert-manager-webhook-ovh

Set the variable “group_name” as the name of the domain you want to certificate

helm install <NAME_OF_DEPLOYMENT> ./deploy/cert-manager-webhook-ovh \ --set groupName='GROUP_NAME'

Then we need to create an OVH API Key , access this URL : And create a API Access with the GET PUT POST DELETE right on the /domain/zone/<domain>/* (replace with the domain you want to validate).

Get all the info that you are given (application key , application secret and customer key)

All the ressources below are namespaced (because we are creating secrets), so, be very carefull that you are deploying the secret in the right namespace.

Next we will create the secret that will contain the application secret.

kubectl create secret generic ovh-credentials \
--from-literal=applicationSecret='<OVH_APPLICATION_SECRET>'

Don’t forget to follow the test explained in the git.

Then, you can apply the followings yaml, I commented the importants variables

First, we create the Role and Rolebinding for the cert-manager so the webhook client can see the secret:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: cert-manager-webhook-ovh:secret-reader
labels:
app.kubernetes.io/name: test-cert-manager
app.kubernetes.io/tier: backend
app.kubernetes.io/managed-by: Ops
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch","list"]
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: cert-manager-webhook-ovh:secret-reader
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: cert-manager-webhook-ovh:secret-reader
subjects:
- apiGroup: ""
kind: ServiceAccount
name: cert-manager-webhook-ovh

Then, We create the issuer (the issuer is the “user” that will create the certificate):

apiVersion: cert-manager.io/v1alpha2
kind: Issuer
metadata:
name: test-Issuer # Name of the issuer
labels:
app.kubernetes.io/name: test-issuer
app.kubernetes.io/tier: backend
app.kubernetes.io/managed-by: Ops
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory # URL of the server
email: popopame@cetacean.com #email of the user that will the notification about the cert
privateKeySecretRef:
name: letsencrypt-account-key
solvers:
- dns01:
webhook:
groupName: test.io # name of the group you setted at the start of this course
solverName: ovh
config:
endpoint: ovh-eu # Endpoint you will use , it was proved at the creation of the API
applicationKey: #application key you received
applicationSecretRef:
key: applicationSecret
name: ovh-credentials # name of the secret you created for the application secret
consumerKey: #Consumer key that was given to you at the token creation

Once this is done, we can finally create the certificate ! I commented the important variables :

apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
name: test-certificate # name of the certificate
labels:
app.kubernetes.io/name: test-certificate # name of the certificate
app.kubernetes.io/tier: backend
app.kubernetes.io/managed-by: Ops
spec:
dnsNames:
- test.domain.io # name of the domain you want to validate the certificate
issuerRef:
name: test-issuer # name of the issuer you created before
kind: Issuer
secretName: test-certificate # name of the secret that will be created that will contain the certificate

I’ll go in my next blog post on how to use the generated certificate in a Traefik ingress. But I hope that I helped you !

Godspeed !

--

--

Gabin Chambon
Gabin Chambon

Written by Gabin Chambon

Currently DevOps (working with Kubernetes/Helm, Terraform and Ansible). Learning GO and Eager to Learn Blockchain technology !

Responses (3)