Aller au contenu
CI/CD & Automatisation medium

Plumber pour GitLab CI/CD : premier scan de conformité

20 min de lecture

Logo Plumber

Si votre pipeline GitLab CI/CD utilise des images Docker non épinglées, des includes sur main ou un build basé sur Docker-in-Docker, vous n’avez pas besoin de commencer par une plateforme complète de gouvernance. Vous avez besoin d’un premier scan clair. Plumber sert à ça : vous créez une configuration minimale, vous lancez plumber analyze, vous lisez trois ou quatre problèmes concrets, puis vous intégrez le contrôle dans GitLab CI/CD avec le composant officiel. Dans ce guide, on commence volontairement par la CLI, ensuite seulement par le composant GitLab, puis on termine par le PBOM, le score A-E et la Platform.

  • Créer une configuration minimale avec plumber config init, puis la valider avant le premier scan
  • Lancer une analyse locale sur un dépôt GitLab et comprendre l’auto-détection du projet
  • Corriger trois erreurs fréquentes : image non épinglée, include mutable, branche non protégée
  • Ajouter le composant GitLab CI/CD officiel sans créer de doubles pipelines ni de job .pre inutilisable
  • Exporter un PBOM et l’exploiter avec Trivy ou Grype

Plumber est un scanner de conformité pour GitLab CI/CD. Il lit votre configuration de pipeline, interroge votre projet GitLab, puis signale les écarts les plus fréquents : images non fiables, tags mutables, branches non protégées, includes obsolètes, scripts téléchargés sans vérification ou usage de Docker-in-Docker.

Votre situationPorte d’entrée recommandéePourquoi
Vous découvrez PlumberCLI localeVous comprenez d’abord ce que l’outil détecte et comment lire la sortie
Vous voulez l’ajouter rapidement à un pipeline existantComposant GitLab CI/CDVous évitez d’écrire un job manuel complet
Vous devez centraliser plusieurs projetsPlatformVous passez de l’analyse projet par projet à la gouvernance

Avant de lancer votre premier scan, vous avez besoin de :

  • un dépôt Git lié à un projet GitLab ;
  • un token GitLab avec les scopes read_api et read_repository ;
  • le rôle Maintainer sur le projet, ou un Project Access Token doté de ce rôle ;
  • un terminal interactif si vous voulez utiliser plumber config init ;
  • au moins une configuration .plumber.yaml si vous passez par la CLI.
Fenêtre de terminal
mise use -g github:getplumber/plumber@0.1.84

Vérification :

Fenêtre de terminal
plumber version

Vous devez voir plumber version 0.1.84 ou une version plus récente.

Le chemin le plus simple est toujours le même : configurer, valider, scanner, corriger.

  1. Créez une configuration minimale avec le wizard interactif

    Fenêtre de terminal
    plumber config init
    plumber config validate

    plumber config init pose des questions ciblées puis génère un fichier court, adapté à votre projet. plumber config validate vérifie ensuite que le YAML est correct et signale les fautes de frappe dans les noms de contrôles ou de clés.

  2. Créez votre token GitLab

    Dans GitLab, ouvrez User Settings -> Access Tokens et créez un token avec read_api et read_repository.

    Fenêtre de terminal
    export GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx
  3. Lancez l’analyse depuis le dépôt Git

    Fenêtre de terminal
    cd mon-projet
    plumber analyze

    Si votre dépôt possède un remote origin pointant vers GitLab, Plumber détecte automatiquement l’URL GitLab et le chemin du projet.

  4. Lisez d’abord le résumé, pas toute la sortie

    Cherchez en priorité :

    • le pourcentage de conformité global ;
    • les contrôles en échec ;
    • les codes ISSUE-XXX ;
    • le nom précis du job concerné.

Sur le dépôt de lab Pipeline Craft, la commande suivante permet d’analyser une branche de solution :

Fenêtre de terminal
plumber analyze --config /tmp/plumber-guide.yaml --branch solution/lab-12 --score-point

Voici le début de la sortie observée :

Auto-detected GitLab URL: https://gitlab.com
Auto-detected project: Bob74/pipeline-craft
Using configuration: /tmp/plumber-guide.yaml
Analyzing project: Bob74/pipeline-craft on https://gitlab.com
Using remote CI configuration from branch: solution/lab-12
✓ [████████████████████] (18/18) Analysis complete

Et le résumé utile à lire :

Status: FAILED
Total (required: 100%): 75.0%
Controls in failure:
- ISSUE-103 ×5 : images non épinglées par digest
- ISSUE-412 ×1 : Docker-in-Docker détecté
- ISSUE-401 ×5 : jobs hardcodés
Plumber Score: E (0.0 / 100 pts)

Le cas le plus fréquent est simple : le dépôt n’a pas de remote origin, ou l’URL du remote ne pointe pas vers GitLab.

Dans ce cas, passez explicitement les paramètres :

Fenêtre de terminal
plumber analyze --gitlab-url https://gitlab.com --project mon-groupe/mon-projet

Quand on débute, il est inutile de mémoriser immédiatement les 14 contrôles. Commencez par ces trois familles d’erreurs. Elles couvrent déjà une grande partie des problèmes visibles sur les pipelines réels.

Dans le lab testé, Plumber a signalé :

HIGH [ISSUE-103] Job 'pytest' uses image without digest pinning: docker.io/python:3.12-slim
HIGH [ISSUE-103] Job 'docker-build' uses image without digest pinning: docker.io/docker:27

Le problème n’est pas seulement l’usage de latest. Un tag de version comme python:3.12-slim reste mutable. Si le registre republie l’image, votre pipeline peut exécuter autre chose demain.

Pour activer le mode strict, la clé se trouve ici :

.plumber.yaml
controls:
containerImageMustNotUseForbiddenTags:
enabled: true
containerImagesMustBePinnedByDigest: true

Un include pointant sur une branche mutable rend votre pipeline difficile à reproduire et peut casser sans changement dans votre dépôt.

Avant
include:
- project: security/templates
file: /pipelines/sast.yml
ref: main
Après
include:
- project: security/templates
file: /pipelines/sast.yml
ref: v2.4.1

Le contrôle associé est includesMustNotUseForbiddenVersions avec ISSUE-404.

Si la branche par défaut n’est pas protégée, un push direct ou une modification non revue peut contourner vos pratiques de revue et de sécurité.

Le contrôle branchMustBeProtected vérifie cela et renvoie ISSUE-501 ou ISSUE-505 selon le problème : absence de protection ou protection incomplète.

Exemple minimal
controls:
branchMustBeProtected:
enabled: true
defaultMustBeProtected: true
namePatterns:
- main
allowForcePush: false

Une quatrième erreur très courante : Docker-in-Docker

Section intitulée « Une quatrième erreur très courante : Docker-in-Docker »

Le lab a également remonté :

HIGH [ISSUE-412] Job 'docker-build' uses DinD service: docker:27-dind
Consider using Kaniko or Buildah instead

Sur des runners partagés, DinD augmente le risque d’évasion de conteneur et de mouvement latéral. Si vous construisez des images, privilégiez Kaniko ou Buildah.

Fichier de configuration : minimal d’abord, complet ensuite

Section intitulée « Fichier de configuration : minimal d’abord, complet ensuite »

Le fichier .plumber.yaml reste volontairement simple au début. Vous n’avez pas besoin d’activer tous les contrôles dès le premier jour.

.plumber.yaml
version: "1.0"
controls:
containerImageMustNotUseForbiddenTags:
enabled: true
tags:
- latest
- dev
- main
containerImagesMustBePinnedByDigest: true
containerImageMustComeFromAuthorizedSources:
enabled: true
trustDockerHubOfficialImages: true
trustedUrls:
- $CI_REGISTRY_IMAGE:*
- registry.gitlab.com/security-products/*
branchMustBeProtected:
enabled: true
defaultMustBeProtected: true
namePatterns:
- main
allowForcePush: false
includesMustNotUseForbiddenVersions:
enabled: true
forbiddenVersions:
- latest
- main
- HEAD
Fenêtre de terminal
# Vérifier le fichier
plumber config validate
# Voir la configuration effective sans commentaires
plumber config view
# Générer le template complet officiel
plumber config generate --output .plumber.yaml --force

Ajouter Plumber à GitLab CI avec le composant officiel

Section intitulée « Ajouter Plumber à GitLab CI avec le composant officiel »

Une fois le premier scan local compris, le bon point d’entrée côté GitLab est le composant CI/CD officiel.

Ajoutez d’abord le token GITLAB_TOKEN dans Settings -> CI/CD -> Variables, puis utilisez ce squelette :

.gitlab-ci.yml
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
when: never
- if: $CI_COMMIT_BRANCH
- if: $CI_COMMIT_TAG
include:
- component: gitlab.com/getplumber/plumber/plumber@v0.1.84

Ce bloc workflow:rules évite de créer à la fois un pipeline de branche et un pipeline de merge request sur le même push.

.gitlab-ci.yml
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
when: never
- if: $CI_COMMIT_BRANCH
- if: $CI_COMMIT_TAG
include:
- component: gitlab.com/getplumber/plumber/plumber@v0.1.84
inputs:
stage: test
threshold: 80
config_file: .plumber.yaml
pbom_file: plumber-pbom.json
pbom_cyclonedx_file: plumber-cyclonedx-sbom.json

Le composant recherche la configuration dans cet ordre :

  1. l’input config_file s’il est défini ;
  2. le fichier .plumber.yaml à la racine du dépôt ;
  3. la configuration par défaut embarquée dans l’image.

Gardez cette variante pour les besoins spécifiques. Si vous voulez ajouter --mr-comment et --badge dans un job manuel, séparez-les en deux jobs : le commentaire de merge request n’a de sens qu’en pipeline de MR, et le badge ne se met à jour que sur la branche par défaut.

Sur un GitLab auto-hébergé, vous ne pouvez pas consommer directement le composant depuis gitlab.com. Le chemin correct est le suivant :

  1. Importez le dépôt https://gitlab.com/getplumber/plumber.git dans votre instance.

  2. Activez le CI/CD Catalog dans le projet importé.

  3. Publiez une release en lançant un pipeline sur un tag déjà importé, par exemple v0.1.84.

  4. Consommez ensuite le composant local dans vos pipelines.

.gitlab-ci.yml
include:
- component: gitlab.example.com/infrastructure/plumber/plumber@v0.1.84

Une fois la lecture du scan comprise, vous pouvez passer au PBOM.

Le PBOM (Pipeline Bill of Materials) est l’inventaire des dépendances de votre pipeline : images Docker, composants GitLab, templates et includes.

Fenêtre de terminal
plumber analyze \
--pbom plumber-pbom.json \
--pbom-cyclonedx plumber-cyclonedx-sbom.json
FormatQuand l’utiliserCe qu’il contient
PBOM natifVous voulez comprendre le pipeline en détailMétadonnées riches propres à Plumber
CycloneDXVous voulez brancher un autre outilFormat standard pour Trivy, Grype ou Dependency-Track
Fenêtre de terminal
trivy sbom plumber-cyclonedx-sbom.json --severity HIGH,CRITICAL
Fenêtre de terminal
grype sbom:plumber-cyclonedx-sbom.json --fail-on high

À ce stade, vous savez déjà lancer Plumber et lire les erreurs les plus utiles. Les fonctionnalités suivantes sont pratiques, mais elles ne doivent pas être votre point d’entrée.

Fenêtre de terminal
plumber explain ISSUE-412
# raccourci accepté : plumber explain 412

Cette commande renvoie :

  • la description du problème ;
  • son impact ;
  • la remédiation ;
  • le lien vers la documentation officielle.
Fenêtre de terminal
plumber analyze --score
plumber analyze --score-point

Sur Pipeline Craft, le scan de solution/lab-12 a produit :

Plumber Score: E
Final points: 0.0 / 100
High: 6
Medium: 5

Le score sert à prioriser. Il ne remplace pas la lecture des contrôles en échec.

Fenêtre de terminal
# Uniquement les images et la protection de branche
plumber analyze --controls containerImageMustNotUseForbiddenTags,branchMustBeProtected
# Tout sauf la protection de branche
plumber analyze --skip-controls branchMustBeProtected

Avec le composant GitLab, activez-les ainsi :

.gitlab-ci.yml
include:
- component: gitlab.com/getplumber/plumber/plumber@v0.1.84
inputs:
mr_comment: true
badge: true

La Platform n’est pas le bon point de départ pour un débutant. Elle devient pertinente quand vous devez :

  • suivre plusieurs projets dans le temps ;
  • disposer d’un tableau de bord centralisé ;
  • gérer des politiques communes à plusieurs équipes ;
  • auditer des variables, des quotas ou des règles de merge request à plus grande échelle.
ContrôleCode principalÀ quoi il sert
containerImageMustNotUseForbiddenTagsISSUE-102Bloque les tags mutables comme latest ou dev
containerImageMustComeFromAuthorizedSourcesISSUE-101Limite les images aux registries autorisés
branchMustBeProtectedISSUE-501 / 505Vérifie la protection des branches critiques
pipelineMustNotIncludeHardcodedJobsISSUE-401Détecte les jobs définis directement dans le YAML
includesMustBeUpToDateISSUE-403Contrôle que les includes ne sont pas obsolètes
includesMustNotUseForbiddenVersionsISSUE-404Interdit les refs mutables comme main ou HEAD
pipelineMustIncludeComponentISSUE-408 / 409Imposent des composants GitLab obligatoires
pipelineMustIncludeTemplateISSUE-405 / 406Imposent des templates GitLab obligatoires
pipelineMustNotEnableDebugTraceISSUE-203Empêche l’exposition des secrets dans les logs
pipelineMustNotUseUnsafeVariableExpansionISSUE-204Réduit le risque d’injection via des variables contrôlées par l’utilisateur
securityJobsMustNotBeWeakenedISSUE-410Détecte les jobs de sécurité neutralisés
pipelineMustNotOverrideJobVariablesISSUE-205Empêche de surcharger certaines variables de gouvernance
pipelineMustNotExecuteUnverifiedScriptsISSUE-411Détecte les motifs `curl
pipelineMustNotUseDockerInDockerISSUE-412 / 413Détecte DinD et son mode non sécurisé
SymptômeCause probableSolution
configuration file not foundAucun .plumber.yaml présent pour la CLICréez le fichier avec plumber config init ou plumber config generate
401 UnauthorizedToken incomplet ou invalideVérifiez read_api + read_repository
403 Forbidden on MR commentScope insuffisantUtilisez api si vous activez mr_comment
403 Forbidden on badgeScope insuffisant ou rôle trop faibleUtilisez api et un rôle Maintainer
Le composant ne s’exécute pasJob en .pre sans autre stage normalForcez stage: test
Deux pipelines sont créés sur le même pushworkflow:rules absentAjoutez le bloc recommandé par GitLab
Le projet n’est pas auto-détectéRemote Git absent ou mal nomméVérifiez le remote origin ou passez --gitlab-url et --project
  • Plumber se comprend mieux par la CLI locale avant de passer au composant GitLab CI/CD
  • Le chemin débutant est simple : config init, config validate, plumber analyze
  • L’auto-détection repose sur un remote origin pointant vers GitLab
  • Commencez par corriger les images non épinglées, les includes mutables et les branches non protégées
  • Le composant GitLab est la meilleure intégration par défaut ; le job manuel vient ensuite
  • Le PBOM sert à inventorier le pipeline ; le CycloneDX facilite l’intégration avec Trivy et Grype
  • Le score A-E, plumber explain, les commentaires de MR et les badges sont utiles après le premier scan, pas avant
  • Gardez la Platform pour les besoins de gouvernance multi-projets

Ce site vous est utile ?

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

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn