Introduction

acmetool est un utilitaire permettant d'obtenir des certificats via le protocole ACME (celui de Let's Encrypt*).

Il a été retenu, parce que :

  • c'est un outil écrit en Go, donc on n'a pas de soucis à pin depuis Debian testing, car il n'a pas de dépendances farfelues ;
  • il est idempotent : relancer acmetool avant qu'un certificat ait besoin d'être renouvelé ne déclenche aucune requête vers Let's Encrypt ;
  • il a un mode batch robuste, bien adapté à l'appel dans un cronjob ;
  • il est très configurable et assez bien documenté ;
  • il supporte d'être exécuté sans privilèges particuliers.

acmetool a été installé sur bulbe par jvoisin et nicoo.

Tour d'horizon

L'état courant d'acmetool se trouve dans /var/lib/acme ; on y trouve notamment le répertoire live, qui contient des liens symboliques vers les répertoires idoines pour chaque nom de domaine (pour lequel on a un certificat).

Ces répertoires contiennent :

  • cert, le certificat ;
  • chain, la chaîne de CAs signant le certificat ;
  • fullchain, le certificat et la chaîne en un seul fichier ;
  • privkey, un lien symbolique vers la clef privée ;
  • url, un fichier contenant une URL où le CA met à disposition une copie du certificat.

acmetool stocke aussi sa configuration dans /var/lib/acme, mais on l'a remplacée par des symlinks vers /etc/acme :

  • le fichier /etc/acme/conf/target contient les valeurs par défaut pour les certificats : challenge, algorithme de signature, taille de la clef RSA, …
  • /etc/acme/desired contient un fichier de configuration par certificat.

Une description plus complète est disponible dans la documentation.

Utilisation « de base »

Pour obtenir un nouveau certificat, sans configuration particulière :

sudo -u acme acmetool want machin.nos-oignons.net truc.nos-oignons.net
sudo etckeeper commit

Une clef est générée, un certificat est acquis depuis Let's Encrypt, et le résultat est disponible sous /var/lib/acme/live/machin.nos-oignons.net.

Le certificat sera renouvelé automatiquement, et une nouvelle clef est générée (par défaut) à chaque renouvellement.

Configuration déployée sur bulbe

À l'heure actuelle, 2 certificats sont maintenus par acmetool, chacun ayant ses spécificités de configuration.

Paramètres par défaut

nicoo a modifié les paramètres par défaut d'acmetool pour générer des clefs RSA de 4kbits (2kb par défaut) :

# /var/lib/acme/conf/target
request:
  provider: https://acme-v01.api.letsencrypt.org/directory
  key:
    type: rsa
    rsa-size: 4096
  challenge:
    webroot-paths:
    - /var/lib/acme/webroot

Serveur Web

Un certificat pour {,www.}nos-oignons.{net,org,fr} est maintenu, avec l'option OCSP-Must-Staple. pour rendre la vérification de révocation du certificat obligatoire.

# /var/lib/acme/desired/www.nos-oignons.org-j5thsdpg7fgtvempit6g4vyv2m
satisfy:
  names:
  - nos-oignons.net
  - nos-oignons.org
  - nos-oignons.fr
  - www.nos-oignons.net
  - www.nos-oignons.org
  - www.nos-oignons.fr

request:
  ocsp-must-staple: true

L'option request.ocsp-must-staple est pour l'instant inopérante, à cause d'un bug remonté par nicoo et corrigé dans la version 0.0.56 d'acme

Serveur SMTP

Notre Postfix a un certificat valide pour bulbe.nos-oignons.net. La spécificité ici est que la clef publique ne doit pas être changée à chaque renouvellement du certificat, puisqu'on la pin sur les nœuds de sortie.

# /var/lib/acme/desired/bulbe.nos-oignons.net-syghkqm6izf3fbm2sjalo4rnnq
satisfy:
  names:
  - bulbe.nos-oignons.net

request:
  key:
    id: k2425j72hots32y36ftqpsmrtktx2pug6hcpy2mcth6hgoofqxwq

request.key.id est l'identifiant de la clef ayant été générée lors de l'exécution d'acmetool want bulbe.nos-oignons.net.

Hooks

acmetool permet de définir des hooks qui sont exécutés à chaque étape de l'obtention d'un nouveau certificat. Celle qui nous intéresse est live-updated, qui signifie qu'un nouveau certificat a été déployé :

#!/bin/sh -e
# /etc/acme/hooks/reload.sh

if [ "$1" = "live-updated" ];  then
    systemctl reload postfix
    systemctl reload nginx
fi

Les hooks se situent sous /etc/acme/hooks, et peuvent être marqués setuid : dans le cas de scripts, le bit setuid est inopérant, mais il signale à acmetool le besoin d'exécuter le hook via sudo.

Du coup, on donne à l'user acme le droit d'exécuter n'importe quel hook (n'importe quel fichier sous /etc/acme/hooks) via sudo, sans forcément avoir un tty ; ce n'est pas un problème, car le répertoire et les fichiers ne peuvent être modifiés que par root.

# /etc/sudoers.d/05_acmetool
Cmnd_Alias ACME_HOOKS = /etc/acme/hooks/
Defaults!ACME_HOOKS !requiretty
acme ALL=(root) NOPASSWD: ACME_HOOKS