Aller au contenu
Infrastructure as Code medium

InSpec : vérifier un cookbook Chef sur la vraie VM

10 min de lecture

logo chef

InSpec vérifie que la machine est réellement dans l'état voulu, après la convergence. Une exécution Chef « sans erreur » ne prouve pas que nginx écoute vraiment ni que la page répond : elle prouve seulement que les ressources ont été appliquées. InSpec, lui, se connecte à la vraie VM et affirme des faits observables : ce paquet est installé, ce port écoute, ce fichier contient ceci, cette URL renvoie cela. Ce guide teste la VM web1 après y avoir convergé le cookbook webstack avec knife-zero. Public visé : lecteur ayant déployé un cookbook sur une VM et vu ChefSpec.

  • Écrire un profil InSpec structuré en contrôles.
  • Vérifier paquet, service, port, fichiers et réponse HTTP sur la machine.
  • Lancer InSpec en SSH sur une vraie VM.
  • Lire un contrôle qui échoue et comprendre l'écart.
  • Enchaîner ChefSpec (avant) puis InSpec (après) autour de la convergence.
  • La VM web1 joignable en SSH, avec le cookbook webstack convergé dessus via knife-zero.
  • Le cookbook webstack, qui installe nginx et sert une page sur le port 8080.
  • CINC Workstation : InSpec y est inclus sous le nom inspec (moteur cinc-auditor).

Testé avec InSpec / CINC Auditor (CINC Workstation), cookbook webstack convergé sur une VM Debian 13 (web1, 192.168.122.167).

ChefSpec vérifie ce qu'une recette déclare, en mémoire, avant toute machine. InSpec vérifie ce que la machine est devenue, après convergence. Les deux sont complémentaires et ne testent pas la même chose : un cookbook peut déclarer parfaitement ses ressources (ChefSpec vert) et pourtant laisser un service inaccessible parce qu'un pare-feu bloque le port. Seul un test sur la vraie machine le révèle.

ChefSpecInSpec
MomentAvant convergenceAprès convergence
CibleEn mémoire, sur le posteLa VM réelle, en SSH
VérifieRessources déclaréesÉtat observable (port, HTTP, fichiers)
AttrapeErreur de logique de recetteÉcart entre déploiement et résultat réel

InSpec dépasse d'ailleurs le cadre des tests de cookbook : c'est aussi l'outil de conformité (vérifier qu'un parc respecte un référentiel de sécurité). Ici, on l'utilise pour son usage le plus direct : prouver qu'un déploiement a produit l'effet attendu.

Un profil InSpec regroupe des contrôles dans une arborescence conventionnelle. Pour un cookbook, on la place sous test/integration/default/. Un contrôle porte un nom, un titre, et une série d'attentes exprimées avec describe.

  1. Déclarer le profil dans test/integration/default/inspec.yml :

    name: webstack
    title: Verification du cookbook webstack
    version: 1.0.0
  2. Écrire les contrôles dans test/integration/default/controls/webstack_test.rb :

    control 'nginx-service' do
    title 'nginx est installe, actif et ecoute sur 8080'
    describe package('nginx') do
    it { should be_installed }
    end
    describe service('nginx') do
    it { should be_enabled }
    it { should be_running }
    end
    describe port(8080) do
    it { should be_listening }
    end
    end
    control 'webstack-contenu' do
    title 'La configuration et la page sont en place'
    describe file('/etc/nginx/conf.d/webstack.conf') do
    it { should exist }
    its('content') { should match(/listen 8080/) }
    end
    describe file('/var/www/webstack/index.html') do
    its('content') { should match(/webstack/) }
    end
    describe command('curl -s http://localhost:8080') do
    its('stdout') { should match(/webstack/) }
    end
    end

Chaque ressource InSpec interroge un aspect du système : package lit la base de paquets, service interroge systemd, port regarde ce qui écoute, file inspecte un fichier, command exécute une commande sur la cible et capture sa sortie. On regroupe les attentes liées dans un même control pour obtenir un rapport lisible : ici, l'état du service d'un côté, le contenu servi de l'autre.

InSpec se connecte à la machine en SSH grâce à l'option -t (target). On pointe le profil, la cible et la clé, et on ajoute --sudo pour lire les fichiers et l'état des services :

Fenêtre de terminal
inspec exec test/integration/default \
-t ssh://ubuntu@192.168.122.167 \
-i ~/.ssh/id_ed25519 --sudo

InSpec exécute chaque contrôle sur web1 et rend un rapport détaillé :

Profile: Verification du cookbook webstack (webstack)
Target: ssh://ubuntu@192.168.122.167:22
✔ nginx-service: nginx est installe, actif et ecoute sur 8080
✔ System Package nginx is expected to be installed
✔ Service nginx is expected to be enabled
✔ Service nginx is expected to be running
✔ Port 8080 is expected to be listening
✔ webstack-contenu: La configuration et la page sont en place
✔ File /etc/nginx/conf.d/webstack.conf is expected to exist
✔ File /etc/nginx/conf.d/webstack.conf content is expected to match /listen 8080/
✔ File /var/www/webstack/index.html content is expected to match /webstack/
✔ Command: `curl -s http://localhost:8080` stdout is expected to match /webstack/
Profile Summary: 2 successful controls, 0 control failures, 0 controls skipped
Test Summary: 8 successful, 0 failures, 0 skipped

Le contrôle curl est le plus parlant : il ne se contente pas de vérifier que nginx tourne, il prouve que la page est réellement servie sur le port 8080. C'est la différence entre « le service est démarré » et « le service répond ».

Un test n'a de valeur que s'il échoue quand la réalité ne correspond pas à l'attente. Supposez qu'un contrôle attende, à tort, le mot Bienvenue dans la page :

describe file('/var/www/webstack/index.html') do
its('content') { should match(/Bienvenue/) }
end

InSpec montre exactement l'écart entre l'attendu et le réel :

× demo-echec: La page contient Bienvenue (attente fausse)
× File /var/www/webstack/index.html content is expected to match /Bienvenue/
expected "webstack\n" to match /Bienvenue/
Profile Summary: 0 successful controls, 1 control failure, 0 controls skipped

La ligne expected "webstack\n" to match /Bienvenue/ dit tout : le fichier contient webstack, pas Bienvenue. Sur un vrai déploiement, ce type d'échec révèle un template mal rendu, une variable oubliée ou une convergence incomplète, autant de choses qu'une exécution Chef « sans erreur » ne signale pas.

La convention place les profils sous test/integration/<suite>/, avec un inspec.yml et un dossier controls/. Cette structure est reconnue par les outils d'intégration continue et permet plusieurs suites (par exemple default et production). Gardez les contrôles lisibles : un control par intention, un titre clair, des describe regroupés par thème. Le rapport final se lit alors comme une liste d'exigences vérifiées, utile bien au-delà de l'équipe qui a écrit le cookbook.

  1. InSpec teste l'état réel de la machine après convergence, là où ChefSpec teste la recette avant.
  2. Un profil regroupe des contrôles sous test/integration/default/, avec un inspec.yml.
  3. Les ressources package, service, port, file, command couvrent l'essentiel d'un service.
  4. On cible la VM en SSH avec inspec exec ... -t ssh://... --sudo.
  5. Un contrôle curl prouve que le service répond, pas seulement qu'il est démarré.
  6. ChefSpec avant, InSpec après knife zero converge : la boucle de test complète d'un cookbook.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn