Aller au contenu

Inventory file (fichier d'inventaire)

Au format YAML, ce type de fichier permet de regrouper les informations nécessaires à l’exécution d’une ou plusieurs opérations. L’inventaire n’est pas obligatoire dans un processus d’automatisation, mais le devient dans le cadre d’une utilisation multihôtes/utilisateurs.

Vous organisez vos inventaires comme bon vous semble, le plus important reste que l’opération doit y avoir accès. Les fichiers d’inventaire peuvent être chiffrés avec SOPS, (plus de détails dans ce chapitre).

Cette partie utilise la commande “run”, Tous les détails sur cette commande.

Besoin d’un fichier d’inventaire ?

Le plus simple est de découvrir pourquoi un fichier d’inventaire va devenir nécessaire dans un process de production.

Cas des clés SSH protégées par mot de passe

  • Une opération “OP1” est réalisée couramment sur “server1”, et exécutée comme suit :
Fenêtre de terminal
automation run -h "server1" -op "OP1" -sshpk "private SSH key place"
  • “OP1” devient nécessaire sur “server2”, j’ajoute l’hôte “server2” aux paramètres “-h”
Fenêtre de terminal
automation run -h "server1 server2" -op "OP1" -sshpk "private SSH key place"
  • Le Boss décide que la clé privée SSH utilisée pour se connecter aux serveurs “server1” et “server2” doit être protégée par un mot de passe, nous devons fournir à automation-cli le secret permettant de déchiffrer la clé privée SSH :
Fenêtre de terminal
automation run -h "server1 server2" -op "OP1" -sshpk "private SSH key place" -sshpass "supersecret"
  • Travaillant en espace partagé, le Boss s’aperçoit que l’historique des commandes bash fait apparaître le mot de passe “en clair”. Bob préconise l’utilisation de “l’espace magique” (fortement déconseillé en équipe), mais la moitié des sysadmins l’oubli, Bob propose d’écrire le secret dans un fichier et la commande se transforme en :
Fenêtre de terminal
automation run -h "server1 server2" -op "OP1" -sshpk "private SSH key place" -sshpass "$(cat ./supersecretfile)"
  • Chaque sysadmin crée maintenant son propre fichier, le secret se retrouve maintenant éparpillé sur le nœud de contrôle. La solution consiste à stocker ce secret et l’emplacement de la clé dans un fichier unique qui sera utilisé par tous les sysadmins.
Fenêtre de terminal
automation run -h "server1 server2" -op "OP1" -i "/inventoryFile.yaml"
  • Bob décide même d’ajouter ce fichier au dépôt Git qui contient toutes les opérations.
  • Le Boss consulte le dépôt Git et constate que le secret, “en clair”, est désormais visible de tous ceux qui ont accès à ce dépôt !
  • Bob n’avait pas encore eu le temps de lire la partie “Secrets” de cette documentation. Il convertit le fichier d’inventaire en fichier SOPS (chiffré), change le secret, et envoie le tout sur le dépôt Git.
  • Le Boss constate le chiffrement du fichier dans le dépôt Git, et ne peut pas le déchiffrer, il revient donc sur la version précédente et tente de se connecter avec le secret “en clair”, mais Bob a bien fait son taf…

Cas des paramètres personnalisés

Syntaxe

En passant le commutateur “-i” aux différentes commandes le supportant, la valeur de ce commutateur est le nom d’un fichier d’inventaire, comprenant l’extension “.yaml”.

Ce chemin peut être :

  • Relatif au chemin d’exécution : ./inventory.yaml.
  • Absolue : /directory1/directory2/inventory.yaml.
  • Relatif à l’ OPSDirectory : “inventory.yaml” sans ./ ou /, exemple : Si la valeur de la variable d’environnement OPS est égale à $(pwd)/OPSDirectory alors le chemin final sera la concaténation de la valeur de OPS et du fichier : $(pwd)/OPSDirectory/inventory.yaml.

Pour un raccourci “bash” vers la “Home directory” d’un utilisateur du serveur (~/), ne pas encadrer la valeur, exemple : -i ~/mydirectory/inventory.yaml.

La syntaxe pour lire la valeur d’un attribut de l’inventaire est :

  • ‘#inv.attribut.otherattribut’, supporte aussi l’itération sur des arrays : ‘#inv.attribut[0].otherattribut’.
  • supporte aussi les variables d’environnement : ‘#inv.$USER.attribut’. L’environnement pris en compte est celui du nœud de contrôle au moment de l’exécution. Ces valeurs ne sont jamais résolues sur l’hôte.

Lorsque la valeur d’un attribut de l’inventaire est vide ou n’a pas été trouvée :

  • La variable d’environnement est requise : ceci entraîne une erreur d’exécution.
  • La variable d’environnement n’est pas requise : la variable d’environnement est définie avec une valeur vide, exemple : TEST="". Ceci permet de gérer confortablement la définition des variables optionnelles pour bash. Rappelez-vous, le shell final exécuté sur l’hôte comporte la commande : “set -u”, ce qui sous-entend que toutes variables utilisées doivent au préalable avoir été déclarée.

Vous pouvez aussi indiquer un attribut représentant un objet, il sera converti en chaine JSON manipulable avec ‘jq’ dans votre shell.

Exemple d’inventaire :

servers:
one:
ipAddress: "xxxx"
two:
ipAddress: "xxxx"

Si vous indiquez -e MYVAR='#inv.servers', la valeur extraite sera une structure JSON sur une seule ligne :

{ "one": { "ipAddress": "xxxx" }, "two": { "ipAddress": "xxxx" } }

qui peut être convertie (dans votre shell) par ‘jq’ en array :

Fenêtre de terminal
echo "${MYVAR}" | jq 'map(select(.))|.[]'

Résultat obtenu avec ‘jq’ :

[{ "one": { "ipAddress": "xxxx" } }, { "two": { "ipAddress": "xxxx" } }]

Exemple

  • Une opération “OP1” est réalisée couramment sur “server1”, et exécutée comme suit :
Fenêtre de terminal
automation run -h "server1" -op "OP1"
  • “OP1” devient nécessaire sur “server2”, j’ajoute l’hôte “server2” au paramètre “-h”
Fenêtre de terminal
automation run -h "server1 server2" -op "OP1"
  • L’opération se termine avec une erreur pour “server2”. Après analyse, un des fichiers nécessaire porte un autre nom sur “server2”, et la commande utilisée dans cette opération prévoit un paramètre permettant de spécifier l’emplacement de ce fichier.
  • Création d’un inventaire de cette forme :
server1:
appfile: "/var/lib/1.conf"
server2:
appfile: "/var/lib/5.conf"
  • Cet inventaire permet de connaître l’emplacement exact du fichier nécessaire sur chacun des serveurs.

  • Arrangeons l’opération.

  • L’opération est de type “script” (run.sh) dont le contenu est le suivant :

#!/usr/bin/env bash
mycommand
  • D’après la documentation, “mycommand” prévoit le paramètre “-fileplace” pour indiquer le chemin du fichier nécessaire, le script devient :
#!/usr/bin/env bash
mycommand -fileplace ${FILEPLACE}

J’ai ajouté le paramètre d’opération “FILEPLACE” de type ‘string’ et dont la fonction permet de précise l’emplacement du fichier nécessaire. Ce paramètre devient “requis” pour son exécution. Modifions le manifeste de l’opération

comment: "operation OP1"
scripts:
- "run.sh"
parameters:
required:
FILEPLACE:
type: string
comment: "file place [full path]"
  • Exécutons l’opération en fournissant le fichier d’inventaire et la valeur de la variable “FILEPLACE” :
Fenêtre de terminal
automation run -h "server1 server2" -op "OP1" -i "/inventoryFile.yaml" -e FILEPLACE='#inv.$host.appfile'
  • Comment çà marche ?
    • “automation-cli” détecte une variable requise par l’opération et fournie dans la ligne de commande (“FILEPLACE”) et détecte aussi le raccourci “#inv.”.
    • “automation-cli” en déduit l’utilisation d’un fichier d’inventaire,
      • est-il spécifié ? Oui.
      • Existe-t-il ? Oui.
      • L’opération peut démarrer simultanément sur chacun des hôtes.
      • À la préparation, “automation-cli” substitue “$host” par l’hôte sur lequel l’opération est réalisée (“server1” ou “server2”).
        • Pour “server1”, la valeur de “FILEPLACE” devient “server1.appfile”,
        • lecture de l’inventaire, l’attribut ‘server1.appfile’ existe-t-il ? Oui.
        • Sa valeur remplace l’originale : “FILEPLACE=‘server1.appfile’ => FILEPLACE=“/var/lib/1.conf”, si l’attribut n’existe pas, dans le fichier d’inventaire, l’opération se termine par une erreur sans même tenter l’exécution.
        • L’opération est exécutée, l’opération ne se termine pas en erreur.

Créer un fichier d’inventaire

La commande pour créer un fichier d’inventaire est : “cinv”, l’option “-age” est recommandée, ceci permet de créer un fichier chiffré avec SOPS.

Fenêtre de terminal
automation-cli cinv "[inventory yaml full path]" -age "[Your public age key]"

Exemple :

Fenêtre de terminal
automation-cli cinv "./inventory.yaml" -age "agexxxxxxxx"

Attributs YAML prédéfinis dans le template interne

NomTypeFonction
sshpkstringchemin (absolu/relatif) de la clé privée SSH utilisée pour se connecter aux hôtes
sshpassstringmot de passe de la clé privée SSH
serverGroups.allArrayliste des hôtes tels qu’appelé par l’option -h

Exemple d’inventaire

Résolution des hôtes par adresse IP

Ce schéma permet à “automation-cli” de résoudre les noms d’hôtes en adresse IP. Le mécanisme de fonctionnement est simple, l’utilisateur définit le ou les hôtes avec le paramètre “-h”. L’attribut “serverGroups” est une structure d’arbre, qu’il suffit de parcourir pour résoudre l’adresse IP associée à un hôte. Tous les attributs de type “array” sont des groupes, qui permettent d’organiser les hôtes. Si l’hôte final n’est pas référencé par une adresse IP, “automation-cli” utilisera le mécanisme de résolution par DNS.

sshpk: "./sshkeys/maintenance"
sshpass: "mysupersecret"
serverGroups:
all:
- sgbdr
- redis
- localhost
controlnode:
- localhost
sgbdr:
- postgresql1
- postgresql2
- postgresql3
redis:
- redis1
- redis2
- redis3
redis1: 172.28.10.1
redis2: 172.28.10.2
redis3: 172.28.10.3
postgresql1: 172.28.50.1
postgresql2: 172.28.50.1
postgresql3: 172.28.50.1
localhost: 127.0.0.1

La résolution des hôtes se fait en parcourant l’arbre, la dernière valeur fait office de “Endpoint”. Prenons l’exemple du serveur ‘postgresql3’. Exécutez :

Fenêtre de terminal
automation run -h "postgresql3" -op "OP1" -i "/inventoryFile.yaml"

Les rapports d’exécution mentionneront que l’opération a été réalisée sur ‘postgresql3’, les connexions SSH se feront auprès de ‘172.28.50.1’. Notez que les rapports d’exécution présentent toujours l’association ‘hôte demandé par l’utilisateur’ et ‘hôte utilisé pour la connexion SSH’.