# 2023/03/20 (atelier) : Ansible * [Réunion précédente](https://doc.neutrinet.be/atelier-ansible-2022-11-11) * [Pad de la réunion](https://doc.neutrinet.be/atelier-ansible-2023-03-20#) Présences : - HgO - Célo ## Météo //Moment informel durant lequel on exprime **en peu de mots** comment on se sent et si on a une attente forte pour la réunion.// //**Ce n'est pas un moment de discussion mais d'expression individuelle et ce n'est pas obligatoire :-)**// ### Attente(s) forte(s) //Si l'une ou l'autre personne exprime une attente forte, merci de vous en occuper en priorité ou de la noter dans le hub ou dans un point approprié//. Fin: 17h ## Secrets Les secrets sont des mots de passes, des identifiants, mais ça peut aussi être des données sensibles. C'est pourquoi on parle de secret et pas uniquement de mots de passe. ### Qu'est qu'un vault ? Un vault signifie "coffre fort" en Anglais. On va stocker les données dans un coffre. En informatique, c'est un conteneur chiffré. Il y a des vault sous Linux qui permettent par exemple de chiffrer tout un dossier. Dans ansible, cela se représente comme un fichier de variables mais chiffré. Par exemple: ``` $ANSIBLE_VAULT;1.1;AES256 34373066383437646132363336313664313232626234313736653361343034653737336166333934 3739376237366164343736396663636534373234386261330a653639626235326534623362326231 65303864366238333833663335616330343433353539646634383561366565303432663232373336 3365626239346363610a343065636539613164613735393037333431613164363134343864313234 30303965306133646235316631646330366335653639613031666562333130356532636335303032 36656465343237373764323763313530306266363464643837333639336138616566626363643731 61396462363733633263633532366635616365333931643263636332316565653830306262636533 33306435346463383639356666336561353736366363363533646464386634346137353266613564 33663065623930356138386466653536313334643665326133346632653463613630613137623737 36363739323537313265386630663432386166623263303635383438656264363161336465363731 31353563623164626566613631376436646164663564316539613933383330663164613931633336 62343261343464323436663535333331366532306435353539613161326263353765346436646633 6361 ``` On peut aussi définir un vault au niveau d'une variable ansible. Par exemple, pour le rôle let's encrypt : ```yaml letsencrypt_dns_gandi_api_key: !vault | $ANSIBLE_VAULT;1.1;AES256 37623065386338343831383566336134303861396663666631656563633730613434633231343336 3132646565373162613537646538353933363161363036650a343634633932373362336134636139 34313539353938393164353034653366303664613332333038663266656466323265303130333035 3430613234383662640a313864386230646137383637343263356236633434356335383335353935 64623839396433346235383264613534383130386433363931306662663063306665 ``` Dans Ansible, on a en général un fichier qui contient tous les secrets. C'est alors chiffré au niveau d'un fichier et pas par variable. En général, c'est mieux supporté par les logiciels tiers (AWX, les linters, etc). Chez Neutrinet, on suit en général cela. Pour let's Encrypt, on a besoin d'un vault dans les variables du rôle parce qu'on a besoin de la clé d'API pour tester le rôle dans molécule. C'est un peu plus complexe d'avoir un fichier vault avec molécule, et cela pourrait poser des problèmes lorsque d'autres rôles feront appel au rôle qui contient le fichier vault. ### Comment fonctionne le chiffrement des secrets ? Qui dit chiffrement dit clés de chiffrement. Dans les exemples ci-dessus, c'est l'alogithme AES256 qui est utilisé. La clé de chiffrement se trouve dans un fichier qui est défini dans la config d'Ansible `ansible.cfg`: ```ìni vault_password_file = vault.key ``` On a donc une clé de chiffrement, Ansible sait où elle se trouve et ne fait que l'utiliser pour déchiffrer. Pour l'utilisateurice c'est transparant. C'est du chiffrement symétrique, donc on a qu'une seule clé pour le chiffrement et le déchiffrement. Pour plus d'infos, voir la doc https://docs.ansible.com/ansible/latest/vault_guide/index.html ### Où placer les secrets ? On en a déjà un peu parlé. On les stock dans un fichier des variables du playbook ou de l'inventaire. Chez Neutrinet, on les places dans un fichier vault.yml au côté du fichier vars.yml. Donc ça donne par exemple: `inventories/group_vars/all/vault.yml` ### Utilisation d'ansible-vault ansible-vault est la commande qui permet de gérer les vault, et donc de chiffrer ou déchiffrer un fichier de variables. ansible-vault peut soit juste regarder dedans, soit le déchiffrer complétement. Pour utiliser la commande, il faut rester à la racine du repo ansible, car il va aller chercher la clé de chiffrement dans le fichier ansible.cfg Avec ```ansible-vault help``` on peut voir toutes les commandes possibles. On va d'abord crée un dossier dans les variables de l'inventaire: ``` mkdir inventories/group_vars/all ``` Et ensuite on déplace le fichier `inventories/group_vars/all.yml` vers `inventories/group_vars/all/vars.yml`. Ainsi on pourra placer le fichier vault à côté du fichier de variables. On va générer une clé de chiffrement, ça peut n'importe quoi. On la génère avec openssl: ```bash openssl rand -base64 -out vault.key 48 ``` Openssl a un module rand auquel on peut indiquer la taille en bits. Avec l'option base64, tout est encodé en base64, mais on pourrait aussi avoir un fichier binaire si on le voulait (ansible le supporte sans problème). Attention aux permissions quand a créé la clé de chiffrement ! Par défaut, elle est accessible en lecture pour tout le monde. Ici on s'en fiche comme c'est un test. On va rajouter le nom du fichier contenant la clé de chiffrement dans le fichier de config d'Ansible, dans la section `defaults` : ```ini vault_password_file = vault.key ``` Maintenant que tout est prêt, on peut créer notre premier vault: ```bash ansible-vault create inventories/group_vars/all/vault.yml ``` Un éditeur s'ouvre. On peut écrire dedans mais par défaut, c'est vi qui est utilisé. Sous Manjaro, il faut préciser que c'est vim que l'on veut, et pas vi… On peut choisir l'éditeur avec: ```bash EDITOR=vim ansible-vault create inventories/group_vars/all/vault.yml ``` On peut mettre cette variable dans notre .bashrc pour ne pas devoir repréciser ceci par la suite. Il y a une convention pour les variables qui sont des vault dans Ansible. On met un préfixe `vault_` dans le nom des variables, cela permet que quand on utilise ces variables, c'est clair pour le lecteur que c'est un secret. Comme ce n'est rien d'autre qu'un fichier de variables, c'est du YAML, donc on met quelque chose comme: ```yaml vault_super_secret: neutrinet ``` Si on fait un cat du fichier créé, le fichier ressemble aux exemples ci-dessus. C'est illisible... Si on veut le lire, il faut utiliser ansible-vault view : ```bash EDITOR=vim ansible-vault view inventories/group_vars/all/vault.yml ``` Si jamais on veut changer le contenu du vault, il suffit d'utiliser la sous-commande `edit`: ```bash EDITOR=vim ansible-vault view inventories/group_vars/all/vault.yml ``` On peut mettre autant de secrets / variables que l'on veut dans le même fichier vault. Si on veut déchiffrer un fichier vault, il suffit de faire: ```bash EDITOR=vim ansible-vault decrypt inventories/group_vars/all/vault.yml ``` On peut faire un cat, et on voit bien que le fichier est désormais en clair. Enfin, on peut chiffrer un fichier (n'import lequel, même un simple fichier texte), avec la sous-commande `encrypt`: ```bash EDITOR=vim ansible-vault encrypt inventories/group_vars/all/vault.yml ``` On remarque que le résultat est différent du premier chiffrement, même si le contenu n'a pas changé. C'est normal, c'est dû au salt du chiffrement, mais on entrera pas dans le détail ici. ### Comment garder la clé de chiffrement secrète ? Pour l'instant, on a créé une clé de chiffrement, que l'on a mis dans un fichier en clair. Mais ici, on est sur un repo git public, donc comment faire pour la publier sur le repo git sans qu'elle soit accessible à tout un chacun ? On va utiliser git-secret pour chiffrer la clé sur le repo git, et gpg pour se partager les accès \o/ ## GPG ### Comment créer une clé GPG On trouve plusieurs tutoriels. Quelques exemples qui sont très complets : - https://mikeross.xyz/create-gpg-key-pair-with-subkeys/ - https://alexcabal.com/creating-the-perfect-gpg-keypair L'idée c'est d'avoir plusieurs clés : une master ou primary, qui permet de créer des sous-clés. C'est exactement le même principe que le CA pour les certificats. Lors qu'on crée cette clé, on lui donne des autorisations comme celle de chiffrer. ### Ajout de la clé GPG de Célo On a créé une clé GPG pour Célo en suivant le tutoriel de Mike Ross. On l'a publié sur un serveur de clé via la commande ```bash gpg --send-keys ``` Ensuite, HgO a récupéré la clé via la commande ```bash gpg --recv-keys ``` Et on accorde une confiance ultime à la clé de Célo: ```bash $ gpg --edit-key > trust > 5 ``` Maintenant, il ne reste plus qu'à rajouter la clé avec git-secret. Pour ce faire, il faut installer git-secret, cf. le site web du logiciel.. qui est down :( Bon, en général il y a un package qui existe, sous Manjaro en tout cas il y a un AUR :) Pour rajouter la clé de Célo, il faut faire: ``` git-secret tell ``` On voit que git-secret a modifié le dossier `.gitsecret` en rajoutant la clé publique de Célo. De son côté, Célo récupère le repo git une fois que les changements sont mergés. ```bash git pull ``` Ensuite, on fait ```bash git-secret reveal ``` Mais cela ne marche pas... À suivre Du coup Célo a récupéré le fichier contenant la clé de chiffrement des vaults directement sur une clé USB. Une fois copié dans le projet Ansible, il faut lui donner les bonnes permissions avec : ``` chmod 0640 vault.key ``` TODO: Comprendre pourquoi git-secret n'aime pas Célo ### Résumé On a un fichier vault.key.secret qui est chiffré avec la clé GPG publique de chaque participant. Ce fichier est envoyé sur le repo git, et est donc accessible publiquement. Mais comme ce fichier est chiffré, ce n'est pas un problème. Ensuite, chaque participant déchiffre localement le fichier vault.key.secret. On obtient ainsi la clé de chiffrement dans vault.key. Enfin, ansible utilise vault.key pour déchiffrer ses vaults. ## Playbook Mobilizon Avant de commencer, on active le virtual env de python: ```bash source .venv/bin/activate ``` On met à jour les dépendences via ```bash pip install -U -r requirements.txt ``` On met aussi à jour les plugins de vagrant: ``` vagrant plugin update ``` On récupère les derniers changements qui ont été fait sur la branche main: ``` git pull origin main ``` ### Review du playbook On a mis certaines valeurs dans des variables. ### Test du playbook On lance le playbook converge de molecule: ```bash molecule converge ``` On remarque que pour l'extension postgis pour PostgreSQL qui est nécessaire à Mobilizon, il faut installer le package suivant: ``` postgresql-13-postgis ``` Cependant, cela doit être installé sur chaque serveur postgresql quand on est en production, et sur la VM de molecule quand on est en local. Donc pour ça, on utilise l'option `delegate_to` pour dire à molecule d'exécuter la tâche sur le bon serveur. Ensuite, on active les extensions PostgreSQL: ```yaml - name: Ajout des extensions nécessaires à postgresql community.postgresql.postgresql_ext: name: "{{ extensions }}" db: "{{ mobilizon_owner }}" loop: - postgis - pg_trgm - unaccent loop_control: loop_var: extensions become_user: postgres delegate_to: "{{ postgresql_patroni_primary_host | default(inventory_hostname) }}" ``` On rajoute une étape pour créer / migrer la base de données de Mobilizon. On doit encore rajouter des handlers pour dire à ansible de redémarrer Mobilizon lorsque sa config change ou lorsque la base de données. Par contre, le playbook n'est pas idempotent : d'une part il télécharge la même version de Mobilizon à chaque fois qu'on lance le playbook, et la tâche apparaît comme modifiée... D'autre part, la migration de la db ne devrait s'exécuter que lorsqu'on met à jour ou qu'on installe Mobilizon pour la première fois. Lors du téléchargement, on dit au module unarchive de ne pas télécharger Mobilizon si le binaire bin/mobilizon existe déjà. TODO: Déclencher la migration de la db uniquement lorsque la version de Mobilizon a changé TODO: Installer la dépendence postgresql pour l'extension postgis. Voir le rôle postgres_db pour les delegate_to TODO: Voir si avoir un lien symbolique serait pertinent TODO: Tester le redémarrage de la VM ### Monitoring - Voir si on peut récupérer des metrics de Mobilizon (bonus) ### Backups - Mettre en place les backups de la db et des données de Mobilizon ### HAProxy - Configurer HAProxy pour pouvoir tester en local - Configurer le HAProxy de Neutrinet ## Prochaine réunion Prochain atelier Ansible : 24/04 Review du playbook Mobilizon et préparation pour la migration Lieu : Chez Célo (Crainhem) ## Météo de fin //Moment informel durant lequel on exprime **en peu de mots** comment, à titre personnel, la réunion a été vécue que ce soit positif ou négatif.// //Si une ou plusieurs **tension est née** durant la réunion, il est peut-être nécessaire d'envisager l'une ou l'autre réunion pour y remédier.// {{tag>infra atelier}}