L'emplacement des quality gates dans votre pipeline importe plus que ce que vous scannez
Vous poussez un commit. Le pipeline démarre. Vous attendez. Et vous attendez. Au bout de quinze minutes, le pipeline échoue à cause d'une vulnérabilité de faible sévérité dans une bibliothèque que votre code n'utilise même pas. Vous corrigez, repoussez, et attendez encore quinze minutes.
C'est le prix à payer quand on place tous les quality gates au même endroit dans le pipeline. L'alternative est tout aussi frustrante : tous les scans s'exécutent à la toute fin, juste avant la production. Votre code passe la compilation, les tests unitaires, les tests d'intégration et le staging. Puis il échoue parce qu'un secret codé en dur traînait dans un fichier de configuration depuis le premier commit. Vous venez de gaspiller des heures de temps pipeline sur quelque chose qui aurait pu être détecté en quelques secondes.
La position de chaque gate détermine deux choses : la rapidité avec laquelle les développeurs reçoivent un retour, et le temps et les ressources de calcul gaspillés en cas d'échec. Bien faire les choses ne consiste pas à choisir entre vitesse et sécurité. Il s'agit d'ordonner les vérifications pour qu'elles fonctionnent ensemble.
Rapide et léger d'abord, lourd ensuite
Le principe de base est simple : les vérifications rapides et légères s'exécutent tôt dans le pipeline. Les vérifications lourdes qui nécessitent plus de contexte s'exécutent plus tard. Mais il ne s'agit pas simplement de diviser les scans en deux groupes. Chaque type de scan a une place naturelle où il apporte le plus de valeur avec le moins de friction.
Le diagramme ci-dessous associe chaque gate à son étape recommandée dans le pipeline :
Secret Scan : à exécuter avant le build
Les secrets doivent être détectés avant que quoi que ce soit ne soit compilé ou construit. Une fois qu'un secret est intégré dans une image conteneur ou un artefact, le supprimer devient beaucoup plus difficile. L'image a peut-être déjà été poussée vers un registre, tirée par d'autres systèmes, ou déployée dans un environnement. Même si vous supprimez l'image, le secret peut être mis en cache ou journalisé quelque part.
Exécutez la détection de secrets juste après le checkout du code, avant toute étape de build. Si le pipeline trouve une clé API ou un mot de passe de base de données codé en dur, le développeur reçoit un retour immédiat. Il corrige le fichier, repousse, et le pipeline redémarre sans avoir attendu un build qui aurait de toute façon été gaspillé.
Dependency Scan : avant la création de l'artefact
Le scan des dépendances vérifie les bibliothèques que votre projet importe. Il a besoin du fichier de manifeste des dépendances, qui est disponible juste après le checkout. L'endroit naturel pour ce scan est après le checkout mais avant la construction de l'artefact.
Si une bibliothèque nouvellement ajoutée présente une vulnérabilité critique, le pipeline échoue tôt. Le développeur n'attend pas le build, les tests unitaires ou les tests d'intégration. Il corrige la dépendance et repousse. C'est l'essence même du feedback rapide : échouer rapidement sur des problèmes peu coûteux à corriger.
Certains scanners de dépendances sont assez rapides pour s'exécuter avant le build. D'autres sont plus lents. Si votre scanner prend plusieurs minutes, envisagez de l'exécuter sur chaque commit pour la branche principale uniquement, et sur les pull requests pour les branches de fonctionnalités. Cela maintient un feedback rapide pour le travail quotidien tout en détectant les problèmes avant qu'ils n'atteignent la production.
Container Image Scan : après le build, avant le registre
Le scan d'images conteneur est différent. Vous ne pouvez pas scanner une image tant qu'elle n'existe pas. Le bon endroit est après la construction de l'image, avant qu'elle ne soit poussée vers un registre ou utilisée dans un environnement.
Si l'image contient des vulnérabilités, le pipeline s'arrête ici. L'image n'atteint jamais le staging ou la production. C'est important car une fois qu'une image est dans un registre, d'autres pipelines ou équipes peuvent la tirer. Arrêter le pipeline à ce point empêche la propagation d'images vulnérables.
Le compromis est que le scan d'image prend du temps. Si votre équipe pousse plusieurs commits par jour, exécuter des scans d'image complets sur chaque commit peut ralentir considérablement le pipeline. Une approche courante consiste à exécuter un scan rapide sur chaque commit et un scan complet lors des fusions vers la branche principale. Une autre consiste à mettre en cache les résultats du scan et à ne rescanner que lorsque l'image de base ou les dépendances changent.
IaC Scan et Policy Check : deux endroits, deux objectifs
Le scan de l'infrastructure en tant que code et les vérifications de politiques peuvent s'exécuter à deux moments différents, chacun servant un objectif distinct.
D'abord, exécutez-les lorsque le code d'infrastructure est écrit. Cela donne aux développeurs un feedback rapide pendant qu'ils travaillent encore sur la configuration. Ils n'ont pas besoin d'attendre une exécution complète du pipeline pour savoir qu'une règle de groupe de sécurité est trop permissive ou qu'un bucket de stockage est accessible publiquement.
Ensuite, exécutez-les à nouveau avant que la configuration ne soit appliquée à un environnement. C'est le gate de conformité. Même si le développeur a ignoré l'avertissement précédent, le pipeline applique la politique avant que tout changement d'infrastructure ne prenne effet.
Le premier gate est pour la commodité du développeur. Le second est pour la certitude de conformité. Les deux sont nécessaires, mais ils n'ont pas besoin d'exécuter les mêmes vérifications. Le gate précoce peut exécuter des vérifications plus légères, tandis que le gate tardif exécute la suite complète de politiques.
Ce qu'il faut éviter : un seul gros gate à la fin
Le pire modèle consiste à placer tous les scans dans un seul bloc à la fin du pipeline. Cela crée une longue boucle de feedback pour chaque type de problème. Un secret manquant, une dépendance vulnérable, un fichier IaC mal configuré et une vulnérabilité de conteneur sont tous signalés en même temps, après que le développeur a attendu le build, les tests unitaires, les tests d'intégration et le staging.
Ce modèle rend également le pipeline fragile. Un scan lent bloque tous les autres. Si un scan échoue, le développeur doit corriger le problème et attendre à nouveau l'ensemble du pipeline, y compris toutes les étapes déjà réussies.
Répartissez les gates sur l'ensemble du pipeline afin que chaque étape ait une responsabilité claire. Les premières étapes détectent rapidement les problèmes peu coûteux. Les étapes ultérieures détectent les problèmes coûteux avant qu'ils n'atteignent la production.
Tenir compte du coût du scanning
Certains scans sont coûteux. Les recherches complètes dans les bases de données de dépendances, l'analyse approfondie des conteneurs et les évaluations complètes des politiques peuvent prendre plusieurs minutes et consommer des ressources de calcul importantes. Les exécuter sur chaque commit pour chaque branche est un gaspillage.
La solution n'est pas de sauter les scans. C'est de les placer stratégiquement. Exécutez les scans coûteux uniquement sur la branche principale ou sur les pull requests ciblant la branche principale. Pour les branches de fonctionnalités, exécutez uniquement les vérifications rapides : scan de secrets, scan rapide des dépendances et validation syntaxique. Cela maintient le pipeline rapide pour le travail quotidien tout en appliquant la qualité avant que le code n'atteigne la production.
Liste de contrôle pratique
- Le scan de secrets s'exécute avant le build, juste après le checkout.
- Le scan des dépendances s'exécute avant la création de l'artefact, en utilisant le fichier de manifeste.
- Le scan d'image conteneur s'exécute après le build, avant le push vers le registre.
- Le scan IaC s'exécute à deux moments : pendant le développement et avant l'application sur l'environnement.
- Les scans coûteux s'exécutent uniquement sur la branche principale ou les cibles de fusion.
- Les scans rapides s'exécutent sur chaque commit pour toutes les branches.
L'essentiel à retenir
Un gate bien placé détecte les problèmes tôt, lorsqu'ils sont peu coûteux à corriger. Un gate mal placé détecte les problèmes tard, après que du temps et des ressources de calcul ont été gaspillés. L'objectif n'est pas de tout scanner partout. Il s'agit de placer chaque scan là où il offre le feedback le plus rapide pour les problèmes qu'il est conçu pour détecter. Lorsque vous placez correctement les gates, les développeurs obtiennent des victoires rapides, la conformité obtient ses garanties, et le pipeline reste suffisamment rapide pour que personne ne veuille le contourner.