Let's Encrypt et DNS challenge pour infrastructure AWS via Route53

Let's Encrypt et DNS challenge pour infrastructure AWS via Route53

Aujourd’hui, il est presque indispensable d’exposer les services de son application à travers le protocole sécurisé HTTPS. Tant pour les communications entre votre application et les utilisateurs que pour des communications entre services. Un exemple récemment rencontré lorsque vous souhaitez exploiter l’API de notification de Google Drive, le “webhook” de votre application doit forcément être exposé à travers https. Dans le cas d’un hébergement de son application chez le fournisseur AWS, vous pourrez mettre en place des certificats de manière triviale via Amazon Certificate Manager (ACM). Vous disposerez d’un ou plusieurs certificats via l’utilisation de la console ou de la CLI ainsi qu’une étape de validation humaine d’approbation à travers un workflow par email. Cette dernière phase peut représenter un handicap dans la mise en place d’automatisation. Pour information, vous trouverez d’autres limitations ici. Pour ces quelques raisons, nous allons étudier une alternative intéressante avec l’utilisation de Let’s Encrypt (LE).

Tout d’abord, je vous conseille la lecture du très bon article de Xebia sur la présentation du fonctionnement de cette autorité de certification. En très concis, l’obtention d’un certificat se fait par la réussite d’un challenge entre le service Let’s Encrypt (LE) et votre infrastructure, et cela soit via HTTP, soit via DNS. Cette dernière possibilité est clairement intéressante pour plusieurs raisons :

  • Vous n’avez pas forcément un unique serveur et par conséquent, exposer une information sur le protocole HTTP vous obligera peut être à mettre en place un mécanisme pour router spécifiquement la requête de challenge vers le bon serveur parmi le cluster.

  • Vous n’avez pas forcément la main au niveau système sur vos serveurs, souvent symptomatique des solutions (a)PaaS tel que Elastic Beanstalk.

Bref, un challenge DNS est tout compte fait plus simple à gérer que son alternative HTTP. Il vous faut juste avoir la main sur le composant technique DNS de votre infrastructure et vérifier que celui-ci dispose d’une API. Nous allons prendre l’architecture suivante (dessinée à l’aide de cloudcraft.co) pour expliquer le déroulement de l’obtention du certificat LE :

cloudcraft - WeResume (5) (1)

Ingrédients :

  • Un client pour l’exploitation de l’API  Let’s Encrypt
  • Un nom de domaine
  • Un client AWS CLI

1. Client Lets Encrypt

J’ai jeté mon dévolu sur ce client qui a l’avantage d’être extrêmement léger, en plus de bien faire le job :

git clone [https://github.com/lukas2511/letsencrypt.sh.git](https://github.com/lukas2511/letsencrypt.sh.git)  

2. Hook spécifique pour la plate-forme

Pour que le client précédent puisse jouer un challenge entre AWS Route53 et LE, il faut lui ajouter cette fonctionnalité à travers un “hook” adéquate:

git clone [https://gist.github.com/3b6760784c098c9139c6.git](https://gist.github.com/3b6760784c098c9139c6.git)  

Pour les dépendances il vous faudra peut-être les résoudre via :

sudo gem install domainatrix aws-sdk pry awesome_print  

3. Jouer la commande de challenge

./letsencrypt.sh --cron --domain app.example.com --hook ./hook.rb --challenge dns-01

Ici, nous souhaitons obtenir un certificat pour app.example.com via un challenge dns. Cette étape va créer une entrée dans Route53 et le client va ensuite transmettre les informations à LE pour que celui puisse vérifier la présence d’un enregistrement du type TXT nommé  _acme-challenge.app.example.com dont la valeur sera un token d’authentification.
Ci-dessous le résultat de la commande :

Screen Shot 2016-03-03 at 14.46.09

4. Upload du certificat sur le compte AWS**

Allez dans le répertoire certs/app.example.com contenant tous les certificats et lancez :

aws iam upload-server-certificate --server-certificate-name appexamplecom-le --certificate-body file://./cert.pem --private-key file://./privkey.pem --certificate-chain file://./chain.pem  

Attention à bien respecter la syntaxe “file://” au risque de vous retrouver avec un message d’erreur obscur vous indiquant que le certificat n’est pas valide.

5. Associer le certificat avec votre load balancer**

aws elb set-load-balancer-listener-ssl-certificate --load-balancer-name awseb-e-n-XXXXXXXXXXXXXX --load-balancer-port 443 --ssl-certificate-id arn:aws:iam::XXXXXX:server-certificate/appexamplecom-le  

Vous disposez maintenant d’une communication sécurisé HTTPS pour la communication avec votre application hébergée sur Elastic Beanstalk. Certes, l’opération est légèrement plus longue que l’utilisation directe de ACM mais vous bénéficiez d’un nombre de certificats disponibles par défaut plus important (100 au lieu de 20). Vous diminuez aussi le couplage avec AWS, ce qui peut être intéressant. Par ailleurs, vous pouvez développer vos propres hook pour vous adapter à votre infrastructure. Il en existe d’ailleurs quelques uns référencés ici.

Un point important concernant le certificat délivré par LE est sa durée de validité assez courte de 90 jours (13 mois pour ceux d’ACM). Par conséquent, Il est important d’en automatiser le renouvellement. Vous pourrez vous tourner vers une solution où ce processus est exécuté sur un AWS Lambda comme ici.