Notre gestion des mises à jour de sécurité Debian

Dans notre organisation interne à Unow, ce sont nous, l’équipe de développement, qui maintenons nous-mêmes les 7 serveurs dédiés hébergés chez Scaleway/Online permettant de faire tourner notre plateforme de formation.

Cela implique donc, entre autres de les maintenir à jour afin de ne pas exécuter de paquet avec une faille de sécurité connue (en effet, la sécurité est un processus, ce n’est ni un produit ni une réaction).

Nous allons donc voir ici comment nous gérons cette problématique. Les dépendances applicatives de nos projets ont un mécanisme de suivi des mises à jour complètement différent qui ne sera pas le sujet de cet article.

Le processus

Une tâche est lancée quotidiennement pour signaler les mises à jour de sécurité disponibles en fonction des paquets installés sur le serveur. Dans le cas où une ou plusieurs mises à jour sont détectées, un email est envoyé à l’équipe technique. La personne en charge du support ce jour-là est responsable de l’application des différentes mises à jour.

Mise en place de la cron

C’est donc une fois par jour, du lundi au vendredi, à 10h, que nous avons une ligne de commande qui tourne dans une cron, en root.

Celle-ci va exécuter un apt-get update afin de récupérer les dernières informations sur les paquets présents sur les dépôts.

Ensuite nous lançons un apt-get upgrade en mode dry run, afin de lister les paquets qui ont une mise à jour disponible. Cette commande va lister les mises à jour des paquets de toutes les sources, nous avons donc un grep sur “security” afin de ne lister que les paquets du dépôt security (cela pourrait être améliorable en ne passant pas par grep, mais fonctionne).

Nous générons ensuite la ligne de commande à exécuter afin de passer les mises à jour. Vu que nous écrivons celle-ci sur la sortie standard, et que nous avons correctement configuré l’envoi de mail (nous utilisons postfix en mode relayhost), le contenu de cette sortie est envoyé sur l’adresse mail configurée dans la variable d’environnement MAILTO (ici l’adresse commune à l’équipe de développement).

Voici ce que donne donc la cron en question :

00 10 * * 1-5 apt-get update > /dev/null && apt-get upgrade --dry-run | grep -i security | grep Inst && printf '\nsudo apt-get install --only-upgrade ' && apt-get upgrade --dry-run | grep -i security | grep Inst | awk '{print $2}' | paste -sd ' ' -

Et voici un exemple de courriel que nous recevons si un paquet doit être mis à jour :

Inst libssl1.1 [1.1.1n-0+deb10u2] (1.1.1n-0+deb10u3 Debian-Security:10/oldstable [amd64]) []
Inst openssl [1.1.1n-0+deb10u2] (1.1.1n-0+deb10u3 Debian-Security:10/oldstable [amd64]) []

sudo apt-get install --only-upgrade libssl1.1 openssl

Simplification passage de la mise à jour

Comme nous l’avons vu, nous générons une commande qui va faire un sudo apt-get install --only-upgrade suivi des noms des paquets à mettre à jour.

Lorsque nous nous connectons en SSH à nos serveurs, nous utilisons un user debuser afin de ne pas nous connecter directement en root. Nos clefs SSH y sont autorisées, il n’y a donc pas de mot de passe à saisir.

Afin de ne pas devoir saisir le mot de passe root à chaque passage des mises à jour, nous avons ajouté un fichier dans /etc/sudoers.d contenant cela :

debuser ALL=NOPASSWD: /usr/bin/apt-get install --only-upgrade *
debuser ALL=NOPASSWD: /usr/bin/apt install --only-upgrade *

Cela nous permet, avec notre user debuser d’appliquer les mises à jour (et seulement les mises à jour) sans saisie du mot de passe. C’est un risque que nous avons choisi de prendre : en effet si une personne a déjà réussi à se connecter en SSH avec notre utilisateur, nous avons déjà d’autres problèmes.

A propos de cette mise en place

La configuration de la cron et des sudoers se fait de manière quasi automatique et cela car nos serveurs sont provisionnés via Ansible : nous avons un rôle dédié aux mises à jour de sécurité qui s’en charge et qu’il suffit d’ajouter au playbook du serveur.

Application de la mise à jour

Chaque jour, une personne de l’équipe est dédiée au support.

Si un email de mise à jour de sécurité est reçu, cette personne devra analyser les différentes mises à jour afin d’en déduire certaines actions.

Pour cela nous utilisons des sites comme le tracker de security de Debian et le tracker de Debian des informations à propos de ces mises à jour.

Cette étape est nécessaire afin de bien comprendre l’impact de la mise à jour et permet de savoir si celle-ci sera transparente ou si elle nécessite le redémarrage du serveur ou d’un service.

Après avoir validé la mise à jour, nous l’appliquons ensuite tout d’abord sur notre environnement de staging, puis en production.

Un processus manuel

Vous aurez donc noté que le processus est manuel. Nous aurions pu tenter de l’automatiser : vu que l’on génère la commande à lancer pour appliquer les mises à jour, nous aurions potentiellement pu l’exécuter directement. Nous n’avons pas fait ce choix. En faisant ainsi, cela nous permet de conserver le contrôle sur le passage des mises à jour et permet d’appliquer des contrôles humains en amont.

De plus, le nombre de mises à jour reste très limité: cela varie en fonction des mois, mais à l’écriture de ces lignes, sur le dernier mois glissant, nous avons 5 jours sur lesquels une mise à jour a été nécessaire.

Conclusion

Voici donc notre organisation actuelle qui nous permet d’avoir connaissance d’un problème de sécurité lorsque celui-ci a un correctif présent dans les dépôts. A noter que, pour être informé plus tôt de potentiels problèmes d’infrastructure, nous avons aussi d’autres canaux (des mailing-lists, Twitter…) afin de nous tenir au courant. Au vu du nombre réduit de nos serveurs, ce processus nous convient jusqu’à présent très bien.