Vous n'êtes sûrement pas passés à coté, Let's Encrypt, la petite dernière des autorités de certification alternatives, est passée en beta publique le 3 décembre 2015. Soutenue par de grands acteurs tels que Mozilla, l'EFF, Google, OVH, Akamai, Cisco, Facebook, et bien d'autres, elle permet d'obtenir gratuitement, de manière confidentielle, et en ligne de commande, des certificats SSL reconnus valides par tous les navigateurs et systèmes d'exploitation. En bref, un beau pied de nez à l'industrie du vent que nous vendent depuis des années les autorités de certification, et une belle voie pour que tout le monde puisse passer à HTTPs.

Cet article présente la manière dont nous avons mis ça en œuvre, concrètement, sur nos serveurs, afin d'exploiter au maximum les possibilités d'automatisation fournies par le protocole de Let's Encrypt : ACME.

Ajouté en juillet 2017 : Cet article date d'une époque où certbot n'existait pas encore. De nos jours nous vous conseillons plutôt d'utiliser cette solution standard.

ACME Tiny

Commençons par un peu de lexique. Let's Encrypt, c'est le nom du projet, mais letsencrypt c'est aussi le nom du script officiel fourni par le projet pour générer les certificats, les installer au bon endroit, et configurer Nginx ou Apache. Nous n'allons pas utiliser ce script, mais plutôt ACME Tiny, qui a l'avantage d'être beaucoup plus court et de ne faire que ce que l'on attend de lui, c'est à dire faire signer un certificat sur les serveurs de Let's Encrypt (via le protocole « ACME » dont le script tire son nom).

Il faut donc installer ce script sur le serveur, par exemple dans /usr/local/bin/acme_tiny.py.

wget https://raw.githubusercontent.com/diafygi/acme-tiny/master/acme_tiny.py -O /usr/local/bin/acme_tiny.py

Un premier certificat

Pour notre premier certificat, la documentation ACME Tiny décrit parfaitement la procédure à suivre. Pour des raisons d'organisation, nous stockerons tout dans /etc/letsencrypt/ :

mkdir /etc/letsencrypt
chown root:ssl-cert /etc/letsencrypt
chmod 750 /etc/letsencrypt

Étape 1 : Préparation

On commence par générer notre clé client Let's Encrypt. On pourra se permettre d'en générer une par serveur, mais elle doit rester parfaitement en sécurité :

openssl genrsa -out /etc/letsencrypt/letsencrypt.key 4096

Puis on génère la clé privée du certificat, ainsi que la CSR (Certificate Signing Request) qui sera envoyée à Let's Encrypt via ACME pour faire générer le certificat :

mkdir /etc/letsencrypt/www.sysnove.fr
cd /etc/letsencrypt/www.sysnove.fr
openssl genrsa -out www.sysnove.fr.key 4096

Pour la CSR, il y a deux solutions. Soit votre certificat ne couvre qu'un seul domaine :

openssl req -new -sha256 -key www.sysnove.fr.key -subj "/CN=www.sysnove.fr" -out www.sysnove.fr.csr

Soit votre certificat couvre plusieurs domaines. C'est le cas de www.sysnove.fr qui doit aussi couvrir sysnove.fr. Dans ce cas, il faut inclure l'extension SAN (Subjet Alternative Names) dans la CSR, et la commande est légèrement plus compliquée :

openssl req -new -sha256 -key www.sysnove.fr.key -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:sysnove.fr,DNS:www.sysnove.fr")) > www.sysnove.fr.csr

Étape 2 : Les challenges

Afin que Let's Encrypt accepte de signer le certificat, nous allons devoir prouver que nous en sommes bien le propriétaire. Pour ce faire, ACME Tiny va générer un fichier qui devra être accessible via le web sur le domaine à valider. Il faut donc que le serveur web soit capable de livrer ce fichier sur la bonne URL, à savoir http://www.sysnove.fr/.well-known/acme-challenge/*fichier-généré*. Par expérience, le plus simple est d'utiliser un seul répertoire pour les challenges de tous les domaines, et de configurer chaque vhost Nginx ou Apache pour pointer vers ce répertoire.

mkdir -p /srv/www/acme-challenges/

Puis, si vous utilisez Apache, il suffit d'ajouter le fichier /etc/apache2/conf-enabled/acme-challenges.conf :

Alias /.well-known/acme-challenge /srv/www/acme-challenges
<Directory "/srv/www/acme-challenges">
    Options -Indexes
    AllowOverride all
    Require all granted
</Directory>

Dans Nginx, il n'y a pas moyen de configurer un chemin pour tous les vhosts. Il faut donc le configurer dans chaque vhost, par exemple dans /etc/nginx/sites-enabled/www.sysnove.fr :

server {
    server_name www.sysnove.fr;
    
    location /.well-known/acme-challenge {
        alias /srv/www/acme-challenges/;
        try_files $uri =404;
    }
}

Étape 3 : Signature

Il ne reste plus qu'à utiliser ACME Tiny pour faire signer la CSR :

# python /usr/local/bin/acme_tiny.py --account-key /etc/letsencrypt/letsencrypt.key --csr /etc/letsencrypt/www.sysnove.fr/www.sysnove.fr.csr --acme-dir /srv/www/acme-challenges/ > /etc/letsencrypt/www.sysnove.fr/www.sysnove.fr.crt
Trying to generate certificate for domain www.sysnove.fr…
Parsing account key...
Parsing CSR...
Registering account...
Registered!
Verifying www.sysnove.fr...
www.sysnove.fr verified!
Verifying sysnove.fr...
sysnove.fr verified!
Signing certificate...
Certificate signed!
Certificate for www.sysnove.fr generated !

Et voilà ! /etc/letsencrypt/www.sysnove.fr/ contient désormais la clé (.key) et le certificat (.crt).

Pour finir, vous pouvez télécharger le certificat intermédiaire et reconstituer le certificat chainé dont vous aurez besoin dans Nginx :

cd /etc/letsencrypt
wget -O - https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem > intermediate.pem
cat www.sysnove.fr/www.sysnove.fr.crt intermediate.pem > www.sysnove.fr/www.sysnove.fr.crt+chain

Automatiser le renouvellement

LE problème de Let's Encrypt, c'est que les certificats ne sont signés que pour 90 jours. Au delà, ils expirent et les navigateurs refuseront la connexion. La solution, c'est de profiter de acme-tiny pour régénérer automatiquement le certificat dès qu'il arrive à 30 jours avant d'expirer.

En effet, jusqu'ici nous avons tout fait manuellement, mais une fois la clé et la CSR préparées, et une fois le répertoire de challenges accessible par le web, qu'est-ce qui empêche de mettre la dernière étape dans un cron ? Rien. Et pour se simplifier la vie, autant faire un script générique qui découvre par lui-même les certificats et régénère uniquement ceux qui en besoin. En voici un exemple :

Ce script, lancé tous les jours (en le plaçant dans /etc/cron.daily/, par exemple), s'assurera que vos certificats soient renouvelés en permanence, et que vous n'ayez plus du tout à vous en préoccuper.

Aller plus loin avec Ansible : automatiser la création des certificats

Le développeur attentif notera que ce script va un peu plus loin que le renouvellement, il gère aussi la première signature (parce qu'en fait, c'est exactement la même chose). Par conséquent, si vous souhaitez un nouveau certificat sur votre serveur, il vous suffit de réaliser les étapes 1 et 2 ci-dessus, et d'appeler le script qui se chargera de la signature.

Et pourquoi s'arrêter en si bon chemin dans l'automatisation ? Maintenant que la première signature et que le renouvellement sont automatisés, il ne reste plus qu'à utiliser notre outil de déploiement préféré pour générer automatiquement les clés et les CSR dont nous avons besoin. C'est tout l'enjeu de ce rôle Ansible, qui en profite pour installer acme-tiny et pour déployer le cron letsencrypt-auto-renew.sh.

Conclusion

En conclusion, le projet Let's Encrypt nous apporte bien plus que des certificats SSL gratuits, il nous donne la possibilité d'automatiser de A à Z la création et le renouvellement de ces certificats. Cette tâche, qui pouvait prendre 30 minutes par certificat à un administrateur système habitué, est désormais à la portée de n'importe quel développeur. On ne peut qu'imaginer le potentiel extraordinaire de Let's Encrypt et du protocole ACME, lorsqu'il sera implémenté dans les panels de gestion comme Plesk, ISPConfig, AlternC, etc.

Du chiffrement partout et pour tous, enfin !

À propos de l'auteur



Guillaume est l'un des deux fondateurs et cogérants de Sysnove. Développeur Python et administrateur système passionné de logiciel libre et des technologies liées à Internet, il participe à divers projets, notamment le fournisseur d'accès Internet Aquilenet ainsi que la Fédération FDN.

Chez Sysnove, son rôle consiste à mettre en place et administrer les infrastructures nécessaires à l'hébergement des services fournis aux clients. En tant que directeur général, il gère aussi les aspects administratifs de l'entreprise.