Date de publication : 8 juin 2026

Temps de lecture : 14 min

Créez un framework de tests de détection automatisés avec GitLab CI/CD et GitLab Duo

Découvrez comment l'équipe Signals Engineering de GitLab a conçu le framework WATCH pour valider en continu son pipeline de surveillance de sécurité.

Lorsqu'il s'agit de maintenir un système d'alerte sain au sein de votre centre des opérations de sécurité (SOC), le réglage des faux positifs ne suffit pas à lui seul. Un aspect souvent négligé de ce système est de s'assurer que les détections critiques, celles qui se déclenchent rarement, n'ont pas tout simplement cessé de fonctionner sans que personne ne s'en aperçoive.

Chez GitLab, l'équipe Signals Engineering teste les détections en simulant des comportements malveillants réels sur une infrastructure qui nous appartient, afin de valider le fonctionnement de bout en bout de nos détections : de la source des logs à l'ingestion, en passant par le système de gestion des informations et des événements de sécurité (SIEM), jusqu'au routage des alertes via notre système Security Orchestration, Automation and Response (SOAR). C'est l'approche adoptée par les outils commerciaux de simulation de brèches et d'attaques, mais ces solutions sont coûteuses, génériques et inadaptées à notre pile de détection spécifique. Nous avons donc construit notre propre framework entièrement automatisé, que nous avons baptisé WATCH (Weekly Attack Testing for Continuous Health).

Dans cet article, vous découvrirez pourquoi nous avons développé ce framework, comment il fonctionne et comment l'utiliser dans votre propre environnement.

Une lacune dans la validation des détections

Entre les modifications de schéma de logs, les mises à jour du SIEM et les erreurs de configuration des pipelines, il existe une multitude de façons pour que vos détections échouent en silence, mais une seule pour qu’elles se déclenchent comme prévu. Face à cette situation, une conclusion s'impose : il nous faut déclencher d'anciennes détections. Cette solution soulève cependant les questions suivantes : « Comment déclencher concrètement des détections ? » et « À quelle fréquence ? »

Une première approche consiste à réintroduire dans votre SIEM des logs qui simulent un comportement malveillant, puis à vérifier si votre règle de détection identifie le faux incident et déclenche une alerte. Cette approche, en plus de ne pas prouver le fonctionnement de la détection en conditions réelles, ne valide pas l'une des étapes les plus sujettes aux erreurs du cycle de vie des alertes : l'ingestion des logs (c'est-à-dire de la source du log au SIEM).

Nous avons précédemment décrit comment notre système GitLab Universal Automated Response and Detection (GUARD) automatise la création et le déploiement des détections via un pipeline de détections en tant que code (DaC), ainsi que le routage et le classement des alertes via notre SOAR. Nos pipelines DaC résolvent le problème de la validation du déploiement d'une détection sans erreur, mais ne répondent pas à la question de savoir si cette détection se déclenchera réellement lorsque le comportement ciblé se produira en conditions réelles.

Le framework WATCH comble cette lacune : il s'agit de la couche de validation continue qui confirme que nos détections fonctionnent correctement.

Fonctionnement du framework WATCH

À un niveau global, le framework WATCH fonctionne en exécutant des simulations d'attaques scriptées dans notre environnement de préproduction, puis en vérifiant que les alertes attendues se propagent à travers l'ensemble de notre pile de surveillance de sécurité : le SIEM pour les règles de détection, le SOAR pour le routage des alertes, et enfin les tableaux de bord utilisés par notre équipe pour surveiller l'état des détections.

Le cycle de vie d'un test WATCH se déroule comme suit :

  1. Planification : chaque semaine, un pipeline GitLab CI/CD planifié découvre tous les tests actifs et les répartit dans des créneaux horaires aléatoires tout au long de la semaine. Cette randomisation est essentielle : nous ne voulons pas que les tests se déclenchent à des moments prévisibles, ce qui faciliterait la distinction entre l'activité de test et les menaces réelles, et pourrait masquer des problèmes liés à la temporalité dans nos détections.
  2. Notification préalable : avant l'exécution d'un test, WATCH notifie notre SOAR via une story dédiée « WATCH Heads Up » qui enregistre les détections qu'il prévoit de déclencher. Des enregistrements traçables sont créés pour que notre SOAR puisse anticiper la suite des événements.
  3. Exécution : le test lance le comportement malveillant simulé. Par exemple, il réinitialise le mot de passe d'un compte administrateur ou effectue des appels API suspects sur l'environnement de préproduction.
  4. Détection : le SIEM traite les logs d'activité de l'environnement de préproduction et déclenche (en principe) les règles de détection correspondantes.
  5. Corrélation : à mesure que les alertes arrivent dans notre SOAR, une vérification qui vise à identifier les tests WATCH détermine si chaque alerte correspond à un test enregistré en s'appuyant sur trois facteurs : la fenêtre temporelle entre l'exécution du test et l'alerte, l'identité de l'acteur (adresse IP ou nom d'utilisateur) et l'identifiant de la règle de détection déclenchée. C'est ce mécanisme qui empêche les alertes générées par WATCH d'être escaladées comme de vrais incidents auprès de l'équipe Security Incident Response Team (SIRT), tout en validant l'ensemble du pipeline.
  6. Vérification : une étape ultérieure du pipeline vérifie si toutes les détections attendues se sont déclenchées, met à jour les métadonnées de statut des détections et déploie les résultats mis à jour sur notre tableau de bord GitLab Pages. Si une détection ne se déclenche pas, une notification est envoyée sur le canal Slack de notre équipe.

Utilisation du framework WATCH avec GitLab CI/CD

WATCH s'appuie sur GitLab CI/CD et l'utilise comme colonne vertébrale d'orchestration à travers trois étapes de pipeline.

L'étape schedule_pipelines s'exécute chaque semaine et gère la répartition des tests. Elle repère tous les tests actifs, les regroupe par lots et crée des pipelines planifiés configurés pour s'exécuter à des moments aléatoires au cours de la semaine. Chaque pipeline planifié reçoit une variable TESTS_TO_RUN qui précise les tests à exécuter.

L'étape run_tests est celle où la simulation d'attaque a lieu. Elle exécute les tests assignés au pipeline en cours, enregistre les statistiques d'exécution dans detection_status.json et consigne les identifiants des enregistrements SOAR pour permettre la corrélation des alertes en aval.

L'étape pages gère la vérification et le reporting. Elle interroge notre SOAR pour confirmer que les alertes ont été générées et correctement acheminées, met à jour les métadonnées de détection avec les résultats de vérification et déploie le tableau de bord GitLab Pages avec les derniers résultats de tests.

Voici un exemple de fichier de configuration GitLab CI/CD gitlab-ci.yml pour le pipeline WATCH :

      spec:
  inputs:
    weekly_scheduling:
      type: boolean
      default: false
      description: "Enable weekly scheduling of detection tests."
    update_pages:
      type: boolean
      default: false
      description: "For triggering the update of GitLab Pages dashboard."

---

# Specify the Docker image to use for the job
image: python:3.12

stages:
  - schedule_pipelines
  - run_tests
  - pages

# Job to manage scheduled pipelines (runs when weekly_scheduling input is true)
manage_scheduled_pipelines:
  stage: schedule_pipelines
  script:
    - pip install -r requirements.txt
    - python scripts/manage_scheduled_pipelines.py
  rules:
    - if: $TESTS_TO_RUN == null && $CI_PIPELINE_SOURCE == "schedule" && [[ inputs.weekly_scheduling ]] == true
      when: on_success
    - when: never

# Job to run detection tests, save tines_record_id to detection_status.json, and commit
run_detection_tests:
  stage: run_tests
  script:
    - pip install -r requirements.txt
    - python main.py --prod --save-stats --scheduled-tests
  rules:
    - if: $TESTS_TO_RUN
      when: on_success
    - when: never

# Job to verify alerts, update detection_status.json, commit, and deploy pages
pages:
  stage: pages
  script:
    - pip install -r requirements.txt
    - python scripts/verify_and_update_detections.py --tines-api-key ${TINES_API_KEY}
    - mkdir -p public/data
    - cp detection_status.json public/data/
    - cp -r static/* public/
  pages: true  # Required for GitLab 17.9+ to trigger Pages deployment
  artifacts:
    paths:
      - public
  rules:
    - if: $TESTS_TO_RUN == null && [[ inputs.update_pages ]] == true
      when: on_success
    - when: never

    

Rédaction de tests avec GitLab Duo

L'une des priorités de conception de WATCH était de faciliter l'ajout de nouveaux tests par n'importe quel membre de l'équipe Signals Engineering ou SIRT. Le framework fournit une classe abstraite BaseSecurityTest qui prend en charge toutes les tâches répétitives (génération de l'identifiant de test, gestion de l'identité de l'acteur, coordination avec le SOAR) de sorte que les auteurs de tests n'ont qu'à se concentrer sur trois aspects : la préparation de l'environnement de test, l'exécution du comportement malveillant simulé et le nettoyage post-test.

      class BaseSecurityTest(ABC):

    def __init__(self, config = {}, test_id: Optional[str] = None):
        self.test_id = test_id or str(uuid.uuid4())
        self.test_name = self.__class__.__name__
        self.expected_detections = {}
        self.actor_id = config.get('gitlab', {}).get(
            'default_actor_id',
            "sirt_detection_test_user_" + self.test_id[:8]
        )
        self.isActive = True
        self.test_run_time = 300
        self.config = config

    @abstractmethod
    def setup(self) -> bool:
        """Prepare test environment and resources"""

    @abstractmethod
    def execute(self) -> Dict[str, Any]:
        """Execute the malicious behavior simulation"""

    @abstractmethod
    def cleanup(self) -> bool:
        """Clean up test environment and resources"""

    

L'élément de configuration clé est le dictionnaire expected_detections, qui associe les noms de règles SIEM des détections attendues à l'identité de l'acteur et à l'heure d'arrivée prévue de l'alerte. Un nouveau test est simplement un fichier Python dans le répertoire tests/ qui hérite de BaseSecurityTest, définit son comportement simulé et déclare les détections qu'il prévoit de déclencher. Le runner de tests le détecte automatiquement lors de la prochaine exécution planifiée.

Cette interface à faible friction est essentielle, car les tests de détection ne fonctionnent en tant que pratique que si l'équipe rédige réellement des tests. Si l'ajout d'un test nécessite de comprendre l'intégralité des mécanismes internes du pipeline, personne ne le fera. Le contrat simple consistant à implémenter setup, execute et cleanup, et à déclarer les détections attendues, fait également des tests WATCH d'excellents candidats pour GitLab Duo, l'assistant d'IA de GitLab. Il vous suffit d'indiquer à GitLab Duo la classe de base et un prompt tel que « Crée-moi un test qui clone un grand nombre de projets à partir d'un groupe cible » ou « Crée-moi un test qui accède à toutes les variables CI de ce projet via GraphQL », voire « Renomme tous ces projets pour utiliser le même schéma de nommage ». GitLab Duo peut alors générer un test WATCH fonctionnel qui s'intègre directement au framework et simplifie encore davantage l'accessibilité. Un ingénieur qui souhaite tester une détection peut rapidement passer de l'idée à un test opérationnel, car GitLab Duo prend en charge l'essentiel de l'implémentation.

Astuce : pour renforcer l'efficacité de GitLab Duo, nous avons utilisé l'agent Skills, qui est idéal pour définir des normes et des procédures pour les tâches récurrentes comme la rédaction de tests. Dans le répertoire de notre projet se trouve un dossier skills/WATCH-test-creator contenant un fichier SKILL.md qui décrit les caractéristiques d'un bon test, les fonctions utilitaires disponibles et la finalité du projet. Ce fichier est lu immédiatement après la saisie d'un prompt comme ceux mentionnés ci-dessus, ce qui évite de devoir rappeler constamment à GitLab Duo le contexte de travail et la méthodologie à suivre. Surtout, les résultats obtenus sont cohérents et de meilleure qualité. Voici un extrait de ce fichier :

      ---
name: WATCH-test-creator
description: Create WATCH (Orchestrated Offensive Penetration Simulator) security detection tests that simulate malicious behavior on GitLab infrastructure to validate SIEM detection rules and alerting pipelines.
---

## WATCH Test Creator

You are an expert at writing security detection tests for the WATCH framework. WATCH tests simulate malicious activities on GitLab-owned infrastructure to verify that the SecOps security monitoring stack (Elastic SIEM, Tines SOAR, alerting rules) properly detects and responds to threats.

### Architecture Overview
```
Project Root
├── core/
│   ├── base_test.py          # Abstract base class all tests inherit from
│   ├── test_runner.py         # Auto-discovers and executes tests
│   └── webhook_manager.py     # Tines/SOAR notification integration
├── tests/
│   ├── gitlab/                # GitLab-specific detection tests
│   └── gcp/                   # GCP-specific detection tests
├── utils/
│   ├── gitlab_helper.py       # GitLab API wrapper (users, projects, tokens, webhooks, OAuth)
│   └── crypto_utils.py        # Password generation utility
├── config/
│   ├── settings.py            # Config loader (reads YAML + GITLAB_ADMIN_PAT env var)
│   └── environments/
│       ├── dev.yaml           # Local GDK config
│       └── prod.yaml          # Production staging.gitlab.com config
├── main.py                    # Entry point with CLI args
└── detection_status.json      # Test results and detection metadata
```


    

Visibilité renforcée grâce aux tableaux de bord de tests

Tableaux de bord de tests

WATCH déploie également deux tableaux de bord interactifs via GitLab Pages qui offrent à l'équipe une visibilité en temps réel sur l'état des détections.

  • Le tableau de bord de statut des détections fournit une vue d'ensemble de toutes les règles de détection et de leur statut de test actuel, y compris des indicateurs tels que le nombre de déclenchements de chaque détection, son état de réussite/échec actuel et sa durée d'activité. Le tableau est filtrable et triable et permet aux ingénieurs d'identifier rapidement les détections qui requièrent une attention particulière.
  • Le tableau de bord d'exécution des tests offre une vue détaillée des exécutions de tests individuels, regroupées par identifiant de test avec des analyses de couverture de détection. Il inclut une visualisation chronologique des délais de propagation des alertes pour aider à évaluer le temps écoulé entre l'exécution du test et la réception de l'alerte, ainsi que des liens directs vers les alertes correspondantes dans notre SIEM.

Ces tableaux de bord ont remplacé un processus auparavant manuel qui consistait à consulter les logs des pipelines et les requêtes SIEM pour déterminer si nos détections étaient opérationnelles.

Comme le reste de GUARD, WATCH s'appuie fortement sur GitLab en tant que plateforme :

  • Les pipelines GitLab CI/CD et les pipelines planifiés orchestrent l'ensemble du cycle de vie des tests, de la planification hebdomadaire à l'exécution et au déploiement des tableaux de bord.
  • Les données d'entrée de pipeline permettent de déclencher les étapes indépendamment : il est possible de relancer uniquement l'étape de vérification ou la mise à jour du tableau de bord sans exécuter à nouveau l'ensemble des tests.
  • Les variables CI/CD stockent de manière sécurisée les clés API nécessaires pour accéder à Tines et à l'environnement de préproduction GitLab.
  • GitLab Pages héberge les tableaux de bord WATCH sans infrastructure supplémentaire, ce qui signifie aucun hébergement distinct à gérer, aucun outil de déploiement additionnel.
  • Étant donné que les tests sont de simples fichiers Python dans un projet GitLab, ils bénéficient du contrôle de version, des revues de merge request et de la propriété du code, tout comme nos règles de détection dans le cadre du DaC.

WATCH nous permet de rester proactifs

La mise en place du framework WATCH a transformé la relation de notre équipe avec la qualité des détections, passant d'une posture réactive à une posture proactive. Avant WATCH, une détection défaillante ne se manifestait que lors d'un incident, lorsque l'alerte attendue était absente, soit le pire moment possible pour découvrir une lacune. Désormais, nous recevons des mises à jour régulières sur l'état de santé de nos détections et savons quand elles cessent de fonctionner avant qu'un problème réel ne survienne. C'est la garantie que les nouvelles détections développées ne seront pas défaillantes puis oubliées.

Un autre avantage de WATCH est l'enregistrement des tactiques, techniques et procédures (TTP) utilisées par notre red team lors d'opérations flash. Une fois les détections implémentées et l'analyse rétrospective d'une opération de test de pénétration réalisée, WATCH peut être utilisé pour rejouer les TTP utilisées afin de valider ces détections. En substance, WATCH transforme les tests atomiques de détection en TTP réutilisables.

Essayez le framework WATCH

Si vous gérez un SOC et que vous comptez sur les détections SIEM pour identifier les menaces, la question n'est pas de savoir si vos détections échoueront, mais si vous le saurez quand cela arrivera. Vous n'avez pas besoin d'une plateforme commerciale de simulation de brèches et d'attaques pour commencer à répondre à cette question. Un environnement sandbox, un pipeline CI/CD et un framework de scripts de simulation d'attaques sont d'excellents points de départ.

Commencez à construire votre propre framework de tests de détection en essayant gratuitement GitLab Ultimate.

Donnez-nous votre avis

Cet article de blog vous a plu ? Vous avez des questions ou des retours à nous faire ? Donnez votre avis en créant un nouveau sujet sur le forum de la communauté GitLab.

Faites-nous part de vos commentaires

Commencez à développer plus rapidement dès aujourd'hui

Découvrez ce que votre équipe peut accomplir avec la plateforme d'orchestration intelligente pour le DevSecOps.