Bon, Let's Encrypt est maintenant en utilisation beta publique. Toutefois l'utilisation de cette AC n'est pas chose aisée pour tout le monde. C'est sûr, pour du Linux Mainstream (Debian au hasard), ça passe impec. Pour OpenBSD, c'est moins gagné.

OpenBSD dispose aussi de son serveur web, particulièrement minimaliste. Donc on doit adapter. On ne peut pas prendre la solution clé en main proposée.

J'écris cet article pour permettre à d'autres de s'y retrouver, et pour me permettre, à moi, de me souvenir de ma propre procédure, quand j'ai besoin d'ajouter un hôte virtuel.

Au passage, il est fort possible que cet article soit très utile à divers geeks ou hackers, qui souhaitent ou doivent s'écarter des articles copier-coller tout-fait tout-réchauffés, qui ne décrivent en fait qu'une utilisation de TLS en site web et rien d'autre.

Préliminaire

L'utilisation de SSL/TLS n'est pas chose aisée et ce pour plusieurs raisons:

  • C'est un cauchemar à configurer et/ou à utiliser proprement (j'en avais parlé auparavant).
  • C'est supposé améliorer la sécurité de vos communications sur internet, mais en fait, ça crée d'autres problèmes de sécurité !
  • Il ne s'agit pas d'une chose à configurer. C'est un ensemble d'outils à configurer, coordonner et adapter à chaque installation, de façon à ce que tout fonctionne sans problème ni télescopage. C'est pour cette raison que vous ne pouvez vous contenter de copier-coller ce que j'écris. Il vous faut aussi réfléchir, voir adapter mes scripts à votre situation.

Mes scripts sont écrits pour OpenBSD, donc avec du Korn Shell et l'utilisation de doas. Modifiez-les si vous voulez les utiliser ailleurs et vérifiez bien qu'ils passent sur votre serveur.

Il n'y a pas de dépendance particulière si ce n'est python. Et tlsa_rdata si vous voulez utiliser DANE.

Génération, maintenance et rotation des certificats

Je souhaite utiliser DANE (certificats TLS validés par leurs empreintes dans DNSSEC). Ceci m'oblige à générer les certificats et publier leurs empreintes dans le DNS, puis attendre quelques temps (2 TTL d'après les recommandations indiquées ici et ) que les empreintes se propagent dans le DNS.

Durant ce court laps de temps, il y aura donc deux jeux de certificats valides, current - en activité - et latest - ceux qui viennent d'être générés et vont être mis en service.

Tout ceci m'oblige à fortement découper le processus.

Générer les certs un par un

Pour générer les certificats, on va donc utiliser l'AC par le biais d'un client acme non officiel, mais néanmoins accepté avec joie par Let's Encrypt. C'est du logiciel libre et c'est ça qu'est beau, puisque l'AC souhaite vraiment que des clients non officiels apparaissent.

Il est à noter que je n'ai jamais réussi à installer et encore moins à utiliser le client officiel.

Je crée un utilisateur système nommé le pour ça, avec son dossier de travail dans /var/le. Dans ce dossier, j'ai le script acme-tiny (dans son dossier à lui), les scripts pour générer et signer les certificats et un répertoire des domaines qui ont un certificat (faîtes gaffe aux permissions sur ce dernier) :

stephane@blackblock:/var/le ls -l
total 68
drwxr-xr-x  4 stephane  tls     512 Dec 11 22:12 acme-tiny
drwxr-xr-x  7 le        tls     512 Jan  7 08:07 domains
-r-sr-xr-x  1 le        tls    1814 Jan  9 11:05 generate
-rw-r--r--  1 stephane  wheel  2875 Dec 28 13:33 intermediate.pem
-rw-r--r--  1 stephane  wheel  3243 Dec  6 08:46 master.key
-rwxr-xr-x  1 root      tls     319 Jan  2 10:19 regenerate-all
-rwxr-xr-x  1 root      wheel   716 Jan  9 11:22 transition-cert

J'écris un script dans ce dossier, dont le boulot est de créer et faire signer les certificats un par un, ainsi que de les assembler en fichiers utilisables. Il prend en paramètre le nom de domaine FQDN - autrement dit le nom complet, toute la chaîne jusqu'au tld - pour lequel vous souhaitez un certificat et retourne le timestamp (autrement dit, le dossier où les fichiers sont rangés).

/var/le/generate - script - signature GPG

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#!/bin/sh

# needs https://github.com/diafygi/acme-tiny/

# first time
# mkdir -p /var/le/domains/{domains you need}

# create account master key for Letsencrypt to run
# openssl genrsa 4096 > master.key

# Think about creating web vhost and DNS records

timestamp=$(date +%s)
domain=$1

if [ ! -d /var/www/$1 ] ; then
echo "webserver not ready"
exit
fi

mkdir -p /var/le/domains/$domain/$timestamp/
cd /var/le/domains/$domain/$timestamp/

# create key
openssl genrsa 4096 > serverkey.pem

# create CSR
openssl req -new -sha256 -key serverkey.pem -subj "/CN=$domain" > csr

# create repository in web vhost for challenge
# user le should be able to write here
# user www should be able to read and walk the path (r and x rights)
mkdir -p /var/www/$1/.well-known/acme-challenge/

# asking for cert
python2.7 /var/le/acme-tiny/acme_tiny.py --account-key /var/le/master.key \
 --csr /var/le/domains/$domain/$timestamp/csr \
     --acme-dir /var/www/$1/.well-known/acme-challenge/ \
    > /var/le/domains/$domain/$timestamp/cert.pem

# create the files you need (full and partial chain…)
# intermediate.pem contains the chain from letsencrypt AC certificate
cat /var/le/domains/$domain/$timestamp/cert.pem \
    /var/le/intermediate.pem > /var/le/domains/$domain/$timestamp/chain.pem

# This full chain file with the key is needed for haproxy
# (to deliver SNI in front of Httpd)
cat /var/le/domains/$domain/$timestamp/cert.pem \
    /var/le/intermediate.pem \
    /var/le/domains/$domain/$timestamp/serverkey.pem \
    > /var/le/domains/$domain/$timestamp/full.pem

rm -rf /var/www/$1/.well-known/*

# if everything went ok, then modify the rights of the certificates files.
# And return the timestamp.
if [ -r cert.pem ] ; then
    chmod 400 *
    return=$timestamp
else
    return=10
fi

echo $return
return $return

Ce script doit tourner comme l'utilisateur le. Il a les droits:

-r-sr-xr-x  1 le        tls    1412 Dec 30 21:05 generate

J'ai mis S pour que ce soit obligatoirement le qui fasse tourner le script. De cette façon, même si root lance le script, en fait ce sera le, et donc également le qui fait tourner le client acme. Root n'est donc pas en contact direct avec l'exterieur.

J'ai enlevé les droits d'écriture dessus. De cette façon l'utilisateur le ne peut pas modifier son propre script si jamais il est compromis.

Ça réduit fortement les dangers potentiels.

Créer tous les certificats les uns à la suite des autres.

Le script précédent crée chaque certificat dans un dossier et assemble les certificats en fichiers utilisables par les différents serveurs (web, imap, smtp…).

Le script suivant a pour but de régénérer l'ensemble des certificats (autrement dit, pour l'ensemble des hôtes virtuels et FQDN du serveur), de mettre les permissions adéquates (Le propriétaire doit être root, sinon smtpd ne démarrera pas ! C'est décrit ici.), et de générer les empreintes TLSA pour DANE avec l'aide d'un troisième script que je présente juste après.

Tous les certificats sont au statut latest.

Si vous ne souhaitez pas utiliser DANE, il vous suffit alors d'utiliser directement les cert's au statut latest dans vos serveurs logiciels et de les relancer avec ce script. (cf paragraphe Mettre les certificats en service plus bas)

/var/le/regenerate-all - script - signature GPG

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/sh

for domain in $(ls /var/le/domains/)
do
    echo $domain

    # create the certs and same time get the timestamp for which it has been generated.
    time=$(su - le /var/le/generate $domain)

    # give the certs to root
    chown -R root:tls /var/le/domains/$domain/$time/

    # If the previous command did fine
    # then link the certs to be the new certs (that will be loaded in a few days).
    if [[ $? -eq 0 ]]; then
        echo "renew $domain certs"
        ln -s /var/le/domains/$domain/$time/ /var/le/domains/$domain/latest
    fi

done

# create the tlsa RR for the newly generated certs
/var/nsd/tlsa-gen latest

Générer les TLSA

/var/nsd/tlsa-gen - script - signature GPG

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/bin/sh

zone=22decembre.eu

output=/var/nsd/$zone/$1.db

rm -f $output

while read host usage selector match preambule
do
    domain=$host.$zone
    cert=/var/le/domains/$domain/$1/full.pem
    echo $preambule.$host "IN TLSA" $(/usr/local/bin/tlsa_rdata $cert $usage $selector $match) \
        >> $output
    echo $domain " tlsa done"
done < /var/nsd/tlsa-list

zone=$zone.

echo "Resigning zone:"
/usr/local/bin/zkt-signer -v -f $zone || exit

echo "Update NSD:"
/usr/sbin/nsd-control reload $zone

Ce script prend donc en paramètre l'état (latest ou current) des certificats, va les lire et écrit les empreintes avec tlsa_rdata, telles que configurées dans un fichier current ou latest.db.

Le fichier en question est inclut dans la zone DNS (il y a deux $INCLUDE) et toute la zone est alors resignée, puis rechargée dans le serveur DNS (vous pouvez jeter un coup d'œil sur mon montage DNS ici, un exemple de fichier de zone se trouve plus loin).

Le fichier tlsa-list contient la liste des empreintes à générer:

www             3 1 1 _443._tcp
photos          3 1 1 _443._tcp
blackblock      3 1 1 _443._tcp
blackblock      3 1 1 _143._tcp
blackblock      3 1 1 _587._tcp
blackblock      3 1 1 _25._tcp

En premier: le nom simple à utiliser, les trois chiffres sont les paramètres de DANE (vérifiez donc le RFC, j'ai lu le paragraphe relatif à ces paramètres, c'est quand même compréhensible ! OUUUUIIIII !). Le dernier morceau, c'est en fait la première partie de l'enregistrement DNS lui-même, c'est plus simple de le faire comme ça je pense (d'autant que ça laisse toute possibilité de bricolage, manipulation et détournement).

Ceci permet donc d'utiliser les TLSA sur tous les services et protocoles qu'on veut. Ici, j'ai de l'imap, du smtp et du https.

Il est important de ne mettre que le nom de machine simple (blackblock, photos ou www ici). En effet le signeur va compléter le nom de domaine. Mettre ici le nom de domaine complet FQDN aboutirait à quelque chose comme ça:

_143._tcp.blackblock.22decembre.eu.22decembre.eu.

C'est du moins ma configuration.

Faîtes gaffe à ce que vous faîtes avec le DNS, DNSSEC et DANE. Si votre serveur DNS a le moindre problème (connectivité, erreur lors d'une signature ou autre), les validations DNSSEC et DANE risquent de rendre votre serveur inaccessible pour un, plusieurs ou tous les services hébergés.

Mettre les certificats en service

Ici, on va tout simplement supprimer le lien vers les certificats créées il y a un ou deux mois (qui sont encore en activité), passer les certificats qui ont été créées il y a quelques jours de latest (à utiliser prochainement) à current (en activité), et recharger ou relancer les services qui utilisent les certificats.

Ces services doivent être configurés pour utiliser les certificats current. Par exemple:

/var/le/domains/www.example.com/current/cert.pem

Le type de certificat est aussi important (juste le certificat, toute la chaîne…). Pour savoir, consultez la doc du serveur en question.

Le script copie aussi les nouveaux certificats vers le dossier de Radicale (un service d'agenda auto-hébergé léger) pour pouvoir les utiliser (rappelez-vous, les certificats sont propriété de root, or, Radicale n'est pas assez sophistiqué pour pouvoir démarrer comme root, lire les certs, puis quitter ses privilèges administratifs).

/var/le/transition-cert - script - signature GPG

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/bin/sh

for domain in $(ls /var/le/domains/)
do
    # end of current cert by removing the link
    rm /var/le/domains/$domain/current

    # certificates that have been created few days ago linked
    ln -s $(readlink -f /var/le/domains/$domain/latest) /var/le/domains/$domain/current

    # these certificates are not anymore new or latest, they are current !
    rm /var/le/domains/$domain/latest
done

cp /var/le/domains/blackblock.22decembre.eu/current/serverkey.pem /var/radicale/
cp /var/le/domains/blackblock.22decembre.eu/current/chain.pem /var/radicale/
chown _radicale /var/radicale/*.pem

rm /var/nsd/22decembre.eu/current.db
rm /var/nsd/22decembre.eu/latest.db

# The signer bugs if latest.db doesn't exist.
touch /var/nsd/22decembre.eu/latest.db

/var/nsd/tlsa-gen current

rcctl reload haproxy
rcctl restart smtpd
rcctl restart spamd
rcctl reload dovecot
rcctl restart radicale

Crontab

Les scripts sont lancés en crontab par root, tous les deux mois, avec cinq jours de décalage entre la génération des cert's et leur mise en service, ce pour les raisons de propagation DNS citées précédemment :

#
SHELL=/bin/sh
PATH=/bin:/sbin:/usr/bin:/usr/sbin
HOME=/var/log
#
#minute hour    mday    month       wday    command
#
# renew letsencrypt cert'
13      1       10      1,3,5,7,9,11    *       /var/le/regenerate-all

# Loading
15      1       15      1,3,5,7,9,11    *       /var/le/transition-cert

Httpd et Haproxy

Let's Encrypt utilisant une validation par HTTP, la configuration du serveur web a un impact important ici.

Le nouveau démon http de OpenBSD ne permet pas de mettre plusieurs certificats sur un seul serveur. Si vous avez donc plusieurs serveurs virtuels, c'est rapé. J'utilise donc Haproxy, suivant en cela Vigdis.

Je ne décrirais pas les autres services. À vous de chercher un peu.

Httpd

En gros, vous mettez dans httpd.conf uniquement la conf' web (php, quelques redirections, les trucs de base) et je mets chaque serveur virtuel à l'écoute sur un port dédié.

prefork 4
types { include "/usr/share/misc/mime.types" }

server "www.22decembre.eu" {
    listen on ::1   port 2000

    root "/www.22decembre.eu"
    location "/.well-known/*"    { directory auto index }

    log error www-error.log
    log access www-access.log

    location "/bibliotheque/" { block return 301 "https://biblib.22decembre.eu" }
    location "/biblib/"     { block return 301 "https://www.22decembre.eu/2013/12/17/softwares-projects-en/" }

    location "/drafts/*"    { directory auto index }
    location "/downloads/*" { directory auto index }

    location "*/feed/" { directory index atom.xml }

    location match "/2012/02/27/*"  { block return 301 "https://www.22decembre.eu/2015/03/31/5-sign-mail-fr/" }
}

server "photos.22decembre.eu" {
    listen on ::1   port 2001

    root "/photos.22decembre.eu"
    location "/.well-known/*"    { directory auto index }

    log error photos-error.log
    log access photos-access.log

    directory index index.php

    location "*.php" { fastcgi socket "/tmp/php.sock" }
}

server "blackblock.22decembre.eu" {
    listen on ::1 port 2002

    root "/blackblock.22decembre.eu"
    directory index index.html

    log error blackblock-error.log
    log access blackblock-access.log

    location "/.well-known/*"    { directory auto index }

    location "/links/"      { directory index index.php }

    location "*.php" { fastcgi socket "/tmp/php.sock" }
}

Alors oui, c'est un peu bordélique, mais bon…

Haproxy

Je mets ensuite toute la conf' tls dans haproxy et les redirections en https.

global
    log 127.0.0.1   daemon debug
    maxconn 1024
    chroot /var/haproxy
    daemon
    pidfile /var/run/haproxy.pid
    tune.ssl.default-dh-param 2048
    ssl-default-bind-options no-sslv3 no-tls-tickets
    ssl-default-bind-ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:!aNULL:!MD5:!DSS
    ssl-default-server-options no-sslv3 no-tls-tickets
    ssl-default-server-ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:!aNULL:!MD5:!DSS

defaults
    log     global
    mode http
    option forwardfor
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms
    option  httplog
    option  dontlognull
    option  redispatch
    retries 3
    maxconn 2000

########################

frontend https
    bind :::443 ssl crt /var/le/domains/www.22decembre.eu/current/full.pem crt /var/le/domains/photos.22decembre.eu/current/full.pem
    bind *:443 ssl crt /var/le/domains/www.22decembre.eu/current/full.pem crt /var/le/domains/photos.22decembre.eu/current/full.pem

    acl is_domain0 hdr_end(host) -i www.22decembre.eu
    acl is_domain1 hdr_end(host) -i photos.22decembre.eu
    acl is_domain2 hdr_end(host) -i blackblock.22decembre.eu

    acl is_domain9 hdr_end(host) -i lectures.22decembre.eu

    use_backend www if is_domain0
    use_backend photos if is_domain1
    use_backend blackblock if is_domain2

    use_backend lectures if is_domain9

frontend http
    bind *:80
    bind :::80

    acl is_domain0 hdr_end(host) -i www.22decembre.eu
    acl is_domain1 hdr_end(host) -i photos.22decembre.eu
    acl is_domain2 hdr_end(host) -i blackblock.22decembre.eu

    acl is_domain9 hdr_end(host) -i lectures.22decembre.eu

    use_backend www if is_domain0
    use_backend photos if is_domain1
    use_backend blackblock if is_domain2

    use_backend lectures if is_domain9

backend www
    server www ::1:2000
    redirect scheme https code 301 if !{ ssl_fc }
    http-response set-header Strict-Transport-Security "max-age=16000000; preload;"

backend photos
    server www ::1:2001
    redirect scheme https code 301 if !{ ssl_fc }
    http-response set-header Strict-Transport-Security "max-age=16000000; preload;"

backend blackblock
    server www ::1:2002
    redirect scheme https code 301 if !{ ssl_fc }
    http-response set-header Strict-Transport-Security "max-age=16000000; preload;"

backend lectures
    redirect location https://www.22decembre.eu/category/lectures.html code 301

Explications:

  • Dans ssl-default-bind-options et ssl-default-bind-ciphers, vous définissez votre conf' tls. La mienne est inspirée de https://cipherli.st/.
  • Avec acl is_domain1 hdr_end(host) -i www.22decembre.eu, je fais les redirections sur les hôtes virtuels du serveur web (httpd), qui doivent correspondre à un des backend définis juste en dessous.
  • Les attributs crt des lignes bind … ssl contiennent les noms de fichiers des certificats tls. Ces fichiers doivent contenir la chaîne complète, y compris la clé privée (cf la partie sur la génération des certificats).
  • redirect fait une redirection automatique en https si le visiteur se connecte en http simple.
  • http-response set-header Strict-Transport-Security indique que le site web supporte l'extension HSTS.

Ces deux dernières options doivent être sur les backend. En effet, si vous les mettez en option générique, alors vous ne pourrez jamais créer de nouveaux certificats: le client acme essayera de se connecter en https sur un site web qui ne fournit pas encore cette option, alors que c'est lui qui doit la lui fournir. Le problème de l'œuf et de la poule.

Au passage, vous constaterez que je fais une redirection avec mon ancien site web, lectures, que j'ai en fait intégré comme une catégorie du blog.

Créer un nouveau certificat

Ici, je décris la procédure pour créer un nouveau certificat. On va réutiliser certaines bases au dessus, mais il y a à faire soi-même aussi.

Il faut tout d'abord ajouter le nom dans votre domaine DNS. Ensuite de quoi ajouter un dossier avec le nom de domaine FQDN dans /var/le/domains/, et configurer le serveur web. L'hôte virtuel du serveur web est lui aussi normalisé : /var/www/FQDN. Le répertoire du serveur web doit contenir un dossier .well-known, dans lequel l'utilisateur le a le droit d'écrire, et l'utilisateur www le droit de lire et parcourir (autrement dit, lecture et execution). Enfin, les certificats doivent être mis en current directement, et mis en service.

DNS

Vous devez donc ajouter le nouveau nom dans votre zone DNS:

$ORIGIN 22decembre.eu.
$INCLUDE soa
@               IN      NS      blackblock.22decembre.eu.
@               IN      NS      ns6.gandi.net.
@               IN      MX 10   blackblock.22decembre.eu.

@               IN      TXT     "v=spf1 mx -all"

blackblock      IN      A       90.185.111.213
        IN      AAAA    2001:16d8:dd00:8207::0
        IN      AAAA    2001:16d8:dd00:207::2

www             IN      CNAME blackblock
photos          IN      CNAME blackblock
ntp             IN      CNAME blackblock
lectures        IN      CNAME blackblock
biblib          IN      CNAME blackblock
piwik           IN      CNAME blackblock

_keybase        IN TXT "keybase-site-verification=brQmXLHBZ1ZHELHYwuWWIshIQ-PTj1Q7Kj_W4vlmzWs"

selector1._domainkey IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOYPdaCG3yT4KKFmW6/CipMqAzE9t8Osusj7MxgER6/t5Q4ZLkAv/53H5GZHDDydYhABFBZF4S2kD/wZJel9aZ5XrvJnuwHzAAUpAYYrbte1q4LLPelsC+WyRaB9tb/nrbDK+k3/sEfydo9lDHVmq8JtsTmwVJWHnzD6NExNZNTwIDAQAB"

$INCLUDE latest.db
$INCLUDE current.db

Bon, je suppose que c'est assez transparent. Lorsque vous voulez un nouveau cert', vous ajoutez un CNAME et hop. Vous n'oubliez pas de resigner et recharger la zone.

Vous remarquerez les deux includes en bas. C'est bien pour dane.

Je mets aussi le SOA en include, que je partage entre toutes mes zones. Il faut être feignant à bon escient. Le dernier truc un peu étrange peut-être, c'est l'enregistrement domainkey. Je vous renvoie ici pour davantage d'info sur le sujet. Il y a des articles sur la toile sur DKIM, cherchez donc.

Serveur web

Créer le dossier du serveur web avec les bonnes permissions

$ cd /var/www
$ mkdir -p www.example.com/.well-known/
$ doas chown le:www www.example.com/.well-known/
$ doas chmod 750 www.example.com/.well-known/

La commande chmod n'est probablement pas nécessaire.

Conf' Httpd

server "www.example.com" {
    listen on ::1   port 2000

    root "/www.example.com"
    location "/.well-known/*"    { directory auto index }

    log error error.log
    log access access.log
}

Faîtes gaffe à

location "/.well-known/*"    { directory auto index }

Il me semble que c'est assez important (cas de debugging; si vous utilisez des scripts alors il faut bien signaler que ce répertoire est juste pour des fichiers, pas des scripts).

Haproxy

Ici, vous ajoutez un backend et une acl, comme indiqué au dessus. Lorsque vos certificats seront publiés, vous pourrez mettre aussi en place une redirection https et la directive hsts. Pas avant.

Générer le certificat

Pensez à créer le dossier dans le répertoire des domaines de le:

$ cd /var/le/domains
$ doas -u le mkdir www.example.com

On se lance:

$ doas -u le /var/le/generate www.example.com
$ cd /var/le/domains/www.example.com/

Propriété de root et lien en current, directement:

$ doas chown -R root 123456789
$ doas ln -s 123456789 current

Vous pouvez maintenant configurer vos serveurs logiciels pour utiliser le certificat current, puis les relancer. Vous pouvez aussi générer le TLSA :

$ doas /var/nsd/tlsa-gen current

Ce qui manque, ce qui pourrait être amélioré

Root

Il y a trop de choses faîtes par root. Ça c'est globalement pas super. En même temps, la localisation sur une seule machine oblige à verrouiller les permissions sur les fichiers et scripts impliqués (cf commentaire de Aeris).

Ainsi, c'est bien root qui doit générer les TLSA, puisque c'est lui le propriétaire et unique lecteur des certificats tls. Une solution serait de générer les TLSA au moment de la génération des certificats, mais cela pose la question de leur inclusion dans les zones DNS.

Vous voyez, chaque solution crée un nouveau problème. C'est la misère.

C'est aussi ça qui m'oblige à gérer Radicale à part, donc à mettre une rustine sur le processus automatique.

Automatisme

Les automatismes n'aiment pas les situations particulières. Tout ce qui sort de l'ordinaire est mauvais, puisqu'on a pas prévu le cas, donc on ne sait pas s'adapter (reprise du commentaire au sujet de Radicale).

Ainsi les scripts pour DANE/TLSA sont écrits avec un seul domaine en ligne de compte. Si vous avez deux domaines ou plus, alors c'est foutu, il vous faudra modifier vous même le script.

Optimisation

Je suppose qu'on pourrait grandement optimiser tout ce bordel, et en particulier demander moins de certificats (en mettant plusieurs noms sur les certificats). Là, j'ai pas d'idée.

Limite en nombre de certificats

Le processus régénère tous les certificats d'un seul coup. Ça signifie que vous ne pouvez pas avoir plus de cinq certificat par domaine (cf ce fil de discussion du forum de LE), ou alors il vous faut trouver une solution au problème signalé au dessus.

Ou alors à nouveau, il faut trouver un moyen d'échelonner les renouvellements semaine par semaine. Et là, chapeau si vous y arrivez !

Conf'

Je n'ai pas un seul fichier de configuration pour tout le schmilblik. Donc, si j'oublie un truc, une étape ou autre, alors il y a risque de plantage. De même, je n'ai pas prévu d'option pour le cas où on ne voudrait pas de DANE, pourtant ça, ça changerait tout (il suffit de modifier un des scripts, hein, c'est pas la mort quand même) !

Je suppose que la liste de TLSA à générer aurait été un bon endroit pour centraliser la configuration (on aurait la liste des certificats à générer, toutes les zones DNS à inclure et signer…), mais je pense que ça atteint un trop haut niveau de complexité pour moi.

Je pense que les problèmes précédents (automatisation, optimisation et limites en nombre de certificats) doivent être envisagés comme un problème global, donc trouver une solution systémique.

Surveillance

Le système n'est pas assez évolué pour faire lui-même ses diagnostics en cas de bug. C'est votre boulot de vérifier régulièrement qu'il n'y a en fait pas de problème. J'ai essayé d'éviter les problèmes, d'en limiter les effets, mais il reste forcement des trucs mal prévus.

Les tâches cron vous enverront leurs rapports par courriels, mais sinon ?

DNS, Httpd et Haproxy

C'est à vous de configurer et vérifier le bon fonctionnement de ces outils.

Par exemple, j'aurais pu écrire un script qui crée les bons dossiers et lance la génération des certificats lors chaque initialisation. Mais de toute façon, il faut quand même ajouter un enregistrement DNS, un serveur virtuel sur Httpd et Haproxy.

Le ménage

Rien ne fait le ménage ici. C'est à vous d'effacer les certificats usagés (je pense qu'il faudrait peut-être le faire un an après leur fin de validité).

Remarques

Cet article ainsi que les scripts qui l'accompagnent sont publiés sous licence CC By. Vous pouvez les utiliser, les améliorer, mais vous devez en tout cas fournir un lien vers cet article.

Ceci m'a également demandé énormément de travail. Grosso modo un mois et demi, avec des pauses pour les fêtes et tout, mais quand même. La version française compte 4590 mots, la version anglaise 3790.

Si vous avez des remarques ou des commentaires, si vous découvrez une faille ou pensez à une amélioration dans mes scripts, n'hésitez pas à m'écrire SVP.