Automatisation.md 15 KB

Automatisation

jeton smartthings: f9f05f67-0e9c-4c99-883e-5cf249eaa2

Maintenant que nous avons fait toutes ces manipulations à la main, nous allons pouvoir automatiser la configuration de notre raspi d'une façon automatique avec ansible.

En fait, le but est de pouvoir déployer notre serveur en un minimum de temps. Nous ajouterons une partie variable, appelée les facts, ce qui nous permettra d'installer différents serveurs avec des options différentes ainsi que des services parfois dictintcs.

Nous allons reprendre toutes les étapes et les scripter dans un playbook ansible.

Principe

Création d'un utilisateur dédié sur le poste client

Il est parfaitement possible d'utiliser un role ansible tout prêt de création d'un nouvel utilisateur sur notre poste client, mais pour ça, il faut que ansible soit déjà installé.

Nous allons donc créer un utilisateur deborah de façon classique avec la commande adduser:

eric@aldebaran:~$ sudo adduser deborah
[sudo] Mot de passe de eric : 
Ajout de l'utilisateur « deborah » ...
Ajout du nouveau groupe « deborah » (1002) ...
Ajout du nouvel utilisateur « deborah » (1002) avec le groupe « deborah » ...
Création du répertoire personnel « /home/deborah »...
Copie des fichiers depuis « /etc/skel »...
Nouveau mot de passe : 
Retapez le nouveau mot de passe : 
passwd: password updated successfully
Changing the user information for deborah
Enter the new value, or press ENTER for the default
    Full Name []: Déborah
    Room Number []: 
    Work Phone []: 
    Home Phone []: 
    Other []: 
chfn: name with non-ASCII characters: 'Déborah'
Cette information est-elle correcte ? [O/n]
eric@aldebaran:~$ 

Installation de ansible sur le compte du nouvel utilisateur

Nous allons assumer que python est déjà installé, ce qui est le cas pour une installation desktop Debian normale.

Passons à l'utilisateur deborah juste créé:

eric@aldebaran:~$ su - deborah
Mot de passe : 
deborah@aldebaran:~$ 
  • vérification de notre installation python

    deborah@aldebaran:~$ python3 --version Python 3.9.1 deborah@aldebaran:~$

  • installation de ansible

Nous installons ansible avec pip3; nous aurions pu utiliser la paquet ansible tout prêt, mais il n'aurait pas été aussi à jour. Une autre solution aurait été d'utiliser virtualenv. Je rajouterai éventuellement un paragraphe pour expliquer le fonctionnement de virtualenv.

ansible ainsi que les autres binaires sont installés dans le répertoire utilisateur ~/.local/bin. Ce chemin est déjà programmé dans le fichier .profile et pour que ce chemin soit pris en compte, il suffit de "sourcer" le fichier .profile

deborah@aldebaran:~$ source .profile

Le résultat est le suivant:

deborah@aldebaran:~$ ansible --version
ansible 2.10.4
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/deborah/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/deborah/.local/lib/python3.9/site-packages/ansible
executable location = /home/deborah/.local/bin/ansible
python version = 3.9.1 (default, Dec  8 2020, 07:51:42) [GCC 10.2.0]
deborah@aldebaran:~$ 

Voilà, ansible est installé, en version 2.10.4.

Configuration ssh

Nous allons suivre la méthode décrite dans un chapitre précédent:

deborah@aldebaran:~$ ssh-keygen -o -a 100 -t ed25519 -f ~/.ssh/piras_ed25519 -C "eric@yojik.eu"
...
deborah@aldebaran:~$

Récupération adresse IP

L'adresse ip par défaut est attribuée par le serveur dhcp de notre box, et donc, est sujet à variation suivant le nombre des autres dispositifs connectés.

Même méthode que précédemment avec nmap:

  • L'adresse dynamique récupérée est : 192.168.111.33

  • L'utilisateur (avec droits sudo) est par défaut: pi

  • Le mot de passe par défaut est : raspberry

Copie de notre clef publique sur le raspi et connexion

deborah@aldebaran:~$ ssh-copy-id -i ~/.ssh/piras_ed25519.pub pi@192.168.111.33
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/deborah/.ssh/piras_ed25519.pub"
The authenticity of host '192.168.111.33 (192.168.111.33)' can't be established.
ECDSA key fingerprint is SHA256:JA3Eb2suh7qz7iwkoKL0yzbO698fj3EF4/vrhW7LTds.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
pi@192.168.111.33's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'pi@192.168.111.33'"
and check to make sure that only the key(s) you wanted were added.

deborah@aldebaran:~$

Connexion:

deborah@aldebaran:~$ ssh -i ./.ssh/piras_ed25519 pi@192.168.111.33
Enter passphrase for key './.ssh/piras_ed25519': 
Linux raspberrypi 5.4.51+ #1333 Mon Aug 10 16:38:02 BST 2020 armv6l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sun Dec 27 17:31:01 2020 from 192.168.111.150
pi@raspberrypi:~ $

Tout fonctionne.

Lancement de raspi-config

Configurez votre raspi avec la commande:

sudo raspi-config

Retaillez la partition root pour occuper toute la place disponible. Changez les locales ainsi que le mappage clavier. (pas très butile si vous ne vous connectez pas directement sur le raspi avec un clavier, mais bon, faites-le par précaution si vous devez vous connecter un jour directement)

Changement du mot de passe

Après avoir généré un mot de passe aléatoire avec pwgen, tapez la commande suivante (il était aussi possible de le changer avec l'utilitaire raspi-config vu au paragraphe précédent):

pi@raspberrypi:~ $ passwd
Changement du mot de passe pour pi.
Current password: 
Nouveau mot de passe : 
Retapez le nouveau mot de passe : 
passwd: password updated successfully
pi@raspberrypi:~ $

Le reste se fera avec ansible. On sort avec "Ctrl D".

Nos serveurs

L'identité de nos serveurs comme les caractéristiques de connexion, port SSH, adresse IP sont conservées dans un fichier inventaire appelé inventory dans le jargon ansible.

Il peut porter n'importe quel nom mais habituellement il est appelé inventory.

  • Création de la structure de répertoires/fichiers

    Nous allons aussi respecter la structure conseillée des répertoires de déploiement des playbooks ansible. Pour cela nous allons utiliser ansible-galaxy avec la commande suivante:

    deborah@aldebaran:~$ ansible-galaxy init piras
    - Role piras was created successfully
    deborah@aldebaran:~$
    

    La structure de répertoires a été créée pour nous.

    deborah@aldebaran:~$ tree piras
    piras
    ├── defaults
    │   └── main.yml
    ├── files
    ├── handlers
    │   └── main.yml
    ├── meta
    │   └── main.yml
    ├── README.md
    ├── tasks
    │   └── main.yml
    ├── templates
    ├── tests
    │   ├── inventory
    │   └── test.yml
    └── vars
        └── main.yml
    
    8 directories, 8 files
    deborah@aldebaran:~$
    

    Les actions à accomplir sont saisies dans des fichiers au format YAML. Le fichier inventaire qui contient les machines à configurer, les hosts peut être en format YAML ou INI (format des fichiers de configuration Windows).

  • Création du fichier inventaire

    2 formats pour ça:

    1. Format INI

      [vps]
      ns1 ansible_port=22 ansible_host=ns1.yojik.eu
      ns2 ansible_port=22 ansible_host=ns2.yojik.eu
      
      [home]
      piras ansible_port=22 ansible_host=piras.yojik.net ansible_user=pi ansible_ssh_private_key_file=.ssh/piras_ed25519
      
    2. Format YAML

        ---
        # my hosts
        all:
        hosts:
            ns1:
                ansible_host: ns1.yojik.eu
            ns2:
                ansible_host: ns2.yojik.eu
            piras:
                ansible_host: piras.yojik.net
                ansible_user: pi
                ansible_ssh_private_key_file: .ssh/piras_ed25519
        ...  
      

      3 hosts sont configurés dans ce fichier inventaire: ns1 et ns2 sont deux VPS loués chez OVH qui servent de serveurs DNS. Et piras qui est l'objet de ce tutoriel.

      Vous noterez que j'ai mis les noms des machines (fqdn) et qu'il faut bien sûr renseigner les IPs de ces machines, soit dans le fichier /etc/hosts soit dans les zones du serveur DNS.

  • Test avec commandes ad-hoc

    On va envoyer une commande ping au raspi:

    deborah@aldebaran:~$ ansible -i inventory piras -m ping
    Enter passphrase for key '.ssh/piras_ed25519': 
    piras | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        },
        "changed": false,
        "ping": "pong"
    }
    deborah@aldebaran:~$
    

    Ca marche ;)

    On va envoyer une commande echo au raspi:

    deborah@aldebaran:~$ ansible piras -i inventory -m command -a "echo 'salut'" 
    Enter passphrase for key '.ssh/piras_ed25519': 
    piras | CHANGED | rc=0 >>
    salut
    deborah@aldebaran:~$
    

    Ca fonctionne.

  • Test avec playbook

    Les playbook(s) sont des fichiers au format YAML qui décrivent les actions à accomplir. Varibales, boucles, tests sont disponibles pour assurer les fonctions nécessaires.

    1. Exemple de playbook (nom: piras.yml)

      -
        name: play-1
        hosts: piras
        tasks:
          - name: test de la connectivité
            action: ping
      
    2. Test du playbook

      deborah@aldebaran:~$ ansible-playbook piras.yml -i inventory
      
      PLAY [play-1] *************************************************************************************************************
      
      TASK [Gathering Facts] ****************************************************************************************************
      Enter passphrase for key '.ssh/piras_ed25519': 
      ok: [piras]
      
      TASK [test de la connectivité] ********************************************************************************************
      ok: [piras]
      
      PLAY RECAP ****************************************************************************************************************
      piras                      : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
      
      deborah@aldebaran:~$ 
      

      Ca marche (ok=2.)

État des lieux

Nous avons les données suivantes:

  • adresse IP DHCP: 192.168.111.33.
  • adresse IPV4 fixe: 192.168.111.171 : à configurer.
  • adresse IPV6 fixe: 2a01:e0a:d0:3c20::171 : à configurer.
  • nom du user: pi (user prédéfini avec droits sudo)
  • nom de la machine: raspberrypi: à configurer.
  • domaine de la machine: yojik.net (c'est le domaine de mon réseau local): à configurer.

    Le non complet sera donc: piras.yojik.net

Un des premiers problèmes à résoudre est que l'adresse IP par défaut est donnée par DHCP, donc variable. Il faudra redémarrer le raspi une fois la modification de la configuration réseau faite et re-tester la connectivité.

Tâche 1

Tester la connectivité:

  • Ajout de l'adresse du serveur toto à /etc/hosts du poste client.

    Nous pouvons le faire manuellement, ou avec un script shell, ou avec un playbook ansible.

    1. à la main

      Utilisez votre éditeur préféré, et ajoutez/modifiez la ligne suivante à /etc/hosts:

      192.168.111.171 toto.yojik.net toto

    2. script shell

      eric@aldebaran:~/ansible-toto$ cat play1.sh 
      #!/bin/sh
      
      echo "192.168.111.171 toto.yojik.net toto" >> /etc/hosts
      cat /etc/hosts
      eric@aldebaran:~/ansible-toto$
      
      eric@aldebaran:~/ansible-toto$ chmod +x play1.sh
      eric@aldebaran:~/ansible-toto$  sudo ./play1.sh
      127.0.0.1              localhost
      
      192.168.111.150         aldebaran.yojik.net        aldebaran
      
      # The following lines are desirable for IPv6 capable hosts
      ::1     localhost ip6-localhost ip6-loopback
      ff02::1 ip6-allnodes
      ff02::2 ip6-allrouters
      192.168.111.171 toto.yojik.net toto
      eric@aldebaran:~/ansible-toto$ 
      

      La ligne a bien été ajoutée à la fin du fichier.

    3. playbook ansible

      La playbook que nous verrons à l'étape suivante va mettre à jour le fichier /etc/hosts automatiquement avec les informations saisies dans le fichier variables de notre projet ansible.

  • test

Tâche 2

Nous allons mettre à jour notre hostname ainsi que le fichier /etc/hosts. Pour cela nous allons utiliser un role tout prêt disponible sur galaxy-ansible.

Ce role s'appelle hostname et l'auteur en est: Mischa ter Smitten

Pour installer ce role, tapez:

eric@aldebaran:~$ ansible-galaxy install oefenweb.hostname
Starting galaxy role install process
- downloading role 'hostname', owned by oefenweb
- downloading role from https://github.com/Oefenweb/ansible-hostname/archive/v2.0.17.tar.gz
- extracting oefenweb.hostname to /home/eric/.ansible/roles/oefenweb.hostname
- oefenweb.hostname (v2.0.17) was installed successfully
eric@aldebaran:~$

La documentation est disponible dans le répertoire:

~/.ansible/roles/oefenweb.hostname

Il nous faut entrer le fqdn dans le fichier inventaire, et créer des fichiers de variables dans le répertoire adéquat, avec un nom bien précis (en rapport avec le fqdn).

  • mise à jour du nom d'hôte (hostname)
  • test

Tâche 3

  • création de l'une clef ssh sur le desktop
  • ajout d'un enregistrement à ./.ssh/config pour intégrer le nouveau serveur
  • modification de /etc/hosts pour intégrer le fqdn de ce nouveau serveur
  • test

Tâche 4

  • copie de cette clef sur le raspi
  • test de connexion avec cette clef

Tâche 5

Sécurisation ssh

  • test d'audit du serveur
  • création de nouvelles clefs sur le serveur
  • copie d'un fichier sshd_config sur le serveur
  • relance du daemon sshd
  • test de connexion
  • test d'audit

Tâche 6

Création d'adresse IPV4 et IPV6 fixes.

  • modification de /etc/dhcpd/dhcpd.conf
  • reboot