Let's Encrypt
Let's Encrypt est une initiative visant à répandre le chiffrement des communications à base de certificat X.509 sur le net, en facilitant son déploiement.
Cette initiative a généré beaucoup de bruit, car comme toujours il y a du bon et du moins bon. Pour simplifier, je dirais que Let's Encrypt permet de générer des certificats (reconnus à peu près partout en utilisation web), valables 90 jours, permettant de définir plusieurs noms DNS (ou même un joker (wildcard)) et ce gratuitement et automatiquement. Plus d'informations sur leur site. Habituellement c'est un processus relativement ennuyeux, souvent payant ou sinon plus limité.
Essais
Au gré des lectures, j'ai vu passer un client non-officiel, et certaines personnes qui me semblaient sensées affirmaient qu'il était encore plus simple et efficace. Par hasard j'ai donc commencé à regarder le README, puis le code, et à tester…
Le README est très explicite, et globalement ça fonctionne effectivement bien. À part quelques détails et un bug (corrigé du coup :)) dans le domaine que j'ai pris comme cobaye, pas de soucis.
Mise en place
Voici comment j'ai mis en place tout cela, guidé par le README du client et un peu de pifomètre. Pour comprendre, vraiment, lisez le README…
Base
cd /usr/local/bin/
wget https://raw.githubusercontent.com/diafygi/acme-tiny/master/acme_tiny.py
chmod +x acme_tiny.py
adduser --system --no-create-home acme
mkdir /etc/ssl/letsencrypt
cd /etc/ssl/letsencrypt
Ici le dossier /etc/ssl/letsencrypt est peut-être pas très malin : vu que certains fichiers vont être amenés à changer automatiquement c'est plutôt à caser dans /var… à améliorer un jour peut-être.
Suite, un peu de crypto (clef privée du compte à sauvegarder !) :
openssl genrsa 4096 > account.key
chown acme account.key
chmod 600 account.key
wget -O intermediate.pem https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem
Edit: passage au certificat X3, voir https://letsencrypt.org/certificates/
Scripts de déploiement
- Globalement, pour chaque nouveau domaine :
- Créer une clef privée
- Générer la requête de signature (CSR)
- Préparer le terrain pour les fichiers de vérification du domaine (créer le dossier acme-challenge)
Pour moi ça se concrétise en :
#!/bin/bash
[ $# -eq 2 ] || exit
domain=$1
acmedir=$2
cd /etc/ssl/letsencrypt
openssl genrsa 4096 > $domain.key
chmod 600 $domain.key
openssl req -new -sha256 -key $domain.key -subj "/" -reqexts SAN -config <(cat ./openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:$domain,DNS:www.$domain")) > $domain.csr
mkdir -p $acmedir/.well-known/acme-challenge/
chown acme $acmedir/.well-known/acme-challenge/
echo "$domain $acmedir/.well-known/acme-challenge/" >> autoupdate
La dernière ligne ajoute une entrée dans un fichier spécial autoupdate, qui permet au script de renouvellement de savoir quels certificats renouveler et dans quel dossier mettre les fichiers de vérification.
Et donc, le script de (re)génération des certificats qui correspond (je l'ai mis dans /etc/cron.monthly/letsencrypt) :
#!/bin/bash
DIR=/etc/ssl/letsencrypt/
TODAY=$(date +%Y%m%d)
cat $DIR/autoupdate | while read -a data; do
domain=${data[0]}
acmedir=${data[1]}
if [ -e $DIR/$domain.pem ] && [[ `date -d "now - $( stat -c "%Y" $DIR/$domain.pem) seconds" +%s` -lt 4320000 ]]; then
echo "Skipping $domain as too young (less than 50 days)"
continue
fi
if ! [ -d $acmedir ]; then
mkdir -p $acmedir
chown acme $acmedir
fi
sudo -u acme python /usr/local/bin/acme_tiny.py --account-key $DIR/account.key --csr $DIR/$domain.csr --acme-dir $acmedir > $DIR/$domain.crt-$TODAY
if [ $? -eq 0 ]; then
cat $DIR/$domain.crt-$TODAY $DIR/intermediate.pem > $DIR/$domain.pem
chmod 600 $DIR/$domain.pem
fi
chmod 600 $DIR/$domain.crt-$TODAY
done
service apache2 reload
J'évite de générer si le fichier existe et a moins de 50 jours (90 jours de validité, en cron monthly au max donc tous les 31 jours, avec un peu de marge disons 40, donc on arrive bien à 90-40=50).
Le nouveau certificat, je le mets dans un fichier plus ou moins "versionné", avec la date dans le nom quoi. C'est pour éviter d'écraser le certificat précédent en cas de mauvaise manipulation (qui m'est arrivé pendant l'écriture du script) ou pour réparer rapidement au cas où une génération se passerait mal, en repartant sur le précédent.
Voila, pour l'instant j'ai 4 sites qui sont passés du snakeoil du paquet ssl-cert à un vrai certificat reconnu comme cela. Le dernier a été "TLSifié" en 3 minutes 30, ça va ! On verra maintenant au moment du renouvellement… ne pas oublier d'ajouter une vérification à son monitoring (auto-pub : picomon par exemple) si on tient à son site en TLS.
EDIT:
- Dans le script, passage de l'opérateur < à -lt car « Lorsqu'ils sont utilisés avec [[, les opérateurs < et > ordonnent d'un point de vue lexicographique en utilisant les paramètres linguistiques régionaux actuels. ». Ceci faisant donc une exception à l'évaluation arithmétique…
- Ajout de la création du dossier acmedir s'il n'existe plus (il peut avoir été écrasé comme par exemple avec make ssh_upload de Pelican qui fait un rsync avec l'option --delete).