From 3627de3afe48a4938db0035279f488ea59500b2b Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Fri, 5 May 2023 09:57:22 +0200 Subject: [PATCH] Add latest tutorial revision --- tutorial/ansible/Makefile | 9 +- tutorial/ansible/ansible-advanced.md | 32 ++++ tutorial/ansible/ansible-inventory.png | Bin 0 -> 46931 bytes tutorial/ansible/ansible.md | 207 +++++++++++++++++++------ tutorial/ansible/project.md | 70 +++++++++ tutorial/ansible/rendu-5.md | 42 +++++ tutorial/ansible/rendu.md | 115 +++----------- tutorial/ansible/tutorial-5.md | 16 ++ tutorial/ansible/tutorial.md | 21 +-- 9 files changed, 348 insertions(+), 164 deletions(-) create mode 100644 tutorial/ansible/ansible-advanced.md create mode 100644 tutorial/ansible/ansible-inventory.png create mode 100644 tutorial/ansible/project.md create mode 100644 tutorial/ansible/rendu-5.md create mode 100644 tutorial/ansible/tutorial-5.md diff --git a/tutorial/ansible/Makefile b/tutorial/ansible/Makefile index 8e3c633..679a215 100644 --- a/tutorial/ansible/Makefile +++ b/tutorial/ansible/Makefile @@ -1,15 +1,18 @@ include ../pandoc-opts.mk SOURCES_2 = tutorial-2.md setup.md maatma.md what.md netfilter.md anssi.md vitrine.md nameserver.md nameserver-anssi.md nameserver-troubleshooting.md -SOURCES_ANSIBLE = tutorial.md ansible.md deploiement-svc.md rendu.md +SOURCES_ANSIBLE = tutorial.md ansible.md rendu.md +PROJECT = project.md -all: tutorial-2.pdf tutorial-ansible.pdf +all: tutorial-2.pdf tutorial-ansible.pdf project.pdf tutorial-2.pdf: ${SOURCES_2} pandoc ${PANDOCOPTS} -o $@ $+ tutorial-ansible.pdf: ${SOURCES_ANSIBLE} pandoc ${PANDOCOPTS} -o $@ $+ +project.pdf: ${PROJECT} + pandoc ${PANDOCOPTS} -o $@ $+ clean:: - rm tutorial-2.pdf tutorial-ansible.pdf + rm tutorial-2.pdf tutorial-ansible.pdf project.pdf diff --git a/tutorial/ansible/ansible-advanced.md b/tutorial/ansible/ansible-advanced.md new file mode 100644 index 0000000..6599789 --- /dev/null +++ b/tutorial/ansible/ansible-advanced.md @@ -0,0 +1,32 @@ +\newpage + +Mieux utiliser Ansible +====================== + +Nous savons maintenant utiliser `ansible` et tirer parti des *playbooks* pour automatiser l'installation et la configuration de nos machines. + +Nous avons vu toute la puissance des *playbooks* : en automatisant les tâches d'administration de nos machines, on réduit les risques d'erreurs humaines, tout en écartant les tâches répétitives de mise à jour, ... Néanmoins, nos *playbooks* peuvent devenir rapidement redondant (peut-être avez-vous géré l'ouverture des ports du pare-feu dans chaque *playbooks* : 80 et 443 dans le playbook `vitrine.yml` et 53 dans le *playbook* `nameserver.yml` ?). + +Nous allons maintenant voir les roles Ansible qui résolvent ce problème en proposant un moyen standardisé et organisé de décomposer les tâches en composants plus petits et réutilisables. + + +Apprivoiser les rôles +--------------------- + +Les rôles Ansible sont un concept clef d'Ansible, conçus pour rationaliser et organiser nos configurations. Il s'agit d'avoir une approche modulaire : de la même manière que l'on essaie de factoriser les parties redondantes lorsque l'on programme une fonction, les rôles vont nous permettre de réutiliser des briques de configuration entre plusieurs *playbooks*. + +Concrètement, les rôles Ansible regroupent un ensemble de tâches, *handlers*, variables, fichiers/modèles. En les concevant correctement, on peut aisément les partager entre différents projets. + + + +### Structure d'un rôle + + +### Utilisation d'un rôle + + +### + + +Bonnes pratiques +================ diff --git a/tutorial/ansible/ansible-inventory.png b/tutorial/ansible/ansible-inventory.png new file mode 100644 index 0000000000000000000000000000000000000000..66cea09db55c8464d52cb87fc391d1417468a85b GIT binary patch literal 46931 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.\ + - `securing.yml`, accompagné de toutes ses dépendances : ce *playbook* doit + s'occuper de toute l'installation de la machine pour qu'elle soit aussi + sécurisée que possible. + + - `vitrine.yml` et ses dépendances : celui-ci + doit permettre de déployer une page vitrine typique d'une entreprise. Cette + page doit être accessible depuis votre domaine + . + + - `name-server.yml` et ses dépendances : celui-ci doit mettre en place le + serveur DNS faisant autorité sur le domaine qui vous est concédé. ::::: {.warning} @@ -96,14 +106,15 @@ Plus tard, c'est dans ce fichier que vous pourrez créer des groupes de machines (pour, par exemple, regrouper les serveurs web, les bases de données, etc.) ou donner des caractéristiques spécifiques à vos machines. +[Plus d'infos sur le fichier d'inventaire par ici.](https://docs.ansible.com/ansible/latest/inventory_guide/index.html) ### `ping` -Lancez ensuite la commande suivante : +Lançons maintenant la commande suivante :
    ``` -42sh$ ansible --inventory-file hosts all --module-name ping --user root +42sh$ ansible --inventory-file hosts all --user root --module-name ping 192.168.0.106 | SUCCESS => { "changed": false, "ping": "pong" @@ -111,9 +122,11 @@ Lancez ensuite la commande suivante : ```
    +Nous demandons avec cette commande, qu'`ansible` utilise le fichier d'inventaire `hosts` ; `all` est un filtre qui nous permet d'indiquer les machines auxquelles on souhaite se restreindre (`all`, on va lancer le module sur toutes les machines de l'inventaire). L'option `--user` précise le nom de l'utilisateur que l'on veut utiliser pour la connexion SSH. Enfin nous avons les options du modules, et cela commence par le nom du module lui-même. + Vous devriez avoir un retour similaire à celui-ci, indiquant simplement que la -connexion a bien été effectuée et que le nécessaire est bien installé sur la -machine distance.\ +connexion a bien été effectuée et que le nécessaire pour utiliser Ansible est +bien installé sur la machine distance.\ ::::: {.question} @@ -123,26 +136,114 @@ compte, sinon vous obtiendrez une erreur plutôt incompréhensible. ::::: +En ajoutant une seconde machine dans notre inventaire, nous aurions quelque chose comme cela : + +
    +``` +42sh$ ansible --inventory-file hosts all --user root --module-name ping +192.168.0.106 | SUCCESS => { + "changed": false, + "ping": "pong" +} +192.168.0.142 | SUCCESS => { + "changed": false, + "ping": "pong" +} +``` +
    + + ### Confort -Une des premières choses que nous devrions faire, est d'installer notre clef -SSH sur les machines, pour éviter d'avoir à taper le mot de passe à chaque -test. +Une des premières choses que nous devrions faire, est de nous créer un +utilisateur puis d'installer notre clef SSH sur les machines, pour éviter +d'avoir à taper le mot de passe à chaque test. -Si vous avez bien suivi jusqu'ici, vous savez qu'il ne faut pas utiliser le -compte `root` directement ! Pas d'inquiétude, tout est prévu dans Ansible : -retirer l'option `--user root` si votre nom d'utilisateur local est identique -que celui dans la machine virtuelle, ou adaptez l'option en conséquence. +Pour créer notre utilisateur, nous pouvons utiliser le [module `user`](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/user_module.html) : -Et ajoutez les options `--become` et `--ask-become-pass` (utilisez `--sudo` et +
    +``` +42sh$ ansible --inventory-file hosts all --user root --module-name user --args "name=login_x uid=1042" +192.168.0.106 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/bin/python3" + }, + "append": false, + "changed": true, + "comment": "", + "group": 1001, + "home": "/home/login_x", + "move_home": false, + "name": "login_x", + "shell": "/bin/sh", + "state": "present", + "uid": 1042 +} +``` +
    + +On voit que le retour de notre commande est bien différent (ne serait-ce que la +couleur du texte !). En particulier, on peut constater sur la première ligne de +sortie standard `CHANGED` au lieu de `SUCCESS` précédemment. + +En fait notre utilisateur vient d'être créé, Ansible rapporte qu'il a apporté +une modification au système cible. Si l'on renvoie exactement la même commande : + +
    +``` +42sh$ ansible --inventory-file hosts all --user root --module-name user --args "name=login_x uid=1042" +192.168.0.106 | SUCCESS => { +[...] +``` +
    + +Aucun changement, l'utilisateur est déjà créé et possède ces attributs, Ansible +rapporte qu'il n'y a pas eu d'altération.\ + + +Maintenant que notre utilisateur est créé, nous pouvons lui ajouter notre clef SSH. Pour cela, on utilisera le [module `authorized_key`](https://docs.ansible.com/ansible/latest/collections/ansible/posix/authorized_key_module.html) : + +
    +``` +ansible --inventory-file hosts all --module-name authorized_key --args "user=login_x key='ssh-ed25519 AAAAC3NzaC1lZD...FD'" +``` +
    + +Notez que j'ai maintenant arrêté d'utilisé l'option `--user root`, puisque je peux me connecter avec l'utilisateur que j'ai créé. Sans préciser, le nom d'utilisateur de votre compte est utilisé pour établir les connexions. + +::::: {.exercice} + +Pour continuer, il va nous falloir installer `sudo` (en `root`), ajouter notre utilisateur au groupe `sudo` et éventuellement configurer le fichier `sudoers` pour accepter que l'on puisse lancer des commandes sans utiliser de mot de passe. +Vous pourrez faire tout cela avec les modules : + + - [`apt`](https://docs.ansible.com/ansible/2.10/collections/ansible/builtin/apt_module.html) + - [`user`](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/user_module.html) + - [`lineinfile`](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/lineinfile_module.html) + +::::: + + +## Utiliser `sudo` + +Après avoir installé et configuré `sudo`, voyons comment l'utiliser avec Ansible. + +Ansible peut utiliser différents programme pour élever ses privilèges (pas seulement `sudo`) ; il va détecter de lui-même quel programme utiliser. + +Il faudra cependant lui indiquer que l'on souhaite qu'il élève ses privilège +juste après la connexion en tant que simple utilisateur. On ajoute pour cela +les options `--become` et `--ask-become-pass` (utilisez `--sudo` et `--ask-sudo-pass` pour les vieilles versions) :
    ```bash -ansible --inventory-file hosts all -m ping -u bruce --become --ask-become-pass +ansible --inventory-file hosts all -m ping -u login_x --become --ask-become-pass ```
    +L'option `--ask-become-pass` vous demandera systématiquement le mot de passe *sudoer*, avant d'établir la connexion. + +Maintenant que l'on sait se connecter proprement, essayons d'en apprendre un peu plus sur les modules. + ### Les modules @@ -164,7 +265,7 @@ exister. À l'application de cette nouvelle recette, si un tel utilisateur est trouvé, il sera donc supprimé. -### Collecte ~~du lundi~~ d'informations +### Collecte d'informations Parmi les modules de base, le module `setup` permet de récupérer un grand nombre de caractéristiques de la machine distance, voyez plutôt : @@ -178,8 +279,8 @@ ansible -i hosts all -m setup Les informations récupérées (quel que soit le module), sont ensuite accessibles dans des variables afin de permettre de compléter des modèles ou pour faire de l'exécution conditionnelle d'état (par exemple on pourra utiliser la variable -`ansible_facts.ansible_distribution` pour distinguer les gestionnaires de -paquets). +`ansible_distribution` pour distinguer les gestionnaires de paquets à utiliser +selon la distribution de la machine). Ma première recette @@ -219,7 +320,7 @@ décrit les tâches. Le guide de référence pour connaître toutes les syntaxes possibles est disponible dans [la documentation -d'Ansible](http://docs.ansible.com/ansible/latest/playbooks.html). +d'Ansible](https://docs.ansible.com/ansible/latest/playbooks.html). ### Exécution d'un *Playbook* @@ -247,7 +348,7 @@ Voici à quoi ressemblerait votre premier playbook créant l'utilisateur tasks: - name: ensure adeline as an account - user: + ansible.builtin.user: name: adeline state: present shell: /bin/fish @@ -256,8 +357,7 @@ Voici à quoi ressemblerait votre premier playbook créant l'utilisateur ``` -La création de l'utilisateur se fait à l'aide du module -[`user`](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/user_module.html). +::::: {.exercice} À vous maintenant, à l'aide [des collections de modules à votre disposition](https://docs.ansible.com/ansible/latest/collections/index.html) @@ -265,6 +365,8 @@ de copier vos fichiers de configuration à leur place et avec les bons droits (`authorized_keys`, `.bashrc`, ...). Installez également les paquets que vous aviez installés à la main (client DHCP, `htop`, ...). +::::: + Les notifications ----------------- @@ -303,16 +405,23 @@ Voir [la documentation](https://docs.ansible.com/ansible/latest/user_guide/playbooks_handlers.html) pour davantage de détails et d'exemples. + +::::: {.exercice} + La configuration de votre serveur SSH laisse à désirer. Corriger les problèmes -énoncés par ces deux articles : +énoncés par ces guides et articles : -  ; -  ; - . -Mettez en place un *handler* pour relancer votre serveur SSH en cas de +Pour modifier un fichier de configuration, on utilise généralement le module [`ansible.builtin.lineinfile`](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/lineinfile_module.html). + +Puis, mettez en place un *handler* pour relancer votre serveur SSH en cas de modification de sa configuration. +::::: + Les variables ------------- @@ -363,7 +472,7 @@ Ces variables peuvent être placées dans un fichier, pour plus de lisibilité  ```yaml - hosts: webservers vars_files: - - /vars/webservers_common.yml + - vars/webservers_common.yml ``` @@ -382,7 +491,7 @@ https_port: 443 #### Modèles Ces variables peuvent être utilisées pour remplir un emplacement de texte dans -un modèle. Ansible utilise [Jinja2](http://jinja.pocoo.org/) comme moteur de +un modèle. Ansible utilise [Jinja2](https://jinja.pocoo.org/) comme moteur de template, un format très courant dans le milieu du développement Python.
    @@ -424,8 +533,8 @@ Jinja2 : ```yaml - hosts: webservers vars_files: - - /vars/webservers_common.yml - - /vars/webservers_{{ ansible_os_family }}.yml + - vars/webservers_common.yml + - vars/webservers_{{ ansible_os_family }}.yml ```
    @@ -451,4 +560,4 @@ tasks: Vous trouverez bien d'autres cas d'utilisation dans [la -documentation](http://docs.ansible.com/ansible/latest/playbooks_conditionals.html). +documentation](https://docs.ansible.com/ansible/latest/playbooks_conditionals.html). diff --git a/tutorial/ansible/project.md b/tutorial/ansible/project.md new file mode 100644 index 0000000..85b22fe --- /dev/null +++ b/tutorial/ansible/project.md @@ -0,0 +1,70 @@ +--- +title: Administration Linux avancée -- Projet +author: Pierre-Olivier *nemunaire* [Mercier]{.smallcaps} +institute: EPITA +date: Jeudi 13 avril 2023 +abstract: | + Nous allons maintenant développer nos savoirs et connaissances + d'Ansible en faisant le tour de quelques bonnes pratiques et en les + appliquant à nos actuels playbooks. + + \vspace{1em} + + Ce projet est à rendre pour le + **dimanche 30 avril 2023 à 23 h 42**. +... + +\ + +En prenant appui sur la base des *playbooks* que vous avez commencés durant les précédents TP, vous devez fiabiliser votre travail et appliquer un certain nombre de [bonnes pratiques courantes](https://docs.ansible.com/ansible/2.8/user_guide/playbooks_best_practices.html).\ + + +Éléments supplémentaires +======================== + +Par rapport au sujet précédent, vous devez : + +* Faire usage des [rôles Ansible](https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_reuse_roles.html) autant que possible : que ce soit les votres dans un dossier `roles` ou la [communauté](https://galaxy.ansible.com/). À ce stade, sont au moins attendu sous forme de rôle : le pare-feu, l'installation et la configuration des serveurs installés, la gestion des certificat (idéalement vos *playbook* ne devraient qu'appeler des rôles, avec les bonnes variables).\ + +* Le *playbook* `name-server.yml` doit également installer et configurer [happyDomain](https://www.happydomain.org/fr/) au moyen de la [collection Ansible mise à disposition par le projet](https://galaxy.ansible.com/happydns/happydomain) (sans Docker, en écoute sur tous les ports 8081, selon la configuration par défaut, pensez à ouvrir le port du pare-feu).\ + +* Le contenu de votre clef SSH publique doit se trouver dans la variable `ssh_key`. Cette variable doit avoir une précédence lui permettant de pouvoir être écrasée par une surcharge sur la ligne de commande (`ansible-playbook -e ssh_key="ssh-ed25519 ABCDEF..."`). Votre clef DOIT bien être présente dans une variable et être utilisée si la variable n'est pas précisée sur la ligne de commande.\ + +* De même, une variable `acme_directory` doit pouvoir vous permettre de passer facilement de l'infrastructure de production (par défaut), à [l'environnement `staging`](https://letsencrypt.org/docs/staging-environment/) de votre fournisseur de certificats. (Vous devez impérativement utiliser l'environnement `staging` durant vos tests.) Le contenu par défaut est : `https://acme-v02.api.letsencrypt.org/directory`\ + +* Utiliser le secret `4dL1n!` pour chiffrer le contenu de vos [`ansible-vault`](https://docs.ansible.com/ansible/latest/cli/ansible-vault.html).\ + +* [KICS](https://docs.kics.io/latest/getting-started/) ne doit pas trouver de problème significatif.\ + +* En bonus, utilisez `happyDomain` (au travers des modules disponibles) pour créer le sous-domaine de votre vitrine.\ + +* N'oubliez pas de relire les guides de l'ANSSI pour vérifier que votre *playbook* `securing.yml` prend en compte un maximum de remarques pertinentes.\ + + +Arborescence attendue +======== + +Tous les fichiers identifiés comme étant à rendre sont à placer dans un dépôt +Git privé, que vous partagerez avec [votre +professeur](https://gitlab.cri.epita.fr/nemunaire/). + +Voici une arborescence type (vous pourriez avoir des fichiers supplémentaires, +cela dépendra de votre avancée dans le projet) : + +
    +``` +./basis.yml +./securing.yml +./vitrine.yml +./name-server.yml +./collections/requirements.yml +./roles/requirements.yml +... +``` +
    + +Votre rendu sera pris en compte en faisant un [tag **signé par votre clef +PGP**](https://lessons.nemunai.re/keys) ou SSH. Consultez les détails du rendu +(nom du tag, ...) sur la page dédiée au projet sur la plateforme de rendu. + +Les fichiers `requirements.yml` sont standardisés : [pour les collections](https://docs.ansible.com/ansible/latest/galaxy/user_guide.html#install-multiple-collections-with-a-requirements-file) et [pour les rôles](https://galaxy.ansible.com/docs/using/installing.html#installing-multiple-roles-from-a-file), placez-y toutes vos dépendances. diff --git a/tutorial/ansible/rendu-5.md b/tutorial/ansible/rendu-5.md new file mode 100644 index 0000000..7d6cba4 --- /dev/null +++ b/tutorial/ansible/rendu-5.md @@ -0,0 +1,42 @@ +\newpage + +Rendu +===== + +Arborescence attendue +------- + +Tous les fichiers identifiés comme étant à rendre sont à placer dans un dépôt +Git privé, que vous partagerez avec [votre +professeur](https://gitlab.cri.epita.fr/nemunaire/). + +Voici une arborescence type (vous pourriez avoir des fichiers supplémentaires, +cela dépendra de votre avancée dans le projet) : + +
    +``` +./basis.yml +./securing.yml +./vitrine.yml +./name-server.yml +... +``` +
    + +Votre rendu sera pris en compte en faisant un [tag **signé par votre clef +PGP**](https://lessons.nemunai.re/keys) ou SSH. Consultez les détails du rendu +(nom du tag, ...) sur la page dédiée au projet sur la plateforme de rendu. + + +Quelques précisions importantes +----- + +* Le contenu de votre clef SSH publique doit se trouver dans la variable `ssh_key`. Cette variable doit avoir une précédence lui permettant de pouvoir être écrasée par une surcharge sur la ligne de commande (`ansible-playbook -e ssh_key="ssh-ed25519 ABCDEF..."`). Votre clef DOIT bien être présente dans une variable et être utilisée si la variable n'est pas précisée sur la ligne de commande. + +* Utiliser le secret `4dL1n!` pour chiffrer le contenu de vos `ansible-vault`. + +* Le fichier `hosts` avec votre inventaire sera écrasé. Vous pouvez le rendre ou non. + +* Tous les `playbooks` doivent pouvoir être exécutés plusieurs fois. **Exécuté deux fois de suite, un même playbook ne doit pas trouver de changement.** + +* Pour simplifier les choses, le *playbook* `basis.yml` sera systématiquement appelé avant tous les autres et le *playbook* `name-server.yml` sera toujours appelé avant `vitrine.yml`. Les autres doivent pouvoir s'exécuter dans un ordre indéfini. diff --git a/tutorial/ansible/rendu.md b/tutorial/ansible/rendu.md index 9e09cbb..7485aba 100644 --- a/tutorial/ansible/rendu.md +++ b/tutorial/ansible/rendu.md @@ -3,115 +3,36 @@ Rendu ===== -## Modalité de rendu +Arborescence attendue +------- -Un service automatique s'occupe de réceptionner vos rendus, de faire des -vérifications élémentaires et de vous envoyer un accusé de réception (ou de -rejet). - -Ce service écoute sur l'adresse , c'est donc à cette adresse -et exclusivement à celle-ci que vous devez envoyer vos rendus. Tout rendu -envoyé à une autre adresse et/ou non signé et/ou reçu après la correction ne -sera pas pris en compte. - - -## Tarball - -Tous les fichiers identifiés comme étant à rendre pour ce TP sont à -placer dans une tarball (pas d'archive ZIP, RAR, ...). +Tous les fichiers identifiés comme étant à rendre sont à placer dans un dépôt +Git privé, que vous partagerez avec [votre +professeur](https://gitlab.cri.epita.fr/nemunaire/). Voici une arborescence type (vous pourriez avoir des fichiers supplémentaires, -en fonction de votre organisation ou de vos choix) : +cela dépendra de votre avancée dans le projet) :
    ``` -login_x-TP2/basis.yml -login_x-TP2/vitrine.yml -login_x-TP2/name-server.yml -login_x-TP2/matrix.yml +./basis.yml +./securing.yml +./vitrine.yml +./name-server.yml ... ```
    - -## Signature du rendu - -Deux méthodes sont utilisables pour signer votre rendu : - -* signature du courriel ; -* signature de la tarball. - -Dans les deux cas, si vous n'en avez pas déjà une, vous devrez créer une clef -PGP à **votre nom et prénom**. - -Pour valider la signature, il est nécessaire d'avoir reçu la clef publique -**séparément**. Vous avez le choix de l'uploader sur un serveur de clefs, soit -de me fournir votre clef en main propre, soit de l'envoyer dans un courriel -distinct. - -### Signature du courriel - -Une version récente de [Thunderbird](https://www.thunderbird.net/fr/) vous -permettra d'envoyer des courriels signés. Si vous n'avez qu'une version -ancienne, l'extension [Enigmail](https://enigmail.net) est très bien réputée -pour signer ses mails depuis Thunderbird. Bien entendu, de nombreuses autres -solutions sont disponibles. - -Utilisez le service automatique pour savoir si votre -courriel est correctement signé et que je suis en mesure de vérifier la -signature. +Votre rendu sera pris en compte en faisant un [tag **signé par votre clef +PGP**](https://lessons.nemunai.re/keys). Consultez les détails du rendu (nom du +tag, ...) sur la page dédiée au projet sur la plateforme de rendu. -### Astuces +Quelques conseils +----- -#### No public key +* Le fichier `hosts` avec votre inventaire sera écrasé. Vous pouvez le rendre ou non. -Si vous recevez un rapport avec l'erreur suivante : +* Tous les `playbooks` doivent pouvoir être exécutés plusieurs fois. Exécuté deux fois de suite, un même playbook ne doit pas trouver de changement. -
    -``` -[FAIL] Bad signature. Here is the gnupg output: - -gpg: Signature made Tue Jan 01 16:42:23 2014 CET -gpg: using RSA key 842807A84573CC96 -gpg: requesting key E2CCD99DD37BD32E from hkp server keys.openpgp.org -gpg: Can't check signature: No public key -``` -
    - -C'est que votre clef publique n'est pas dans mon trousseau et que les -méthodes de récupération automatique n'ont pas permis de la -trouver. Uploadez votre clef sur [un serveur de -clefs](https://keys.openpgp.org/) ou envoyez un courriel au service -avec votre clef publique en pièce jointe, avant de retenter votre -rendu. - - -#### Not explicit username - -Si vous recevez un rapport avec l'erreur suivante : - -
    -``` -[FAIL] The username of your key is not explicit, I can't find you. -``` -
    - -Votre clef ne contient sans doute pas vos noms et prénoms ou l'adresse -électronique associée à la clef n'est pas celle que j'ai dans ma base de -données. - - -#### I've decided to skip your e-mail - -Si vous recevez un rapport concluant ainsi : - -
    -``` -After analyzing your e-mail, I've decided to SKIP it. -``` -
    - -Cela signifie que la lecture de votre courriel qui a été préférée n'est pas -celle d'un rendu. Vérifiez que vous n'envoyez pas votre clef publique avec -votre rendu. +* Pour simplifier les choses, le *playbook* `basis.yml` sera systématiquement appelé avant tous les autres et le *playbook* `name-server.yml` sera toujours appelé avant `vitrine.yml`. Les autres doivent pouvoir s'exécuter dans un ordre indéfini. diff --git a/tutorial/ansible/tutorial-5.md b/tutorial/ansible/tutorial-5.md new file mode 100644 index 0000000..d63a5e4 --- /dev/null +++ b/tutorial/ansible/tutorial-5.md @@ -0,0 +1,16 @@ +--- +title: Administration Linux avancée -- TP n^o^ 5 +subtitle: Bonnes pratiques d'Ansible +author: Pierre-Olivier *nemunaire* [Mercier]{.smallcaps} +institute: EPITA +date: Jeudi 13 avril 2023 +abstract: | + Durant ce cinquième TP, nous allons développer nos savoirs et connaissances + d'Ansible en faisant le tour de quelques bonnes pratiques et en les + appliquant à nos actuels playbooks. + + \vspace{1em} + + Ce TP est le projet final du cours qui sera à rendre pour le + **dimanche 30 avril 2023 à 23 h 42**. +... diff --git a/tutorial/ansible/tutorial.md b/tutorial/ansible/tutorial.md index fd4e408..ed63301 100644 --- a/tutorial/ansible/tutorial.md +++ b/tutorial/ansible/tutorial.md @@ -1,24 +1,15 @@ --- -title: Administration Linux avancée -- TP n^o^ 2 -subtitle: "Maatma : l'hébergeur DIY" +title: Administration Linux avancée -- TP n^o^ 4 +subtitle: Automatiser la gestion de configuration avec Ansible author: Pierre-Olivier *nemunaire* [Mercier]{.smallcaps} institute: EPITA -date: Jeudi 16 mars 2023 +date: Jeudi 30 mars 2023 abstract: | - Durant ce troisième TP, nous allons apprendre à déployer des services sur un + Durant ce quatrième TP, nous allons apprendre à déployer des services sur un serveur, de manière industrielle ! \vspace{1em} - La partie 5 de ce TP est un projet à rendre à au plus tard - le **jeudi 31 mars 2022 à 23 h 42**. Consultez la dernière - section de chaque partie pour plus d'information sur les éléments à - rendre. Et n'oubliez pas de répondre aux [questions de - cours](https://adlin.nemunai.re/quiz/20). - - En tant que personnes sensibilisées à la sécurité des échanges électroniques, - vous devrez m'envoyer vos rendus signés avec votre clef PGP. Pensez à - [me](https://keys.openpgp.org/search?q=nemunaire%40nemunai.re) - faire signer votre clef et n'hésitez pas à [faire signer votre - clef](https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/). + Ce TP contient un projet à rendre pour le **mercredi 12 avril à + 23 h 42**. Consultez la dernière partie pour plus d'informations. ...