E-NO
DevOps 10 min de lecture

Durcissement de la sécurité GitLab CI/CD avec des exemples pratiques

calendar_today Publié : 2026-08-11
update Dernière mise à jour : 2026-08-11
analytics Efficacité SEO : 100%
Illustration du guide technique pour « Durcissement de la sécurité GitLab CI/CD avec des exemples pratiques ».

GitLab CI/CD est puissant, mais les configurations par défaut peuvent exposer des secrets, accorder des permissions excessives ou laisser l'infrastructure accessible sur le réseau. Ce guide propose un chemin pratique et vérifiable pour durcir GitLab CI/CD sans casser la livraison quotidienne. Vous allez :

  • Faire l'inventaire des versions, des runners et de la visibilité pour savoir exactement ce que vous sécurisez.
  • Appliquer des changements de configuration sûrs par petits lots : contrôle d'accès, secrets, isolation des runners, hygiène des pipelines et restrictions réseau.
  • Vérifier chaque changement avec des contrôles observables et des résultats attendus.
  • Comprendre les modes de défaillance courants et comment récupérer rapidement.
  • Adopter une liste de contrôle opérationnelle reproductible pour maintenir une posture saine.

Les exemples supposent que vous avez les droits Maintainer ou Owner sur un projet de test, et un accès administratif lorsque les changements l'exigent. Commencez avec un projet non critique, confirmez le comportement, puis déployez sur les dépôts critiques.

Inventaire des versions et de l'environnement

Le durcissement de la sécurité dépend de votre édition GitLab, de la version, des exécuteurs de runners et de la visibilité du projet. Capturez ces détails avant d'apporter des modifications. Utilisez les valeurs d'exemple ci-dessous uniquement comme placeholders pour votre propre inventaire.

ÉlémentValeur d'exemple (construite)Pourquoi c'est important
Édition et version GitLabGitLab EE 16.10Les fonctionnalités disponibles et l'emplacement des réglages varient selon la version et l'édition
Exécuteurs et versions des runners2 runners Shell partagés ; 1 runner Docker verrouillé au projetL'isolation, le tagging et les options de config.toml dépendent de l'exécuteur et de la portée
Visibilité du projetPrivéContrôle qui peut voir les pipelines, les logs et les artefacts
Nom de la branche par défautmainLes protections de branche et les règles de revue reposent sur la branche par défaut
Branches/tags protégés définismain protégé ; tags v* protégésDétermine qui peut exécuter des jobs sensibles et publier des releases
Stockage des variables et secretsVariables de groupe masquées et protégéesDéfinit comment les secrets sont scopés et hérités
Services externes utilisésRegistre de paquets interne ; hôte de staging en liste d'autorisationLa liste d'autorisation réseau doit inclure uniquement les endpoints requis
Administration des runnersLes Maintainers de projet gèrent le runner de projet ; l'Admin gère les runners partagésQui peut changer l'isolation et les tags affecte le placement des jobs

Conseil : stockez cet inventaire dans un README de dépôt ou un runbook ops et mettez-le à jour après chaque changement.

Chemin de configuration sûr

Appliquez les changements par étapes scopées. Après chaque étape, exécutez les étapes de vérification de la section suivante.

1) Contrôle d'accès et protection des branches/tags

Objectif : garantir que seuls les utilisateurs de confiance et les refs protégés peuvent déclencher des jobs sensibles.

Actions :

  • Mettez la visibilité du projet sur Privé sauf raison claire de ne pas le faire.
  • Protégez la branche par défaut et les tags de release (par exemple, v*). Limitez les push/merge aux Maintainers ou à un rôle de release dédié.
  • Exigez des revues de merge request et des vérifications de statut avant de merger vers les branches protégées.

Exemple : jobs uniquement sur branches/tags protégés dans .gitlab-ci.yml

stages: [test, build, deploy]

# S'exécute uniquement sur les branches/tags protégés
secure_job_template: &secure_job_rules
  rules:
    - if: '$CI_COMMIT_REF_PROTECTED == "true"'
      when: on_success
    - when: never

unit_tests:
  stage: test
  script:
    - echo Exécution des tests
  rules:
    - if: '$CI_PIPELINE_SOURCE == "push"'
      when: on_success

build_release:
  stage: build
  script:
    - echo Construction de l'artefact de release
  <<: *secure_job_rules

deploy_prod:
  stage: deploy
  script:
    - echo Déploiement en production
  environment:
    name: production
    when: manual
    allow_failure: false
  <<: *secure_job_rules

Résultat attendu : build_release et deploy_prod ne s'exécutent pas sur les branches non protégées ou depuis des forks.

2) Secrets et tokens

Objectif : éliminer les tokens personnels à longue durée de vie et garder les secrets hors des logs et artefacts.

Actions :

  • Utilisez des variables CI de projet ou de groupe avec Masqué et Protégé activés pour toute valeur secrète.
  • Préférez CI_JOB_TOKEN aux personal access tokens pour l'API GitLab et l'accès au registre/paquets interne. Scoppez l'accès à ce dont les jobs ont réellement besoin.
  • Utilisez des tokens d'accès de projet ou de groupe (rotatifs) lorsque l'accès non interactif est requis hors des jobs CI.
  • Rotez tous les tokens régulièrement et lors des changements de personnel.

Exemple : appel de l'API GitLab avec CI_JOB_TOKEN

list_issues:
  stage: test
  script:
    - curl --header "JOB-TOKEN: $CI_JOB_TOKEN" "$CI_API_V4_URL/projects/$CI_PROJECT_ID/issues?per_page=1"
  rules:
    - if: '$CI_COMMIT_REF_PROTECTED == "true"'

Exemple : référencement de variables masquées et protégées

deploy_prod:
  stage: deploy
  script:
    - set +x # empêche le shell d'afficher les commandes
    - ./deploy.sh --user "$DEPLOY_USER" --password "$DEPLOY_PASSWORD"
  <<: *secure_job_rules

Conseils pratiques :

  • N'affichez jamais les secrets ; préférez les fichiers ou stdin. Si vous devez créer un fichier, assurez-vous qu'il est supprimé avant la fin du job.
  • Gardez CI_DEBUG_TRACE désactivé sauf débogage actif. Réactivez les protections après le débogage.
  • Stockez les secrets spécifiques à l'environnement (staging vs production) au niveau de portée approprié (groupe, sous-groupe ou projet) et marquez-les comme Protégés pour qu'ils ne soient disponibles que sur les refs protégés.

3) Isolation et tagging des runners GitLab

Objectif : garantir que seuls les jobs prévus peuvent atterrir sur des runners spécifiques, et que les runners ne peuvent pas être détournés.

Actions pour les runners partagés (config.toml) :

  • Exigez des tags de job et désactivez les jobs sans tag.
  • Limitez la concurrence pour prévenir l'épuisement des ressources.
  • Évitez les modes d'exécution privilégiés sauf si strictement requis par le job.

Extrait d'exemple config.toml construit (runner partagé) :

concurrent = 4
check_interval = 0

runners
  name = "shared-secure"
  url = "https://gitlab.example.com"
  token = "REDACTED"
  executor = "shell"
  [runners.system]
  # défauts au niveau système
  [runners.cache]
  # réglages de cache selon les besoins
  # Exige des tags sur les jobs et n'accepte pas les jobs sans tag
  run_untagged = false
  # Exemple de limitation des requêtes parallèles pour ce runner
  request_concurrency = 1

Actions pour les runners spécifiques au projet :

  • Verrouillez le runner au projet.
  • Utilisez un tag dédié (par exemple, secure) et référencez-le dans les jobs qui ont vraiment besoin de ce runner.

Exemple : job épinglé à un runner verrouillé au projet par tag

secure_build:
  stage: build
  tags: [secure]
  script:
    - echo Construction avec runner verrouillé au projet
  <<: *secure_job_rules

Isolation additionnelle :

  • Pour les exécuteurs Shell, faites tourner le runner sous un utilisateur OS dédié avec des permissions minimales.
  • Pour tout exécuteur supportant l'élévation de privilèges, gardez-le désactivé sauf si un job spécifique l'exige, et confinez l'usage via des tags de job sur refs protégés uniquement.

4) Permissions des jobs et moindre privilège

Objectif : les jobs doivent opérer avec la portée et les capacités minimales.

Actions :

  • Utilisez des rules avec $CI_COMMIT_REF_PROTECTED pour clôturer les jobs sensibles.
  • Utilisez allow_failure: false pour les étapes critiques et when: manual pour les actions impactant la production.
  • Utilisez resource_group pour sérialiser les actions exclusives sur le même environnement.

Exemple : sérialiser les déploiements production

deploy_prod:
  stage: deploy
  resource_group: production
  when: manual
  script:
    - ./deploy-prod.sh
  <<: *secure_job_rules

5) Hygiène des artefacts, caches et logs

Objectif : éviter les fuites de secrets et réduire le rayon d'action des données divulguées.

Actions :

  • Ne stockez pas de secrets dans les artefacts ou caches. Si des artefacts sont requis, définissez de courts expire_in et n'incluez que les fichiers nécessaires.
  • Évitez de collecter des dumps d'environnement complets ou des logs verbeux par défaut.
  • N'écrivez jamais de secrets dans des fichiers dotenv ou rapports similaires.

Exemple : artefacts minimaux et courts

build_release:
  stage: build
  script:
    - ./build.sh
  artifacts:
    paths:
      - dist/
    expire_in: '1 day'
  <<: *secure_job_rules

6) Contrôles d'exposition réseau

Objectif : restreindre ce que votre instance GitLab et vos jobs peuvent atteindre.

Actions :

  • Dans les réglages admin, activez une liste d'autorisation des requêtes sortantes pour les webhooks et intégrations ; listez uniquement les hôtes dont vous avez vraiment besoin.
  • Gardez "autoriser les requêtes vers le réseau local" désactivé sauf besoin clair et revu.
  • Assurez-vous que les projets n'exposent pas de pipelines publics quand ils contiennent des logs ou artefacts sensibles.

Actions au niveau projet :

  • Désactivez les pipelines publics pour les projets privés.
  • Utilisez des variables scopées à l'environnement et des refs protégées pour que les identifiants de production ne soient pas disponibles depuis des sources non fiables.

7) Référence rapide des valeurs par défaut sûres

Utilisez ce tableau pour croiser les réglages de base dans un projet nouveau ou existant.

ContrôleRéglage recommandéOù régler
Visibilité du projetPrivéProject Settings > General > Visibility
Pipelines publicsDésactivéProject Settings > CI/CD > General pipelines
Branches/tags protégésProtéger la branche par défaut et les tags de releaseProject Settings > Repository > Protected branches/tags
Variables masquéesActivé pour tous les secretsProject ou Group Settings > CI/CD > Variables
Variables protégéesActivé pour identifiants prod/stagingProject ou Group Settings > CI/CD > Variables
Tags de jobs runnerRequis ; pas de jobs sans tagRunner config.toml et Project Settings > CI/CD > Runners
Portée du runnerVerrouiller runners de projet ; restreindre partagésProject Settings > CI/CD > Runners
Traçage de débogageDésactivé par défautVariable CI CI_DEBUG_TRACE=false
Rétention artefactsCourt terme (1 jour ou moins pour sensible).gitlab-ci.yml artifacts.expire_in

Vérification et diagnostics

Exécutez ces vérifications immédiatement après chaque changement. Utilisez les commandes construites ci-dessous ; remplacez les placeholders par vos valeurs.

1. Branches protégées et jobs

  • Créez une branche de fonctionnalité et poussez un commit qui déclencherait normalement build_release ou deploy_prod. Attendu : les jobs ne s'exécutent pas.
  • Créez un tag qui ne correspond pas au motif protégé et poussez. Attendu : les jobs protégés ne s'exécutent pas.
  • Mergez dans la branche par défaut protégée. Attendu : les jobs protégés s'exécutent selon les rules et les gates manuelles.

2. Secrets et logs

  • Ajoutez echo $DEPLOY_PASSWORD dans un job de test jetable sur une branche non protégée. Attendu : le job échoue car la variable est protégée et non disponible, ou affiche une valeur vide. Supprimez ce job de test immédiatement après validation.
  • Confirmez que les logs n'affichent pas les secrets. Attendu : les variables masquées apparaissent comme [MASKED].

3. Portée du CI_JOB_TOKEN

  • Exécutez un job qui appelle l'API GitLab en utilisant CI_JOB_TOKEN comme montré plus haut. Attendu : accès uniquement au projet courant là où autorisé. Essayez d'accéder à un autre projet que vous ne devriez pas atteindre. Attendu : 403 Forbidden.

4. Isolation des runners

  • Soumettez un job sans tags. Attendu (runner partagé) : le job reste en attente avec un message qu'aucun runner n'est disponible pour les jobs sans tag.
  • Soumettez un job avec tags: [secure] dans un projet avec un runner verrouillé. Attendu : le job atterrit sur ce runner verrouillé au projet.

5. Artefacts et rétention

  • Confirmez que seuls les chemins prévus sont archivés. Attendu : pas de secrets ou fichiers de config dans l'artefact.
  • Attendez après expire_in ou expirez manuellement les artefacts. Attendu : les artefacts deviennent inaccessibles.

6. Exposition réseau

  • Déclenchez un webhook ou une intégration vers un hôte non autorisé. Attendu : la requête est bloquée.
  • Vérifiez que les pipelines ne sont pas accessibles publiquement quand le projet est privé. Attendu : authentification requise pour voir les jobs et logs.

Astuces de diagnostic :

  • Revoyez les logs de job pour les rules ignorées et les messages de mismatch de tags pour identifier les mauvaises configurations.
  • Inspectez Project Settings > CI/CD > Runners pour confirmer quel runner a pris un job et pourquoi.
  • Pour les contrôles réseau au niveau admin, testez avec une intégration minimale (par exemple, un endpoint HTTP simple) pour valider la liste d'autorisation.

Modes de défaillance et récupération

Problèmes courants et comment les corriger proprement :

1. Variables protégées non disponibles dans les jobs

  • Symptôme : les jobs de déploiement échouent avec des secrets vides sur branches non protégées.
  • Cause : les variables marquées Protégées ne sont disponibles que sur les refs protégés.
  • Récupération : exécutez depuis un ref protégé ou déprotégez temporairement la variable pour tester dans un projet non critique. Ne déprotégez jamais les secrets de production dans les dépôts critiques.

2. Jobs bloqués en attente à cause des tags de runner

  • Symptôme : les jobs restent en attente avec "no runners found".
  • Cause : run_untagged=false ou tags requis qui ne correspondent pas.
  • Récupération : ajoutez les bons tags aux jobs, ou autorisez temporairement les jobs sans tag sur un runner de test pendant que vous propagez les tags. Revenez aux réglages sécurisés après vérification.

3. CI_JOB_TOKEN ne peut pas accéder à la ressource requise

  • Symptôme : erreurs 403 en appelant l'API GitLab ou le registre.
  • Cause : token non autorisé pour la cible, ou l'endpoint requiert une portée différente.
  • Récupération : basculez vers un token d'accès de projet/groupe avec la portée minimale requise, rotez le token après test.

4. Risque de fuite de secrets dans les logs

  • Symptôme : valeurs sensibles apparaissent dans la sortie du job.
  • Cause : affichage des secrets ou activation du traçage de débogage.
  • Récupération : supprimez les instructions echo, désactivez le débogage, rotez le secret fuité, et recherchez dans les artefacts/logs pour toute autre exposition.

5. Restrictions réseau trop agressives

  • Symptôme : webhooks et intégrations échouent silencieusement ou avec 403.
  • Cause : hôte non dans la liste d'autorisation sortante.
  • Récupération : ajoutez uniquement l'hôte requis à la liste d'autorisation, testez, et documentez pourquoi il est nécessaire.

6. Rétention d'artefacts trop courte

  • Symptôme : les consommateurs ne peuvent pas télécharger les artefacts de build à temps.
  • Cause : expire_in défini trop bas.
  • Récupération : augmentez expire_in modestement (par exemple, de 1 jour à 3 jours) et surveillez l'usage ; évitez de rendre les artefacts effectivement permanents.

Conseils de rollback :

  • Gardez les changements .gitlab-ci.yml dans des merge requests dédiées avec un plan de revert. Utilisez des commits de revert pour restaurer le pipeline précédent si un changement cause des pannes.
  • Sauvegardez les config.toml des runners avant modifications ; restaurez depuis la sauvegarde et redémarrez le runner si les jobs arrêtent de progresser.
  • Pour les réglages de projet, changez un contrôle à la fois, validez, et enregistrez la valeur précédente pour pouvoir faire un rollback rapide.

Liste de contrôle opérationnelle

Utilisez cette liste mensuellement ou lors de l'intégration d'un nouveau projet. Tous les items utilisent des exemples construits ; adaptez à votre environnement.

ÉtapeCe qu'il faut fairePreuve de succès
1Confirmer que le projet est Privé et les pipelines publics désactivésLes visiteurs doivent s'authentifier pour voir pipelines et logs
2Revoir les branches et tags protégésSeuls les Maintainers (ou plus strict) peuvent push/merge sur refs protégés
3Auditer les variables CITous les secrets sont Masqués et Protégés ; les non-secrets sont clairement étiquetés
4Revoir l'usage des tokensCI_JOB_TOKEN utilisé pour API/registre interne ; pas de tokens personnels à longue durée dans les jobs
5Isolation des runnersRunners partagés exigent des tags ; runners de projet verrouillés ; pas d'exécution privilégiée sauf justification
6Rules de pipelineJobs sensibles clôturés par $CI_COMMIT_REF_PROTECTED et when: manual pour la prod
7Hygiène des artefactsArtefacts contiennent seulement les fichiers nécessaires ; expire_in court ; pas de secrets présents
8Hygiène des logsCI_DEBUG_TRACE désactivé ; pas d'echo de secrets ; rédaction vérifiée
9Liste d'autorisation réseauSeuls les hôtes requis sont listés ; accès localhost désactivé sauf justification
10Rotation et revuesTokens rotés ; revues d'accès complétées ; documentation mise à jour

Conclusion

Durcissez GitLab CI/CD en avançant par petits pas vérifiables : verrouillez l'accès aux branches et tags protégés, stockez et scopez correctement les secrets, isolez les runners avec des tags et des verrous de projet, gardez les artefacts et logs exempts de données sensibles, et restreignez l'exposition réseau. Après chaque changement, exécutez les vérifications décrites ici pour confirmer que les contrôles voulus fonctionnent et ne bloquent pas le travail légitime.

Un pilote étroit dans un projet non critique vous aide à valider les contrôles et ajuster les défauts avant de généraliser à votre organisation. Une fois vérifié, codez vos décisions dans des templates et politiques de runners, adoptez la liste de contrôle mensuelle, et suivez les écarts dans le temps. Cela maintient votre posture CI/CD forte tout en minimisant la perturbation des équipes.

Recherches connexes

Score de qualité de l’article

Utilité pour le lecteur 100%
  • check_circle Guide prêt à lire
  • check_circle Exemples pratiques inclus
  • check_circle URL d’article optimisée pour le SEO