Florian Amette

Florian Amette

July 9, 2026

Automatiser la création de labs avec Terraform et Ansible (patterns pour la classe)

TerraformAnsibleIaClab cybersécuritéautomatisation pédagogique
Automatiser la création de labs avec Terraform et Ansible (patterns pour la classe)

Automatiser la création de labs avec Terraform et Ansible (patterns pour la classe)

Pourquoi automatiser un lab pédagogique

Un lab cybersécurité manuel, c'est 30 étudiants qui attendent que l'admin finisse de configurer les VMs pendant la première heure d'une séance de 3 heures. C'est un reset post-TP qui prend une matinée. C'est une infrastructure qui dérive entre les promotions parce que des étudiants ont modifié des configurations sans les documenter.

L'Infrastructure as Code (IaC) résout ces problèmes en rendant le lab reproductible, versionnable et réinitialisable en quelques minutes. Terraform gère l'infrastructure (VMs, réseaux, stockage), Ansible configure les systèmes (packages, utilisateurs, services, vulnérabilités intentionnelles pour les TP). Ensemble, ils forment un pipeline de provisionnement qui s'exécute de façon idempotente : on peut relancer le même script dix fois sans effet de bord.

Cet article présente les patterns pratiques adaptés à un contexte scolaire : contraintes de budget, rotations de promotions, niveaux de droits étudiant variés et besoins de sécurité différents d'un homelab.

Ce qu'on gagne et ce qu'on ne doit pas automatiser

Avant de choisir les outils, clarifier ce qui mérite d'être automatisé et ce qui ne l'est pas.

AutomatiserNe pas automatiser
Création et suppression des VMsLa topologie réseau pédagogique (à documenter manuellement)
Installation des packages et outilsLes vulnérabilités intentionnelles complexes (vérifier à la main)
Création des comptes étudiantsLes corrections de TP et les retours d'évaluation
Reset entre séances ou promotionsLes accès à des systèmes tiers réels
Déploiement des challenges (CTF)Les politiques de sécurité de l'établissement
Génération de snapshots de référenceLa relation pédagogique avec les étudiants

Ce qui doit rester manuel : tout ce qui touche à la pédagogie elle-même (construction du scénario, accompagnement des étudiants, feedback) et tout ce qui implique des décisions de sécurité institutionnelles.

Architecture de référence d'un lab automatisé

Un lab scolaire typique comprend trois zones :

┌─────────────────────────────────────────────────────┐
│                  RÉSEAU PÉDAGOGIQUE                  │
│                                                     │
│  ┌────────────┐   ┌────────────┐   ┌────────────┐  │
│  │ Zone Admin  │   │ Zone Cibles │   │ Zone Étud. │  │
│  │ (Ansible   │   │ (VMs vulnér)│   │ (Kali Linux│  │
│  │  control)  │   │            │   │  x 30)     │  │
│  └────────────┘   └────────────┘   └────────────┘  │
│         │                │                │         │
│  ┌──────┴────────────────┴────────────────┴──────┐  │
│  │              Réseau isolé (RFC 1918)           │  │
│  │              Pas d'accès Internet direct       │  │
│  └────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────┘

La segmentation réseau est fondamentale : les étudiants ne doivent pas pouvoir sortir du périmètre du lab. Les cibles doivent être isolées de l'infrastructure de l'école.

Modules Terraform pour l'infrastructure pédagogique

Structure de base d'un projet Terraform de lab

lab-cyber/
├── main.tf           # Infrastructure principale
├── variables.tf      # Paramètres (nb étudiants, région, image)
├── outputs.tf        # IPs, noms de VMs
├── modules/
│   ├── student-vm/   # Module VM étudiant
│   └── target-vm/    # Module VM cible
└── environments/
    ├── pentest/      # Config spécifique module pentest
    └── web-security/ # Config spécifique module sécurité web

Exemple : VM étudiant sur AWS (Terraform HCL)

# variables.tf
variable "student_count" {
  description = "Nombre de VMs étudiants à créer"
  type        = number
  default     = 30
}

variable "lab_name" {
  description = "Identifiant du lab (ex: pentest-2026-s2)"
  type        = string
}

variable "student_instance_type" {
  type    = string
  default = "t3.medium"  # 2 vCPU, 4 Go RAM — suffisant pour Kali + outils
}
# main.tf
resource "aws_instance" "student" {
  count         = var.student_count
  ami           = data.aws_ami.kali.id
  instance_type = var.student_instance_type

  subnet_id              = aws_subnet.student.id
  vpc_security_group_ids = [aws_security_group.student.id]
  key_name               = aws_key_pair.lab.key_name

  tags = {
    Name        = "${var.lab_name}-etudiant-${count.index + 1}"
    Environment = "pedagogique"
    Lab         = var.lab_name
  }
}

# Snapshot post-provisionnement (référence pour le reset)
resource "aws_ami_from_instance" "student_base" {
  count              = 1
  name               = "${var.lab_name}-base"
  source_instance_id = aws_instance.student[0].id
  depends_on         = [null_resource.ansible_provision]
}

Points importants pour le contexte scolaire

  • Nommer systématiquement les ressources avec le nom du lab et la promotion : cela évite les orphans en fin d'année.
  • Utiliser des tags pour les politiques de facturation et la traçabilité.
  • Limiter les droits IAM du compte Terraform au strict nécessaire (EC2, VPC, IAM restreint) : ne pas utiliser de compte admin.
  • Planifier la destruction automatique : un lab oublié en production accumule des coûts. Ajouter une ressource aws_cloudwatch_event_rule pour déclencher terraform destroy à J+7 si non reconduit.

Rôles Ansible pour le provisionnement et le durcissement

Ansible configure les VMs après leur création par Terraform. Un rôle Ansible se compose de tâches, de templates et de variables organisés en répertoires standardisés.

Rôle "student-kali" : configuration de la VM étudiant

# roles/student-kali/tasks/main.yml
---
- name: Mise à jour des paquets
  apt:
    update_cache: yes
    upgrade: dist

- name: Installation des outils de base
  apt:
    name:
      - nmap
      - burpsuite
      - metasploit-framework
      - gobuster
      - john
      - hashcat
    state: present

- name: Création du compte étudiant
  user:
    name: "etudiant"
    password: "{{ student_password | password_hash('sha512') }}"
    shell: /bin/bash
    groups: sudo
    append: yes

- name: Copie du répertoire de TP
  copy:
    src: "files/tp-{{ lab_name }}/"
    dest: "/home/etudiant/TP/"
    owner: etudiant
    group: etudiant
    mode: '0755'

- name: Désactivation de l'historique bash persistant
  lineinfile:
    path: /home/etudiant/.bashrc
    line: "export HISTFILE=/dev/null"

Rôle "target-web" : machine cible avec vulnérabilités intentionnelles

# roles/target-web/tasks/main.yml
---
- name: Installation de l'application vulnérable
  apt:
    name:
      - docker.io
      - docker-compose
    state: present

- name: Déploiement de DVWA (Damn Vulnerable Web Application)
  docker_compose:
    project_src: /opt/dvwa
    state: present

- name: Configuration de DVWA en mode low (niveau débutant)
  lineinfile:
    path: /opt/dvwa/config/config.inc.php
    regexp: "^.*security.*"
    line: "$_DVWA[ 'default_security_level' ] = 'low';"

- name: Désactivation des mises à jour automatiques
  service:
    name: unattended-upgrades
    state: stopped
    enabled: no
  # Intentionnel : la machine cible ne doit pas se patcher toute seule

Attention : les machines cibles doivent être isolées sur un VLAN distinct. Ne jamais déployer une application intentionnellement vulnérable sur un réseau accessible depuis Internet.

Inventory dynamique : mapper les VMs Terraform aux groupes Ansible

# inventory/lab.ini (généré par Terraform output)
[students]
etudiant-01 ansible_host=10.0.1.1
etudiant-02 ansible_host=10.0.1.2
# ... (générable avec `terraform output -json | jq ...`)

[targets]
cible-web ansible_host=10.0.2.10
cible-ad  ansible_host=10.0.2.20

Terraform peut générer cet inventaire automatiquement via un output formaté :

# outputs.tf
output "ansible_inventory" {
  value = templatefile("${path.module}/inventory.tpl", {
    student_ips = aws_instance.student[*].private_ip
    target_ips  = aws_instance.target[*].private_ip
  })
}

Reset entre promotions : le pattern "snapshot + destroy + rebuild"

Le reset est l'opération la plus fréquente dans un lab pédagogique. Voici le pattern recommandé :

Phase 1 : snapshot de référence (fin de provisionnement initial)

Après que le lab est provisionné et validé par l'enseignant, créer un snapshot de chaque VM. Ce snapshot est la "référence propre" qui sert de base pour tous les resets ultérieurs.

# Script de snapshot (exemple AWS CLI)
#!/bin/bash
LAB_NAME=$1
for instance_id in $(aws ec2 describe-instances \
  --filters "Name=tag:Lab,Values=$LAB_NAME" \
  --query 'Reservations[*].Instances[*].InstanceId' \
  --output text); do
  aws ec2 create-image \
    --instance-id $instance_id \
    --name "${LAB_NAME}-snapshot-$(date +%Y%m%d)" \
    --description "Snapshot de référence lab $LAB_NAME"
done

Phase 2 : reset entre séances (intra-promotion)

Pour remettre les VMs à l'état initial entre deux séances :

# Playbook Ansible de reset léger
ansible-playbook reset-session.yml \
  -i inventory/lab.ini \
  -e "lab_name=pentest-2026-s2"
# reset-session.yml
---
- name: Reset des VMs étudiants entre séances
  hosts: students
  become: yes
  tasks:
    - name: Suppression des fichiers de TP précédents
      file:
        path: /home/etudiant/TP/
        state: absent

    - name: Recréation du répertoire TP propre
      file:
        path: /home/etudiant/TP/
        state: directory
        owner: etudiant

    - name: Copie des nouveaux exercices
      copy:
        src: "files/tp-seance-{{ seance_number }}/"
        dest: "/home/etudiant/TP/"

Phase 3 : rebuild complet (changement de promotion)

Pour une nouvelle promotion, un rebuild complet depuis les modules Terraform est préférable à un patch sur l'existant :

# Destruction du lab précédent
terraform destroy -var="lab_name=pentest-2025-s2" -auto-approve

# Recréation pour la nouvelle promotion
terraform apply -var="lab_name=pentest-2026-s1" \
               -var="student_count=28" \
               -auto-approve

# Provisionnement Ansible
ansible-playbook setup.yml -i inventory/lab.ini

Avantage : repartir d'une infrastructure propre garantit qu'aucun résidu de configuration de la promotion précédente ne subsiste.

Gestion des secrets et bonnes pratiques

La gestion des secrets est le point le plus souvent négligé dans les labs pédagogiques. Les erreurs fréquentes : committer des mots de passe dans Git, utiliser le même credential pour tous les étudiants et pour l'administration, ou utiliser des comptes cloud personnels pour le lab.

Règles minimales pour un lab scolaire

  1. Jamais de secrets dans Git : ajouter un .gitignore qui exclut *.tfvars, *.env, vault.yml et tout fichier contenant password ou secret dans le nom.

  2. Ansible Vault pour les credentials de provisionnement :

# Chiffrement du fichier de secrets
ansible-vault encrypt secrets.yml

# Lancement du playbook avec déchiffrement
ansible-playbook setup.yml --ask-vault-pass
  1. Secrets de lab distincts des secrets réels : les mots de passe des VMs de lab (souvent volontairement faibles pour les TP) ne doivent jamais être réutilisés sur des systèmes de production.

  2. Rotation des credentials entre promotions : le rebuild complet garantit cette rotation. Si un étudiant a eu accès aux credentials de lab, ils ne doivent pas subsister la saison suivante.

  3. Compte AWS/Azure dédié au lab : créer un compte séparé (AWS Organizations ou Azure Subscription) avec un plafond de budget (aws_budgets_budget) pour éviter les surprises de facturation.

Intégration dans un cours DevSecOps

L'automatisation des labs est aussi un excellent support pédagogique en soi, notamment pour un cours DevSecOps. Les étudiants peuvent :

  • Auditer les modules Terraform pour identifier des mauvaises pratiques de sécurité (groupe de sécurité trop permissif, port 22 ouvert au monde, secrets en clair dans user_data).
  • Écrire des tests d'infrastructure avec terraform validate et tflint.
  • Implémenter un pipeline CI/CD qui valide le code Terraform avant déploiement.
  • Comparer le coût estimé de deux architectures avec infracost.

C'est le même code que celui qui tourne en production chez les entreprises, ce qui donne au lab une dimension directement professionnalisante. Le profil de DevOps sécurité est le débouché naturel de cette compétence.

Pour les modules orientés sécurité cloud, les mêmes patterns s'appliquent avec des modules spécifiques à AWS, Azure ou GCP, et la certification AWS Security Specialty peut servir de repère pour calibrer le niveau des TP.

Coûts et optimisation budgétaire d'un lab cloud

Un lab de 30 étudiants sur AWS pendant une semaine a un coût réel qui mérite d'être planifié. Voici les principaux postes et leviers d'optimisation.

Estimation indicative (AWS, 30 étudiants, 5 jours de TP)

RessourceTypeCoût estimé / heureUsage (5 jours × 4h)
VM étudiant (Kali)t3.medium~0,04 $/h30 × 20h = 600h → ~24 $
VM cible Webt3.small~0,02 $/h1 × 20h = 20h → ~0,4 $
VM cible ADt3.medium~0,04 $/h1 × 20h = 20h → ~0,8 $
Stockage EBS20 Go/VM~0,10 $/Go/mois30 × 20 Go → ~6 $
Trafic réseauSortant~0,09 $/GoVariable → ~5 $

Total estimé pour 30 étudiants, 5 jours : 35-50 $ selon l'utilisation réelle. C'est un ordre de grandeur, à valider avec votre console de facturation et les tarifs actuels d'AWS.

Leviers d'optimisation

  • Arrêter les VMs hors créneaux de TP : via un EventBridge schedule (aws ec2 stop-instances) à la fin de chaque séance. L'économie est proportionnelle au ratio temps arrêté / temps total.
  • Utiliser les Spot Instances pour les VMs étudiants : moins cher (40-70 % de réduction), acceptable pour un lab pédagogique où une interruption occasionnelle est tolérable. Éviter les Spot Instances pour les VMs cibles (risque de perte d'état en cours de TP).
  • Demander des crédits éducatifs : AWS Educate, Azure for Education et Google for Education proposent des crédits annuels pour les établissements d'enseignement supérieur. Contacter le représentant commercial éducation du fournisseur.
  • Partager une même infrastructure entre plusieurs modules si le calendrier le permet.

On-prem vs cloud : le bon choix selon le contexte

Si l'école dispose déjà d'une infrastructure Proxmox ou VMware en état de marche, l'automatisation on-prem avec Ansible seul (sans Terraform) est souvent plus simple et moins coûteuse pour des labs récurrents. Terraform et le cloud prennent tout leur intérêt pour les labs éphémères (événements CTF, formations ponctuelles) ou pour simuler des environnements cloud natifs dans les cours de sécurité cloud.

Ce qu'il faut retenir

  • Terraform + Ansible forment un duo complémentaire : Terraform crée l'infrastructure, Ansible configure les systèmes. Les deux ensemble rendent le lab reproductible et réinitialisable en quelques minutes.
  • L'architecture en trois zones (admin, cibles, étudiants) et l'isolation réseau sont non négociables dans un contexte scolaire : aucune VM cible intentionnellement vulnérable ne doit être accessible depuis Internet.
  • Le pattern snapshot + destroy + rebuild garantit un reset propre entre promotions et élimine les résidus de configuration.
  • La gestion des secrets suit une règle simple : jamais dans Git, Ansible Vault pour le provisionnement, comptes dédiés au lab, rotation systématique entre promotions.
  • L'IaC de lab est aussi un support pédagogique pour les cours DevSecOps : les étudiants apprennent en auditant et en améliorant le code qui fait tourner leur propre environnement.

Vous cherchez un intervenant capable d'animer des TP de sécurité cloud ou de DevSecOps avec une infrastructure automatisée ? Retrouvez les formateurs spécialisés en sécurité cloud et IaC sur Cyber Teachers.

Tous les articles →

Transformez vos formations cybersécurité avec des experts

Expert qualifié en 24h • Formation sur-mesure • Consultation gratuite

Cyber Teachers