[Musique]
Bonjour à toutes et à tous, et bienvenue sur le podcast Yakafokon.
Yakafokon est un podcast traitant de la sécurité de l'information, et de son implantation, notamment dans les pratiques DevOps.
Je suis Florian Maury, et je bosse dans l'IT depuis 20 ans.
J'ai occupé tout plein de postes, de développeur à architecte système ou architecte réseau, et même auditeur en sécurité.
Je n'ai cependant que récemment embrassé les outils d'infrastructure codifiée et développé un système d'information dans sa globalité.
Je suis actuellement freelance, et ce podcast est une manière de partager mes connaissances et réflexions avec la communauté,
dans l'espoir d'initier des échanges constructifs et pourquoi pas faire évoluer la doctrine !
Côté philosophie, j'ai rapidement fait mienne l'idée que l'immuabilité est une propriété désirable pour une infrastructure.
Peut-être est-ce du à mes expériences en développement qui m'ont permis d'apprendre la valeur de cette propriété dans des languages comme Ocaml ou Rust.
Peut-être est-ce les mauvaises expériences que j'ai eu avec Ansible et les gestionnaires de configuration par mutation.
Dans ce premier épisode de Yakafokon, je vais donc vous partager mon expérience avec Ansible pour la configuration d'une infrastructure par mutation.
Cela servira de base pour la suite des discussions sur la pertinence de l'immuabilité, et les contraintes qui en découlent.
Ce podcast est chapitré, de façon à permettre aux auditeurs et auditrices de zapper les chapitres qui ne les intéressent pas.
Je vais commencer par rappeler ce qu'est Ansible. Il s'agit d'un outil de gestion de configuration.
Les configurations sont exprimées en YAML et consistent en une succession d'actions, appelées tâches, à effectuer sur le ou les machines cibles.
Chaque action consiste en l'appel d'un module avec des paramètres.
Les modules Ansible sont développés en Python. Il en existe une multitude qui sont fournis par Ansible ou téléchargeables.
Les différentes actions à réaliser peuvent être listées dans des rôles Ansible.
Ces rôles sont des collections d'actions réutilisables et paramétrables.
Des rôles sont publiés par la communauté sur des serveurs de distribution comme Ansible Galaxy, une sorte d'annuaires de rôles.
Ces rôles peuvent ensuite être énumérés dans un fichier appelé playbook, qui décrit l'ensemble des rôles et tâches s'appliquant pour la réalisation d'un objectif spécifique à ce playbook.
Passons maintenant aux problèmes que j'ai avec Ansible en tant qu'outil de gestion des configurations d'un parc de machines.
Le premier point, probablement l'un des plus problématiques en tant que freelancer et chef d'entreprise, est celui de la licence.
Ansible est publié sous licence GPL v3. Ses collections de modules sont publiées sous leurs propres licences, généralement GPL v3.
Certaines sont publiées sous des licences plus libres, comme MIT ou BSD.
Cet état de fait est déjà surprenant puisque certaines publiées sous des licences autres, utilisent en leur sein des bibliothèques issues du code source d'Ansible.
Elles devraient donc être contaminées par la GPL v3 et devraient être publiées également sous cette licence.
Le problème de la contamination de GPL v3 ne s'arrête cependant pas aux modules.
Ainsi, il n'est pas clair si les configurations décrites en YAML et interprétées par Ansible sont elles-mêmes contaminées par GPL v3.
Après tout, comme décrit précedemment, les modules sont appelés et paramétrés par la configuration.
Cela pourrait donc tomber sous le coup de la licence GPL v3, à l'image d'un appel de fonction d'une bibliothèque publiée sous cette licence.
Pour aller plus loin, des rôles publiés sur Ansible Galaxy sont eux-mêmes publiés sous une licence GPL v3.
En conséquence, faire usage de ces rôles dans un playbook pourrait contaminer le playbook.
En tant que développeur d'infrastructure codifiée, les playbooks et rôles que je pourrais développer pour ma société et que je pourrais ensuite revendre à mes clients,
courent le risque d'être contaminés par la GPL v3.
Il en résulterait alors une possible perte sèche de cet investissement, si mes clients décidaient de le publier librement sur Internet, comme le leur permet la licence !
Un autre problème d'Ansible, technique cette fois-ci, a rapport avec l'idempotence.
L'idempotence est la propriété de pouvoir exécuter plusieurs fois une même action et de toujours obtenir le même résultat ou état final.
L'exemple typique est celui d'une action de copie d'un fichier.
Copier plusieurs fois le même fichier au même endroit devrait toujours résulter en un fichier à l'endroit indiqué, avec le contenu prévu.
Ansible indique que la plupart des modules devraient avoir un comportement idempotent.
Le coeur du problème se situe dans cet emploi du conditionnel.
Il n'y a aucun engagem ent d'idempotence, et Ansible recommande même de "tester" pour savoir si une action est idempotente ou non, "en cas de doute".
En outre, l'idempotence d'Ansible se limite à ses modules.
Si ces modules installent des outils qui ne sont pas idempotents, par exemple l'utilitaire apt,
alors le résultat ne sera pas nécessairement identique.
Par exemple, apt installe, par défaut, la dernière version disponible d'un paquet Debian ; pas une version fixe.
Il est possible de forcer apt à installer une version spécifique, mais c'est souvent la recette pour des problèmes de dépendances cassées.
Pire, même si l'on utilise exclusivement des modules testés et dont on a pu confirmer l'idempotence, cela ne dit rien vis-à-vis de l'intégrité des modifications apportées par le playbook.
En cas d'incident, par exemple réseau, au milieu de l'exécution d'un playbook, la machine cible restera dans un état intermédiaire jusqu'à ce que l'incident soit terminé.
Certains systèmes de configuration utilisent une approche transactionnelle pour éviter ce genre d'écueil ;
la nouvelle configuration n'est appliquée qu'une fois que toutes les modifications programmées ont été effectuées.
C'est le cas, par exemple, de la distribution Suse Aeon, mais nous reviendrons ultérieurement dans ce podcast sur les distributions Linux dites "immuables".
En outre, et même en faisant abstraction de l'absence de promesse d'idempotence, Ansible n'a qu'une connaissance très partielle de l'état réel d'un système ;
il n'a connaissance que ce qui est décrit dans ses propres fichiers de configuration, et dans les faits qui sont récoltés pendant l'exécution du playbook.
Si des modifications parasites ont été effectuées manuellement, ou de manière automatisés par des composants système,
alors Ansible n'en saura rien, et n'y apportera aucune rémédiation, à moins qu'il s'agisse d'une ressource à laquelle le playbook a prévu d'apporter une modification ou d'en vérifier l'état.
Ansible n'est donc pas une solution viable pour prévenir les serveurs "flocons de neige" comme sont appelés les serveurs dont la configuration a dérivé de celle de l'outil d'infrastructure codifiée.
Finalement, le dernier point majeur me posant problème avec Ansible est la gestion des dépendences.
Ces dernières années, les attaques sur les chaines d'approvisionnement sont devenues un point de préoccupation majeur.
Ces attaques sont d'autant plus pertinentes que les systèmes d'information se complexifient et se densifient.
Il peut devenir de plus en plus difficile d'avoir un inventaire clair des logiciels utilisés dans une infrastructure.
Pour réduire les risques liés à ce type d'attaques, de nombreuses solutions ont été développées, à commencer par des inventaires des dépendances, avec un épinglage par numéros de version et par empreintes cryptographiques.
Des projets comme cosign ont également vu le jour afin d'apporter de la transparence sur les clés cryptographiques pouvant être employées pour signer des artefacts.
Ansible n'a pas du tout suivi ce chemin, et utilise encore un fichier requirements.yml pour référencer la liste des rôles et des collections de modules pouvant être utilisés dans un playbook.
Ce fichier ne contient que des numéros de version et il n'est pas possible d'épingler cryptographiquement une version, sauf à utiliser une syntaxe baroque d'URL git ;
au mieux, il existe un système de signatures GnuPG qui n'est fonctionnel qu'avec certains serveurs de distribution de roles et les collections, et notamment pas avec celui appelé Ansible Galaxy.
En outre, on sait que cette approche avec de simples signatures s'est déja révélée insuffisante dans d'autres dépots de code, que ce soit npm pour Javascript ou pypi pour Python.
Voilà. Je pense avoir fait le tour des problèmes que je vois à l'utilisation d'Ansible dans une infrastructure codifiée.
Pour le résumer un peu brutalement, on ne sait pas ce qu'on utilise, on ne sait pas vraiment ce qui sera fait, et en plus, on peut être contraint de publier son code sous GPL v3 pour de sombres histoires de licence !
Alors peut-être que certaines ou certains me diront : "fort bien, et on utilise quoi du coup ? Salt Stack, Chef, Puppet, ou que sais-je ?"
Eh bien, non. Cela ne résoud pas le problème et cela reste des outils de configuration par mutation.
Dans le prochain épisode de ce podcast, je vous présenterai la solution que je privilégie pour l'heure : ignition et la distribution Linux Fedora Core OS.
Les épisodes suivants seront consacrés aux sauvegardes, et à la gestion des secrets.
En attendant ces prochains épisodes, n'hésitez pas à réagir et à commenter celui-ci ;
vous pouvez le faire depuis n'importe quel compte sur le fédiverse.
C'est mon premier podcast maison ; il y a surement des trucs à améliorer. Alors, à vos claviers ! Et merci pour votre écoute.
À bientôt.