Pinning de clefs publiques avec Let's Encrypt et Apache (Dernière mise à jour : 25/02/2017 11:57:16)

J'utilise, pour un autre domaine que celui-ci des certificats SSL gratuits grâce à Let's Encrypt.

J'ai ensuite souhaité mettre en place du pinning de clefs publiques pour les différents certificats associés.

Cependant, les certificats Let's Encrypt n'étant valident que trois mois, j'ai donc du prévoir le cas d'un renouvellement de certificat et donc la gestion/génération des nouvelles clefs publiques.

Dans les faits, j'ai utilisé CertBot pour créer les certificats SSL et je lance une tâche CRON de manière quotidienne afin de renouveler, si nécessaire, les nouveaux certificats : # Certbot
45 23 * * * root certbot renew --quiet > /dev/null 2>&1 && /root/le.sh


Pour la suite de cet article, le nom de domaine osef.com a été utilisé, remplacé par le vôtre, bien entendu.

J'appelle ensuite le script /root/le.sh qui va s'occuper de calculer les clefs publiques des certificats.
Voici le script que j'ai mis en place à cette occasion :
#!/bin/bash
# First, let's define our domain name :
LEDomain='osef.com'

# Next, let's get the certificates locations
LEPrivkey=/etc/letsencrypt/live/${LEDomain}/privkey.pem
LEAuthority=/etc/letsencrypt/live/${LEDomain}/chain.pem
LERootCert=/etc/ssl/certs/DST_Root_CA_X3.pem

# Then we get the HPKP keys needed
echo '---'
echo 'First key to pin:'
Key1=$(openssl rsa -in ${LEPrivkey} -outform der -pubout 2>/dev/null | openssl dgst -sha256 -binary | openssl enc -base64)
echo ${Key1}
echo '---'
echo 'Second key to pin:'
Key2=$(openssl x509 -in ${LEAuthority} -pubkey -noout 2>/dev/null | openssl pkey -pubin -outform der 2>/dev/null | openssl dgst -sha256 -binary | openssl enc -base64)
echo ${Key2}
echo '---'
echo 'Last key to pin:'
Key3=$(openssl x509 -in ${LERootCert} -pubkey -noout 2>/dev/null | openssl pkey -pubin -outform der 2>/dev/null | openssl dgst -sha256 -binary | openssl enc -base64)
echo ${Key3}
echo '---'
echo 'Backup key to pin:'
BackupKey=${LEDomain}-backup.key
if [ -f $BackupKey ]
then
echo 'Generating backup key for '${LEDomain}
openssl genrsa -out ${LEDomain}-backup.key 4096 2>/dev/null
fi
Key4=$(openssl x509 -in ${LEDomain}-backup.key -pubkey -noout 2>/dev/null | openssl pkey -pubin -outform der 2>/dev/null | openssl dgst -sha256 -binary | openssl enc -base64)
echo ${Key4}
echo '---'

# Finally, we export those informations into a file in order to import it in our Apache configuration
mkdir -p /etc/apache2/ssl/
echo '' > /etc/apache2/ssl/${LEDomain}-hpkp.conf
echo ' Header always set Public-Key-Pins "pin-sha256=\"'${Key1}'\"; pin-sha256=\"'${Key2}'\"; pin-sha256=\"'${Key3}'\"; pin-sha256=\"'${Key4}'\"; max-age=5184000; includeSubDomains"' >> /etc/apache2/ssl/${LEDomain}-hpkp.conf
echo '
' >> /etc/apache2/ssl/${LEDomain}-hpkp.conf

# Reload Apache2 configuration
if [[ $(apache2ctl -t) != "Syntax OK" ]]
then
echo 'Reloading Apache'
service apache2 reload
echo 'Reload is done'.
else
echo 'Syntax is not OK. Check it and reload on your end.'
fi

Le script pourrait être amélioré pour que l'on puisse l'appeler avec un argument : le nom de domaine.
Par manque de temps, je n'ai pas mis en place cette possibilité mais ça peut vite se corriger.

Enfin, j'ai placé une instruction d'Include dans la configuration de mon vhost pour aller rechercher le fichier créé par le script donné plus haut et contenant les hashes de clefs publique que doit renvoyer Apache lors des appels effectués en HTTPS pour ce vhost :
# HPKP
Include /etc/apache2/ssl/osef.com-hpkp.conf


Fichier généré dans /etc/apache2/ssl/osef.com-hpkp.conf :

Header always set Public-Key-Pins "pin-sha256=\"DYCLwC/X0/TGlxRRdi6JyqlwL2YnOCn+zdJHims4Bis=\"; pin-sha256=\"YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fvihg=\"; pin-sha256=\"Vjs8r4z+80wjNcr1YKepWQboSIRi63WsWXhEMN+eWys=\"; pin-sha256=\"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMqJWZG3hSuFU=\"; max-age=5184000; includeSubDomains"


Et le tour est joué.
07/01/2017 15:15:55

Partager cet article

Commentaires (Cliquer pour afficher)

comments powered by Disqus