Commit 065bf196 authored by sebian's avatar sebian Committed by Maxime Vidori
Browse files

blog: Add letsencrypt article

parent bfc19afe
Title: Yet another tutorial about Let's Encrypt
Category: Tech
Tags: https, letsencrypt
Date: 2016-03-07 20:00
![Logo Let's Encrypt](//letsencrypt.org/images/letsencrypt-logo-horizontal.svg)
Voilà 1 million de certificats [Let's Encrypt](//letsencrypt.org/) délivrés (les certificats délivrés par [Let's Encrypt](https://crt.sh/?Identity=%25&iCAID=7395)); La littérature sur le sujet ne manque pas, mais je vais quand même en apporter une de plus, pour la partie compilation :-)
Pour rappel, Let's Encrypt, est un projet porté par l' « Internet Security Research Group » (ISRG), qui vise à automatiser, rendre accessible à tous, de manière ouverte et gratuite, des certificats SSL
# Génération
Nous allons ici, ne pas utiliser le client officiel; Principalement parce qu'il intègre trop de fonctionnalités (serveur web intégré, …), mais aussi parce qu'il ne réponds pas vraiment aux besoins de cet article (arborescence flexible, serveur nginx, …; et que c'est plus facile à lire un script de 200 lignes qu'un énorme client…)
Le client que nous allons utiliser est donc le [acme-tiny](https://github.com/diafygi/acme-tiny) (écrit en python). Lors de mes pérégrinations sur la toile (oui ok ça fait un peu vieillot, j'aurais pu dire « alors que je surfais sur le web », … :-D), je suis tombé sur ce script [letsencrypt.sh](https://github.com/lukas2511/letsencrypt.sh). Le coté FQDN à un endroit, et le rechargement lorsque les AltNames changent sont des features appréciables. Après c'est du bash, donc comme vous voulez :)
## Création des certificats
De mon coté, j'ai opté pour une arborescence de ce type (certificats générés dans un répertoire dédié, avec un utilisateur dédié).
```
$ mkdir -p /etc/letsencrypt/{certs,challenges,csr,pem,private}
/etc/letsencrypt/
├── certs
├── challenges
├── csr
├── pem
└── private
```
Il suffit donc alors de :
* Créer une clé pour le domaine en question
* Créer une demande de signature (CSR) en y incluant les noms DNS alternatifs
* Lancer le client (qui va se charger de créer un challenge) et signer si le challenge est ok.
* Télécharger et concaténer le certificat obtenu avec le certificat intermédiaire de Let's Encrypt
Le challenge sert ici à ce que let's encrypt vérifie que nous contrôlons bien le
domaine pour lequel nous demandons un certificat. Il faut d'ailleurs ajouter à
la configuration du serveur web, l'endroit où seront stockés ces challenges.
```nginx
location /.well-known/acme-challenge/ {
alias /etc/letsencrypt/challenges/gitoyen.net/;
try_files $uri =404;
}
```
Coté certificat intermédiaire, ils sont disponibles sur le site de [Let's Encrypt](https://letsencrypt.org/certificates/).
Bon donc du coup ça donne cela dans un mini-script (pas super beau…)
```bash
#!/bin/bash
# bootstrap letsencrypt
account=$1
cert=$2
dns=$3
mkdir -p /etc/letsencrypt/{certs,challenges,csr,pem,private}
pushd /etc/letsencrypt
if [[ ! -f "./private/${account}.key" ]]; then
openssl genrsa 4096 > "./private/${account}.key"
fi
if [[ ! -f ./pem/intermediate.pem ]]; then
wget -O - https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem > ./pem/intermediate.pem
fi
echo "##### ${cert} #####"
if [[ ! -f "./private/${cert}.key" ]]; then
openssl genrsa 4096 > "./private/${cert}.key"
fi
mkdir -p "./challenges/${cert}"
openssl req -new -sha256 -key "./private/${cert}.key" -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=%s" "${dns}")) > "./csr/${cert}.csr"
acme_tiny.py --account-key "./private/${account}.key" --csr "./csr/${cert}.csr" --acme-dir "/etc/letsencrypt/challenges/${cert}/" > "./certs/${cert}.crt"
cat "./certs/${cert}.crt" ./pem/intermediate.pem > "./pem/${cert}.pem"
popd
```
Qu'il suffit de lancer comme ceci (pour l'exemple je génère un certificate
asral.fr avec comme domaines gérés gitoyen.net et planet.gitoyen.net (oui de la pub au passage))
```bash
$ bash bootstrap-letsencrypt.sh asrall gitoyen.net 'DNS:gitoyen.net,DNS:planet.gitoyen.net'
##### gitoyen.net #####
Parsing account key...
Parsing CSR...
Registering account...
Already registered!
Verifying planet.gitoyen.net...
planet.gitoyen.net verified!
Verifying gitoyen.net...
gitoyen.net verified!
Signing certificate...
Certificate signed!
```
Plutôt cool non? Il suffit alors d'adapter la configuration du serveur web, pour
prendre en compte ces certificats. Et passer tout en HTTPS! (dans notre cas,
c'est un nginx en reverse proxy qui gère le SSL et forward en HTTP sur une IP
privée).
```nginx
# Gitoyen
server {
server_name gitoyen.net planet.gitoyen.net;
rewrite ^(.*) https://$host$1 permanent;
}
# Gitoyen SSL
# DNS:gitoyen.net,DNS:planet.gitoyen.net
server {
listen 443;
ssl on;
client_max_body_size 20M;
server_name gitoyen.net planet.gitoyen.net asrall.sebian.fr;
ssl_certificate /etc/letsencrypt/pem/gitoyen.net.pem;
ssl_certificate_key /etc/letsencrypt/private/gitoyen.net.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA;
ssl_session_cache shared:SSL:50m;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/letsencrypt/dh4096.pem;
ssl_ecdh_curve secp384r1;
add_header Strict-Transport-Security max-age=15768000;
resolver 127.0.0.1;
location /.well-known/acme-challenge/ {
alias /etc/letsencrypt/challenges/gitoyen.net/;
try_files $uri =404;
}
location / {
proxy_pass http://10.41.1.143;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Ssl on;
}
}
```
Pour la génération du dhparams (4096 bits c'est bien)
```bash
openssl dhparam -out dh4096.pem 4096
```
Et vous voila donc avec une super config et du HTTPS automatisé, on peut aller
faire un tour sur [imirhil](https://tls.imirhil.fr/https/gitoyen.net) pour un
check de la conf et bien sûr pour pouvoir briller en société…
# Supervision
Bon c'est bien beau, mais avec tout ça les certificats sont valables que 90j
(oui mort à CertPatrol :-() mais pour le coup il va donc falloir superviser
tout cela.
## Via Certificate Monitor
Si vous utilisez le sympa [certificatemonitor](https://certificatemonitor.org/) ([code source](https://github.com/RaymiiOrg/certificate-expiry-monitor)) de Raymii, il suffit alors d'ajouter vos FQDN dans l'interface. Et ainsi recevoir une notification avant l'expiration de vos certificats.
## Via Checkmk
Sinon si vous avez déjà une bonne veille supervision à base de nagios ou checkmk ou compatible, il suffit d'ajouter les checks via le script `check_http`.
Dans la conf `main.mk` de checkmk:
```checkmk
# /etc/checkmk/main.mk
legacy_checks = [
## Gitoyen
( ( "check-certificate!gitoyen.net", "Certificate Gitoyen - Letsencrypt", True), ['baloo.sebian.fr']),
( ( "check-certificate!planet.gitoyen.net", "Certificate Planet Gitoyen - Letsencrypt", True), ['baloo.sebian.fr']),
]
```
Et ne pas oublier la `check_command` associée (on émet un warning lorsque que le certificat expire à J-30 et un critical à J-7)
```nagios
# /etc/checkmk/conf.d/commands_extra.mk
define command {
command_name check-certificate
command_line $USER1$/check_http -H $ARG1$ -C 30,7 --sni
}
```
# Renouvellement
Il existe des scripts de renouvellement automatique:
* [letsencrypt-renew](https://github.com/octopuce/octopuce-goodies/tree/master/letsencrypt-renew)
* [letsencrypt.sh](https://github.com/lukas2511/letsencrypt.sh)
Mais je ne sais pas encore quoi en penser, pour le moment je réagit lorsque que
le check passe en warning avec ce mini script bash.
```bash
#!/bin/bash
account='asrall'
certs='gitoyen.net planet.gitoyen.net'
pushd /etc/letsencrypt
for cert in $certs
do
echo "##### ${cert} #####"
acme_tiny.py --account-key ./private/labriqueinternet.key --csr ./csr/${cert}.csr --acme-dir /etc/letsencrypt/challenges/${cert}/ > ./certs/${cert}.crt
cat ./certs/${cert}.crt ./pem/intermediate.pem > ./pem/${cert}.pem
done
popd
systemctl restart nginx
```
# Chocolat
Même si le modèle des CA et bancal, il n'y a plus de raison maintenant de ne pas proposer du HTTPS partout!
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment