Table des matières
2023/03/20 (atelier) : Ansible
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 :
- snippet.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:
- snippet.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
:
- snippet.ini
vault_password_file = vault.key
Maintenant que tout est prêt, on peut créer notre premier vault:
- snippet.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:
- snippet.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:
- snippet.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 :
- snippet.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
:
- snippet.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:
- snippet.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
:
- snippet.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 :
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
- snippet.bash
gpg --send-keys <ID de la clé>
Ensuite, HgO a récupéré la clé via la commande
- snippet.bash
gpg --recv-keys <ID de la clé>
Et on accorde une confiance ultime à la clé de Célo:
- snippet.bash
$ gpg --edit-key <ID de la clé> > 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 <email de la clé de Célo>
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.
- snippet.bash
git pull
Ensuite, on fait
- snippet.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:
- snippet.bash
source .venv/bin/activate
On met à jour les dépendences via
- snippet.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:
- snippet.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:
- snippet.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 postgresdb pour les delegateto 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.