Laisser un commentaire

Certbot: challenge DNS OVH & wildcard

Certbot est l’outil de l’EFF qui permet d’automatiser la génération de certificats TLS Letsencrypt. L’outil dispose de plusieurs méthodes – appellées challenges – permettant de valider que vous contrôlez bien le domaine. Cependant, seule la méthode DNS permet de générer des certificats wildcard. Voyons comment la mettre en place avec OVH.

Il existait déjà quelques plugins alternatifs permettant d’automatiser les modifications nécessaires aux DNS OVH en passant par leur API, mais c’est aujourd’hui le plugin officiel qui nous intéresse. Une fois en place, il vous permettra d’automatiquement générer et renouveller des certificats wildcard ou non, même si le DNS dudit domaine pointe pas sur un autre serveur.

Nous nous concentrons ici sur le plugin OVH, mais il en existe d’autres (CloudFlare, DigitalOcean, Linode, AWS…).

Installation des outils

Comme ces plugins nécessitent une des dernières versions de Certbot et qu’ils ne sont pas inclus par défaut, commençons par installer nos dépendances. Nous utiliserons pip afin de s’assurer d’obtenir une version récente, car les gestionaires de paquets des distributions livrent la plupart du temps des versions un peu datées…

Si vous avez déjà une version installée par votre ppa préféré et que vous souhaitez la supprimer avant d’installer la version pip, assurez-vous de faire un petit backup de /etc/letsencrypt. En effet apt purge certbot effacera ce répertoire et vos certificats avec.

# on s'assure d'avoir pip
apt install python3-pip

# puis on installe certbot et le plugin ovh
pip install certbot
pip install certbot-dns-ovh

Nous installons pip de python3. C’est en effet la version de python la plus récente et elle est installée par défaut sur la plupart des systèmes. En outre, l’installation via python2.x pose des problèmes au niveau des dépendances.

Dernier point de cette étape d’installation, la gestion des logs. Certbot log le résultat de chaque commande dans /var/log/letsencrypt. Cependant, pip ne configure aucune politique de rotation des logs. Afin que ces derniers ne s’ammassent pas indéfiniement, on va configurer logrotate pour qu’il les compresse puis qu’il les efface après 6 mois – comme un certificat a une durée de validité de 3 mois, ça semble être un bon compromis.

On place donc un nouveau fichier de config /etc/logrotate.d/certbot avec le contenu suivant :

/var/log/letsencrypt/*.log {
    monthly
    rotate 6
    compress
    delaycompress
    notifempty
    missingok
    create 640 root adm
}

Création des accès à l’API OVH

Deuxième étape, nous allons créer un accès à l’API d’OVH afin que le plugin puisse modifier des enregistrements pour vérifier que le domaine est bien à nous. Pour cela, rendez-vous sur la page de création de Token API.

Assurez-vous de bien définir le token avec une validité illimitée et renseignez les droits comme ceci :

Comme le signale Veovis dans les commentaires, ces droits sont un peu larges. Aussi, pour limiter cela à un seul domaine, vous pouvez définir les droits comme ceci :

Remplacez bien {domain.ext} par votre nom de domaine. Attention, il s’agit toujours du nom de domaine racine sans sous-domaine.

Après validation, il va falloir créer un fichier de configuration pour que Certbot puisse accéder aux identifiants de l’API. Vous pouvez enregistrer ce fichier où bon vous semble et le nommer comme il vous plaît. Pour ma part, c’est /root/.ovhapi et voici son contenu.

dns_ovh_endpoint = ovh-eu
dns_ovh_application_key = xxx
dns_ovh_application_secret = xxx
dns_ovh_consumer_key = xxx

Vous remplacez évidemment les xxx par les informations obtenues lors de la création du token. Enfin, assurez-vous de paramétrer les droits d’accès de ce fichier en 600, sans quoi Certbot émettra des warnings. chmod 600 /root/.ovhapi.

Génération des certificats

Une fois tout cela en place, nous pouvons générer nos certificats. Nous allons prendre buzut.fr en exemple, mais bien entendu, seulement les domaines gérés sur votre compte OVH pourront fonctionner.

# génération du certificat pour buzut.fr et *.buzut.fr
# ce sont deux certificats distincts mais ils seront groupés en un seul fichier
certbot certonly --dns-ovh --dns-ovh-credentials ~/.ovhapi -d buzut.fr -d *.buzut.fr

# alternativement, si on exécute les lignes de commande en deux étapes (donc sans -d *.buzut.fr pour la précédente)
# nous obtenons un fichier par certificat
certbot certonly --dns-ovh --dns-ovh-credentials ~/.ovhapi -d *.buzut.fr

# si vous souhaitez scripter la génération
# il faut préciser à la commande de ne pas être interactive
certbot certonly --dns-ovh --dns-ovh-credentials ~/.ovhapi --non-interactive --agree-tos --email mon@email.fr -d buzut.fr -d *.buzut.fr

La commande renew de Certbot n’est pour l’heure pas compatible avec les plugins DNS. Il faudra donc renouveller l’ensemble des commandes utilisées pour créer les certificats de temps à autre – au moins une fois tous les 90 jours – afin de ne pas laisser les certificats périmer. Un petit script de renouvellement est tout indiqué.

# ce script trouve parfaitement sa place dans /usr/local/sbin/renewCerts.sh
#!/bin/bash

/usr/local/bin/certbot certonly --dns-ovh --dns-ovh-credentials /root/.ovhapi --non-interactive --agree-tos --email mon@email.fr -d buzut.fr
/usr/local/bin/certbot certonly --dns-ovh --dns-ovh-credentials /root/.ovhapi --non-interactive --agree-tos --email mon@email.fr -d *.buzut.fr

Vous pouvez ensuite l’appeler une fois par mois avec une crontab et vous aurez l’assurance d’avoir des certificats toujours à jour.

22 4 5 * * /usr/local/sbin/renewCerts.sh > /dev/null 2>&1

Et voilà, vous avez maintenant une validation par DNS avec renouvellement automatique, laquelle vous permet d’obtenir des certificats wildcard et de générer des certificats même si les DNS du domaine pointent vers une autre ip. Ça peut être utile en cas de load balancing par DNS par exemple.

Commentaires

Rejoignez la discussion !

Vous pouvez utiliser Markdown pour les liens [ancre de lien](url), la mise en *italique* et en **gras**. Enfin pour le code, vous pouvez utiliser la syntaxe `inline` et la syntaxe bloc

```
ceci est un bloc
de code
```