Add latest tutorial revision

This commit is contained in:
nemunaire 2023-05-05 09:57:22 +02:00
commit 3627de3afe
9 changed files with 348 additions and 164 deletions

View file

@ -4,11 +4,12 @@ Automatiser la configuration de son SI
=======================================
Comme tout bon ~~paresseux~~ sys. admin qui se respecte, sans plus attendre,
vous allez vouloir automatiser toutes ces actions rébarbatives (configurer des
services). Comme de très nombreuses personnes sont passées par là avant vous,
il existe un grand nombre de solutions pour gérer les configurations d'un parc
de machines. Parmi les plus connues, citons : [Puppet](https://puppet.com/),
[Chef](http://www.chef.io/), [SaltStack](https://saltstack.com/) ou encore
nous allons vouloir automatiser toutes les actions rébarbatives que nous avons
faites jusque là. Comme de très nombreuses personnes sont passées par là avant
nous, il existe un grand nombre de solutions pour gérer les configurations d'un
parc de machines. Parmi les plus connues, citons :
[Puppet](https://puppet.com/), [Chef](https://www.chef.io/),
[SaltStack](https://saltstack.com/) ou encore
[Ansible](https://www.ansible.com/).
@ -17,40 +18,49 @@ Introduction à Ansible
Ansible est une solution de gestion de configuration. Basé sur
[Python](https://www.python.org/) et
[YAML](http://www.yaml.org/spec/1.2/spec.html), sa principale particularité est
[YAML](https://www.yaml.org/spec/1.2/spec.html), sa principale particularité est
de ne pas nécessiter de daemon sur les machines qu'il va gérer : tout se fait
exclusivement via SSH, à partir de la machine d'un administrateur, possédant
Ansible (ou bien d'un système de gestion de configuration tel qu'[Ansible
Tower](https://www.ansible.com/products/tower) ou
[AWX](https://github.com/ansible/awx)).
Tower](https://www.ansible.com/products/tower),
[AWX](https://github.com/ansible/awx) ou [Semaphore](https://github.com/ansible-semaphore/semaphore/)).
Son installation est très simple, car les dépendances sont minimes et l'outil
n'a pas besoin de base de données pour fonctionner : tout va se faire à partir
d'une arborescence de fichiers, qui sera gérée par Git.
Commencez par installer Ansible, sur une machine distincte de la machine
virtuelle démarrée : la machine hôte sera parfaitement adaptée à cette tâche,
d'autant plus que l'installation de la plate-forme est propre et légère : vous
ne risquez pas de vous retrouver avec une usine à gaz impossible à retirer.
Commençons par installer Ansible, sur une machine distincte de la machine
virtuelle démarrée : la machine hôte sera parfaitement adaptée à cette
tâche. Mais vous pouvez aussi choisir de l'installer dans une seconde machine
virtuelle.
[Consultez la procédure d'installation pour votre distribution ici](http://docs.ansible.com/ansible/latest/intro_installation.html).
[Consultez la procédure d'installation pour votre distribution ici](https://docs.ansible.com/ansible/latest/intro_installation.html).
Résultat attendu
----------------
À la fin de cette partie, vous devez être en mesure de déployer une nouvelle
machine, identique à celle que vous venez de configurer, à partir d'une ISO et
À la fin de ce TP, vous devez être en mesure de déployer une nouvelle
machine, identique à celle que vous avez configurée, à partir d'une ISO et
d'un nouveau disque.
Le fichier à rendre est un *playbook* `login-x-TP2/basis.yml`, accompagné de
toutes ses dépendances : celui-ci doit faire les configurations basiques du
système et des utilisateurs.
Vous devrez pour cela réaliser des *playbooks* :
- `basis.yml`, accompagné de toutes ses dépendances : celui-ci doit faire les
configurations **minimales** du système et des utilisateurs (le seul
*playbook* qui se connecte à l'utilisateur `root` directement, retirez le
maximum de chose de ce *playbook* qui pourraient aller dans le suivant).
Un deuxième playbook est à rendre : `login-x-TP2/vitrine.yml`, celui-ci doit
permettre de déployer, une page vitrine typique d'une entreprise (cf. la 4e
question de cours ;)). Cette page doit être accessible depuis votre domaine
<https://login-x.adlin2024.example.tld/>.\
- `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
<https://login-x.adlin2024.example.tld/>.
- `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 :
<div lang="en-US">
```
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 :
```
</div>
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 :
<div lang="en-US">
```
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"
}
```
</div>
### 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
<div lang="en-US">
```
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
}
```
</div>
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 :
<div lang="en-US">
```
42sh$ ansible --inventory-file hosts all --user root --module-name user --args "name=login_x uid=1042"
192.168.0.106 | SUCCESS => {
[...]
```
</div>
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) :
<div lang="en-US">
```
ansible --inventory-file hosts all --module-name authorized_key --args "user=login_x key='ssh-ed25519 AAAAC3NzaC1lZD...FD'"
```
</div>
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) :
<div lang="en-US">
```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
```
</div>
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
```
</div>
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 :
- <https://linuxhandbook.com/ssh-hardening-tips/> ;
- <https://www.ssi.gouv.fr/guide/recommandations-pour-un-usage-securise-dopenssh/> ;
- <https://stribika.github.io/2015/01/04/secure-secure-shell.html>.
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
```
</div>
@ -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.
<div lang="en-US">
@ -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
```
</div>
@ -451,4 +560,4 @@ tasks:
</div>
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).