146 lines
5.4 KiB
Markdown
146 lines
5.4 KiB
Markdown
---
|
||
categories: web security
|
||
title: Howto Let's Encrypt
|
||
...
|
||
|
||
* Documentation : <https://letsencrypt.org/docs/>
|
||
* Documentation Certbot : <https://certbot.eff.org/docs/>
|
||
* Rôle Ansible : <https://forge.evolix.org/projects/ansible-roles/repository/revisions/stable/show/evoacme>
|
||
|
||
[Let's Encrypt](https://letsencrypt.org/) est une autorité de certification fournissant des certificats [SSL](HowtoSSL) valables 90 jours gratuitement et automatiquement.
|
||
L'obtention d'un certificat signé s'effectue via le protocole [ACME (Automated Certificate Management Environment)](https://en.wikipedia.org/wiki/Automated_Certificate_Management_Environment),
|
||
ce qui nécessite d'avoir temporairement un serveur HTTP sur le port TCP/80 de l'adresse IP correspondant au _Common Name_ du certificat à signer.
|
||
Le certificat intermédiaire de Let's Encrypt est également signé par l'autorité de certification [IdenTrust](https://www.identrust.com/) préinstallée dans la plupart des navigateurs.
|
||
|
||
|
||
## Installation
|
||
|
||
Un client ACME est nécessaire pour communiquer avec les serveurs de Let's Encrypt et obtenir un certificat.
|
||
|
||
Nous utilisons le client officiel [Certbot](https://certbot.eff.org/) disponible via les [backports](HowtoDebian/Backports).
|
||
|
||
On ajoute les lignes suivantes à `/etc/apt/preferences.d/backports` :
|
||
|
||
~~~
|
||
Package: certbot python-certbot python-acme python-cryptography python-openssl python-setuptools python-ndg-httpsclient python-pyasn1 python-pkg-resources
|
||
Pin: release a=jessie-backports
|
||
Pin-Priority: 999
|
||
~~~
|
||
|
||
puis on installe certbot et ses dépendances :
|
||
|
||
~~~
|
||
# apt install certbot
|
||
|
||
$ certbot --version
|
||
certbot 0.9.3
|
||
~~~
|
||
|
||
### Création d'un utilisateur dédié
|
||
|
||
On évite de faire tourner certbot avec l'utilisateur _root_ (notamment pour ne pas lui donner accès aux clés privées).
|
||
Nous allons créer un utilisateur dédié _acme_ :
|
||
|
||
~~~
|
||
# adduser --home /var/lib/letsencrypt --quiet --system --no-create-home --group acme
|
||
# install -m 755 -o acme -g acme -d /etc/letsencrypt /var/lib/letsencrypt
|
||
# install -m 750 -o acme -g acme -d /var/log/letsencrypt
|
||
~~~
|
||
|
||
et désactiver la tâche cron `/etc/cron.d/certbot` :
|
||
|
||
~~~
|
||
# mv /etc/cron.d/certbot /etc/cron.d/certbot.disabled
|
||
~~~
|
||
|
||
### Configuration du Serveur Web
|
||
|
||
Pour vérifier que la demande est légitime, Let's Encrypt doit accéder à un fichier temporaire via HTTP sur le port TCP/80 de l'adresse IP correspondant au _Common Name_ du certificat à signer,
|
||
du type *http://www.example.com/.well-known/acme-challenge/hNgN_ygEFf-XiHJd6VErwNbfRcpP2CbJmIN3qpJXZOQ*
|
||
|
||
#### Apache
|
||
|
||
Configuration :
|
||
|
||
~~~{.apache}
|
||
Alias /.well-known/acme-challenge /var/lib/letsencrypt/.well-known/acme-challenge
|
||
<Directory "/var/lib/letsencrypt/.well-known/acme-challenge">
|
||
Options -Indexes
|
||
Allow from all
|
||
Require all granted
|
||
</Directory>
|
||
~~~
|
||
|
||
#### Nginx
|
||
|
||
Configuration :
|
||
|
||
~~~
|
||
location /.well-known/acme-challenge {
|
||
alias /var/lib/letsencrypt/.well-known/acme-challenge;
|
||
try_files $uri =404;
|
||
allow all;
|
||
}
|
||
~~~
|
||
|
||
|
||
## Génération du certificat
|
||
|
||
Générér une clé privée (www.example.com.key) et sa demande de certificat associé (www.example.com.csr) (voir [HowtoSSL]()) :
|
||
|
||
~~~
|
||
# openssl req -newkey rsa:2048 -sha256 -nodes -keyout /etc/ssl/private/www.example.com.key -out /etc/letsencrypt/www.example.com.csr
|
||
# chown acme:acme /etc/letsencrypt/www.example.com.csr
|
||
~~~
|
||
|
||
Faire la première demande de certificat avec l'utilisateur _acme_ :
|
||
|
||
~~~
|
||
$ certbot certonly --webroot --csr /etc/letsencrypt/www.example.com/www.example.com.csr --webroot-path /var/lib/letsencrypt \
|
||
--cert-path /etc/letsencrypt/www.example.com.crt --non-interactive --agree-tos --register-unsafely-without-email
|
||
~~~
|
||
|
||
Votre certificat est maintenant présent dans `/etc/letsencrypt/www.example.com.crt`.
|
||
|
||
> *Note* : l'utilisateur _acme_ n'a pas accès aux clés privées :
|
||
|
||
~~~
|
||
$ cat /etc/ssl/private/www.example.com.key
|
||
cat: /etc/ssl/private/www.example.com.key: Permission non accordée
|
||
~~~
|
||
|
||
## Renouvellement du certificat
|
||
|
||
Les certificats Let's Encrypt sont valables 90 jours. Avant la date d'expiration, il faudra relancer avec l'utilisateur _acme_ :
|
||
|
||
~~~
|
||
$ certbot certonly --webroot --csr /etc/letsencrypt/www.example.com/www.example.com.csr --webroot-path /var/lib/letsencrypt \
|
||
--cert-path /etc/letsencrypt/www.example.com.crt --non-interactive
|
||
~~~
|
||
|
||
|
||
## Automatisation
|
||
|
||
Pour automatiser l'installation de _Certbot_ et la génération/renouvellement de certificats, nous utilisons des scripts : [Evoacme](https://forge.evolix.org/projects/ansible-roles/repository/revisions/stable/show/evoacme).
|
||
|
||
|
||
## FAQ
|
||
|
||
### Certificat Wildcard ou EV
|
||
|
||
Let's Encrypt ne permet pas de générer un certificat Wildcard ou EV (Extended Validation).
|
||
|
||
### Je n'ai pas de port TCP/80 accessible
|
||
|
||
Let's Encrypt vérifie la légitimité de la demande en faisant une requête DNS sur l'enregistrement DNS correspondant au _Common Name_ du certificat à signer (si il n'y a pas d'enregistrement DNS propagé mondialement, c'est donc impossible d'utiliser Let's Encrypt) et effectue une requête HTTP vers le port TCP/80 de l'adresse IP : il faut donc obligatoirement avoir temporairement un service HTTP sur le port TCP/80... au moins temporairement.
|
||
|
||
### Challenge DNS
|
||
|
||
Si notre serveur web n'est pas accessible de l'extérieur, on peut utiliser un challenge par DNS plutôt que via une page http.
|
||
|
||
~~~
|
||
$ certbot -d domain.example.com --manual --preferred-challenges dns certonly
|
||
~~~
|
||
|
||
Il suffira alors de créer l'entrée DNS que certbot affichera et continuer le processus interactif.
|