{"id":500,"date":"2026-03-02T01:06:45","date_gmt":"2026-03-02T00:06:45","guid":{"rendered":"https:\/\/secure-pipelines.com\/?p=500"},"modified":"2026-03-24T12:55:30","modified_gmt":"2026-03-24T11:55:30","slug":"separation-of-duties-least-privilege-ci-cd-pipelines","status":"publish","type":"post","link":"https:\/\/secure-pipelines.com\/fr\/ci-cd-security\/separation-of-duties-least-privilege-ci-cd-pipelines\/","title":{"rendered":"S\u00e9paration des Responsabilit\u00e9s et Moindre Privil\u00e8ge dans les Pipelines CI\/CD"},"content":{"rendered":"<h2>Introduction<\/h2>\n<p>La plupart des pipelines CI\/CD d\u00e9marrent avec un objectif simple : acheminer le code depuis la machine d&rsquo;un d\u00e9veloppeur vers la production le plus rapidement possible. En cours de route, quelqu&rsquo;un cr\u00e9e un compte de service, lui accorde des permissions larges, stocke les identifiants comme secret du pipeline, et passe \u00e0 autre chose. Cela fonctionne. Les builds passent, les d\u00e9ploiements r\u00e9ussissent, et personne n&rsquo;y repense \u2014 jusqu&rsquo;\u00e0 ce qu&rsquo;un attaquant compromette ce pipeline et d\u00e9couvre qu&rsquo;il poss\u00e8de les cl\u00e9s de l&rsquo;ensemble du royaume.<\/p>\n<p>Le probl\u00e8me n&rsquo;est pas que les \u00e9quipes sont n\u00e9gligentes. Le probl\u00e8me est que les outils CI\/CD rendent <em>facile<\/em> l&rsquo;octroi de privil\u00e8ges excessifs et <em>difficile<\/em> l&rsquo;application de contr\u00f4les granulaires. Le chemin par d\u00e9faut dans la plupart des plateformes est une identit\u00e9 unique avec un acc\u00e8s large ex\u00e9cutant chaque \u00e9tape du pipeline. Les principes de s\u00e9curit\u00e9 comme la <strong>s\u00e9paration des responsabilit\u00e9s<\/strong> (SoD) et le <strong>moindre privil\u00e8ge<\/strong> ressemblent \u00e0 des contraintes bureaucratiques quand on essaie de livrer des fonctionnalit\u00e9s.<\/p>\n<p>Ils ne le sont pas. Ce sont des contr\u00f4les d&rsquo;ing\u00e9nierie qui limitent le rayon d&rsquo;impact quand \u2014 et non si \u2014 quelque chose tourne mal. Ce guide explique comment appliquer ces deux principes aux pipelines CI\/CD d&rsquo;une mani\u00e8re qui renforce votre posture de s\u00e9curit\u00e9 sans d\u00e9truire la v\u00e9locit\u00e9 de livraison.<\/p>\n<h2>Pourquoi les pipelines accumulent les privil\u00e8ges<\/h2>\n<p>Avant de plonger dans les solutions, il convient de comprendre comment les pipelines se retrouvent avec des permissions excessives. Le sch\u00e9ma est remarquablement constant d&rsquo;une organisation \u00e0 l&rsquo;autre.<\/p>\n<h3>Le probl\u00e8me du compte de service unique<\/h3>\n<p>Tout commence avec un seul compte de service \u2014 souvent nomm\u00e9 quelque chose comme <code>ci-deployer<\/code> ou <code>pipeline-bot<\/code> \u2014 cr\u00e9\u00e9 lors de la mise en place initiale du CI\/CD. Ce compte a besoin de r\u00e9cup\u00e9rer le code, donc il obtient l&rsquo;acc\u00e8s en lecture au d\u00e9p\u00f4t. Puis il a besoin de pousser des images Docker, donc il obtient l&rsquo;acc\u00e8s en \u00e9criture au registre. Puis il doit d\u00e9ployer en staging, puis en production, puis g\u00e9rer l&rsquo;infrastructure. En quelques semaines, cette seule identit\u00e9 peut construire, tester, d\u00e9ployer et acc\u00e9der aux donn\u00e9es de production. Elle est devenue un passe-partout.<\/p>\n<h3>Les tokens omnipotents<\/h3>\n<p>\u00c9troitement li\u00e9 est le \u00ab token omnipotent \u00bb \u2014 un jeton d&rsquo;acc\u00e8s personnel ou une cl\u00e9 API avec un acc\u00e8s en lecture\/\u00e9criture \u00e0 tout. Ces tokens sont souvent cr\u00e9\u00e9s par un administrateur lors de la mise en place, stock\u00e9s comme variable CI\/CD, et jamais renouvel\u00e9s. Ils survivent g\u00e9n\u00e9ralement \u00e0 la personne qui les a cr\u00e9\u00e9s, et personne ne se souvient exactement des permissions qu&rsquo;ils portent.<\/p>\n<h3>La commodit\u00e9 avant la s\u00e9curit\u00e9<\/h3>\n<p>Les organisations utilisent fr\u00e9quemment un pool unique de runners pour tous les environnements. La m\u00eame machine qui ex\u00e9cute les tests unitaires sur des pull requests non fiables provenant de forks a \u00e9galement acc\u00e8s r\u00e9seau \u00e0 l&rsquo;infrastructure de production. Le raisonnement est simple : maintenir des pools de runners s\u00e9par\u00e9s est op\u00e9rationnellement co\u00fbteux. Mais cette commodit\u00e9 signifie qu&rsquo;une pull request malveillante pourrait potentiellement acc\u00e9der aux identifiants de production.<\/p>\n<h3>Absence de fronti\u00e8res d&rsquo;identit\u00e9 entre les \u00e9tapes<\/h3>\n<p>La plupart des pipelines ex\u00e9cutent toutes les \u00e9tapes sous la m\u00eame identit\u00e9. L&rsquo;\u00e9tape de build, l&rsquo;\u00e9tape de test, l&rsquo;\u00e9tape de d\u00e9ploiement \u2014 elles partagent toutes le m\u00eame compte de service, les m\u00eames secrets et le m\u00eame acc\u00e8s r\u00e9seau. Il n&rsquo;y a pas de fronti\u00e8re entre \u00ab compiler du code \u00bb et \u00ab pousser en production \u00bb. Du point de vue de la s\u00e9curit\u00e9, ce sont des niveaux de confiance fondamentalement diff\u00e9rents qui ne devraient jamais partager une identit\u00e9.<\/p>\n<h2>S\u00e9paration des responsabilit\u00e9s dans le CI\/CD<\/h2>\n<p>La s\u00e9paration des responsabilit\u00e9s est un principe de conception des contr\u00f4les qui garantit qu&rsquo;aucune entit\u00e9 unique ne dispose d&rsquo;un acc\u00e8s suffisant pour accomplir seule un processus critique. En CI\/CD, cela signifie diviser d\u00e9lib\u00e9r\u00e9ment les op\u00e9rations du pipeline entre diff\u00e9rentes identit\u00e9s, approbations et fronti\u00e8res de confiance.<\/p>\n<h3>Principes fondamentaux pour la SoD des pipelines<\/h3>\n<ul>\n<li><strong>Aucune identit\u00e9 unique ne devrait construire ET d\u00e9ployer en production.<\/strong> L&rsquo;identit\u00e9 qui compile le code et produit les artefacts ne devrait pas \u00eatre la m\u00eame que celle qui pousse ces artefacts vers l&rsquo;infrastructure de production.<\/li>\n<li><strong>Les auteurs du code ne devraient pas approuver leurs propres d\u00e9ploiements.<\/strong> La personne qui \u00e9crit le code ne devrait pas \u00eatre la seule approbatrice de la mise en production de ce code. Au minimum, un second humain doit \u00eatre impliqu\u00e9.<\/li>\n<li><strong>Les d\u00e9finitions de pipeline devraient \u00eatre prot\u00e9g\u00e9es du code qu&rsquo;elles traitent.<\/strong> Les fichiers de workflow qui d\u00e9finissent comment le code est construit et d\u00e9ploy\u00e9 ne devraient pas \u00eatre modifiables par le m\u00eame processus qui ex\u00e9cute le code applicatif.<\/li>\n<li><strong>Les artefacts de build devraient \u00eatre immuables une fois produits.<\/strong> Une fois qu&rsquo;une \u00e9tape de build produit un artefact, aucune \u00e9tape ult\u00e9rieure ne devrait pouvoir le modifier. L&rsquo;artefact qui a \u00e9t\u00e9 test\u00e9 est l&rsquo;artefact qui est d\u00e9ploy\u00e9.<\/li>\n<\/ul>\n<h3>Correspondance entre SoD et \u00e9tapes du pipeline<\/h3>\n<p>Un pipeline bien con\u00e7u associe la s\u00e9paration des responsabilit\u00e9s \u00e0 des \u00e9tapes distinctes, chacune avec sa propre identit\u00e9 et ses propres permissions :<\/p>\n<ul>\n<li><strong>Build<\/strong> \u2014 Compile le code, r\u00e9sout les d\u00e9pendances, produit les artefacts. N\u00e9cessite un acc\u00e8s en lecture au code source et aux registres de d\u00e9pendances. Aucun acc\u00e8s aux cibles de d\u00e9ploiement.<\/li>\n<li><strong>Test<\/strong> \u2014 Ex\u00e9cute les tests unitaires, les tests d&rsquo;int\u00e9gration, les analyses de s\u00e9curit\u00e9. N\u00e9cessite un acc\u00e8s en lecture aux artefacts et \u00e0 l&rsquo;infrastructure de test. Aucun acc\u00e8s aux secrets de production.<\/li>\n<li><strong>Signature<\/strong> \u2014 Signe cryptographiquement les artefacts qui passent toutes les v\u00e9rifications. N\u00e9cessite l&rsquo;acc\u00e8s aux cl\u00e9s de signature mais rien d&rsquo;autre. Cette \u00e9tape agit comme une porte de contr\u00f4le.<\/li>\n<li><strong>Staging<\/strong> \u2014 D\u00e9ploie dans un environnement de staging pour validation finale. N\u00e9cessite un acc\u00e8s en \u00e9criture au staging uniquement. Aucun identifiant de production disponible.<\/li>\n<li><strong>D\u00e9ploiement<\/strong> \u2014 Promeut l&rsquo;artefact sign\u00e9 et test\u00e9 en production. N\u00e9cessite un acc\u00e8s en \u00e9criture \u00e0 la production, prot\u00e9g\u00e9 par une approbation manuelle. Identit\u00e9 diff\u00e9rente de celle du build.<\/li>\n<\/ul>\n<p>Chaque fronti\u00e8re d&rsquo;\u00e9tape est une fronti\u00e8re de confiance. Les identifiants ne circulent pas entre les \u00e9tapes sauf s&rsquo;ils sont explicitement accord\u00e9s.<\/p>\n<h2>Mod\u00e8les de moindre privil\u00e8ge<\/h2>\n<p>Le moindre privil\u00e8ge signifie n&rsquo;accorder que les permissions minimales requises pour une t\u00e2che sp\u00e9cifique, pour la dur\u00e9e la plus courte n\u00e9cessaire. En CI\/CD, cela se traduit par des mod\u00e8les concrets qui varient selon la plateforme.<\/p>\n<h3>GitHub Actions : permissions par job<\/h3>\n<p>GitHub Actions fournit un bloc <code>permissions<\/code> qui contr\u00f4le les port\u00e9es du <code>GITHUB_TOKEN<\/code> g\u00e9n\u00e9r\u00e9 automatiquement. Par d\u00e9faut, ce token dispose d&rsquo;un acc\u00e8s large en lecture\/\u00e9criture. Vous devriez toujours le restreindre.<\/p>\n<p>D\u00e9finissez des valeurs par d\u00e9faut restrictives au niveau du workflow et n&rsquo;accordez des permissions suppl\u00e9mentaires qu&rsquo;aux jobs sp\u00e9cifiques qui en ont besoin :<\/p>\n<pre><code># .github\/workflows\/deploy.yml\nname: Build and Deploy\n\n# Restrict default permissions for ALL jobs in this workflow\npermissions:\n  contents: read\n\non:\n  push:\n    branches: [main]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    # This job inherits the workflow-level permissions: contents read only\n    steps:\n      - uses: actions\/checkout@v4\n      - run: make build\n      - uses: actions\/upload-artifact@v4\n        with:\n          name: app-binary\n          path: dist\/\n\n  security-scan:\n    needs: build\n    runs-on: ubuntu-latest\n    permissions:\n      security-events: write  # Only this job can write security findings\n      contents: read\n    steps:\n      - uses: actions\/checkout@v4\n      - uses: github\/codeql-action\/analyze@v3\n\n  deploy-staging:\n    needs: [build, security-scan]\n    runs-on: ubuntu-latest\n    environment: staging  # Scoped to staging secrets only\n    permissions:\n      contents: read\n      id-token: write  # OIDC token for cloud auth \u2014 no static credentials\n    steps:\n      - uses: aws-actions\/configure-aws-credentials@v4\n        with:\n          role-to-assume: arn:aws:iam::123456789:role\/staging-deployer\n          aws-region: us-east-1\n      - run: .\/scripts\/deploy.sh staging\n\n  deploy-production:\n    needs: deploy-staging\n    runs-on: ubuntu-latest\n    environment: production  # Requires manual approval + different secrets\n    permissions:\n      contents: read\n      id-token: write\n    steps:\n      - uses: aws-actions\/configure-aws-credentials@v4\n        with:\n          role-to-assume: arn:aws:iam::123456789:role\/production-deployer\n          aws-region: us-east-1\n      - run: .\/scripts\/deploy.sh production<\/code><\/pre>\n<p>Points cl\u00e9s de cette configuration : chaque job d\u00e9clare uniquement les permissions dont il a besoin, les jobs de d\u00e9ploiement utilisent OIDC pour des identifiants \u00e9ph\u00e9m\u00e8res au lieu de secrets statiques, et le staging et la production utilisent des r\u00f4les IAM diff\u00e9rents avec des niveaux d&rsquo;acc\u00e8s diff\u00e9rents.<\/p>\n<h3>GitLab CI : variables prot\u00e9g\u00e9es et runners<\/h3>\n<p>GitLab CI offre un ensemble de contr\u00f4les diff\u00e9rent mais tout aussi puissant pour impl\u00e9menter le moindre privil\u00e8ge :<\/p>\n<pre><code># .gitlab-ci.yml\nstages:\n  - build\n  - test\n  - deploy-staging\n  - deploy-production\n\nbuild:\n  stage: build\n  tags:\n    - shared-runners  # Non-privileged runners for build\n  script:\n    - make build\n  artifacts:\n    paths:\n      - dist\/\n\ntest:\n  stage: test\n  tags:\n    - shared-runners\n  script:\n    - make test\n  dependencies:\n    - build\n\ndeploy-staging:\n  stage: deploy-staging\n  tags:\n    - deploy-runners  # Dedicated runners with network access to staging\n  environment:\n    name: staging\n  script:\n    - .\/scripts\/deploy.sh staging\n  # CI_JOB_TOKEN is automatically scoped to this project\n  # Staging secrets are only available on protected branches\n  rules:\n    - if: '$CI_COMMIT_BRANCH == \"main\"'\n\ndeploy-production:\n  stage: deploy-production\n  tags:\n    - production-runners  # Isolated runners with production network access\n  environment:\n    name: production\n  script:\n    - .\/scripts\/deploy.sh production\n  rules:\n    - if: '$CI_COMMIT_BRANCH == \"main\"'\n      when: manual  # Requires manual approval\n  allow_failure: false  # Block the pipeline if not approved<\/code><\/pre>\n<p>Dans GitLab, utilisez les <strong>variables prot\u00e9g\u00e9es<\/strong> afin que les identifiants de production ne soient disponibles que pour les branches et tags prot\u00e9g\u00e9s. Utilisez les <strong>runners prot\u00e9g\u00e9s<\/strong> pour garantir que les jobs de d\u00e9ploiement en production ne s&rsquo;ex\u00e9cutent que sur une infrastructure durcie et isol\u00e9e. Marquez les secrets de production comme <strong>masqu\u00e9s<\/strong> pour pr\u00e9venir toute exposition accidentelle dans les logs.<\/p>\n<h3>Comptes de service par \u00e9tape avec r\u00f4les IAM scop\u00e9s<\/h3>\n<p>Au-del\u00e0 de la plateforme CI elle-m\u00eame, appliquez le moindre privil\u00e8ge au niveau du fournisseur cloud. Chaque \u00e9tape du pipeline devrait s&rsquo;authentifier avec un compte de service diff\u00e9rent disposant de permissions strictement d\u00e9limit\u00e9es :<\/p>\n<ul>\n<li><strong>\u00c9tape de build :<\/strong> Acc\u00e8s en lecture seule aux d\u00e9p\u00f4ts source et aux registres de d\u00e9pendances. Acc\u00e8s en \u00e9criture au stockage d&rsquo;artefacts (par exemple, un bucket S3, un registre de conteneurs) mais rien d&rsquo;autre.<\/li>\n<li><strong>\u00c9tape de test :<\/strong> Acc\u00e8s en lecture seule aux artefacts. Permission de cr\u00e9er et d\u00e9truire une infrastructure de test \u00e9ph\u00e9m\u00e8re, mais aucun acc\u00e8s au staging ou \u00e0 la production.<\/li>\n<li><strong>\u00c9tape de d\u00e9ploiement :<\/strong> Acc\u00e8s en \u00e9criture \u00e0 la cible de d\u00e9ploiement sp\u00e9cifique (par exemple, un namespace Kubernetes unique, un service ECS sp\u00e9cifique). Aucun acc\u00e8s aux autres environnements ou services.<\/li>\n<\/ul>\n<h3>Identifiants \u00e9ph\u00e9m\u00e8res via OIDC<\/h3>\n<p>Les identifiants statiques stock\u00e9s comme secrets CI\/CD sont une dette de s\u00e9curit\u00e9. Ils n&rsquo;expirent pas, sont difficiles \u00e0 renouveler et constituent des cibles attractives pour les attaquants. L&rsquo;approche moderne consiste \u00e0 utiliser la f\u00e9d\u00e9ration OIDC pour que votre plateforme CI\/CD \u00e9change un token \u00e9ph\u00e9m\u00e8re, sign\u00e9 par la plateforme, contre des identifiants cloud temporaires :<\/p>\n<ul>\n<li>GitHub Actions peut assumer des r\u00f4les AWS IAM, des comptes de service GCP ou des identit\u00e9s manag\u00e9es Azure en utilisant la permission <code>id-token: write<\/code> \u2014 aucun secret stock\u00e9 n&rsquo;est n\u00e9cessaire.<\/li>\n<li>GitLab CI supporte OIDC nativement via son <code>CI_JOB_JWT<\/code> ou le mot-cl\u00e9 <code>id_tokens<\/code>, permettant le m\u00eame mod\u00e8le.<\/li>\n<li>Ces identifiants durent g\u00e9n\u00e9ralement de 15 \u00e0 60 minutes et sont limit\u00e9s au job sp\u00e9cifique qui les a demand\u00e9s.<\/li>\n<\/ul>\n<p>Si vous utilisez encore des cl\u00e9s d&rsquo;acc\u00e8s statiques dans les secrets de votre pipeline, la migration vers OIDC devrait \u00eatre une initiative hautement prioritaire.<\/p>\n<h2>Prot\u00e9ger les d\u00e9finitions de pipeline<\/h2>\n<p>Le pipeline-as-code est puissant, mais il introduit un probl\u00e8me de confiance subtil : si un attaquant peut modifier la d\u00e9finition du pipeline, il contr\u00f4le comment le code est construit, test\u00e9 et d\u00e9ploy\u00e9. Prot\u00e9ger les fichiers de configuration du pipeline est tout aussi important que prot\u00e9ger le code applicatif lui-m\u00eame.<\/p>\n<h3>CODEOWNERS pour les fichiers de workflow<\/h3>\n<p>Utilisez un fichier CODEOWNERS pour exiger que des \u00e9quipes sp\u00e9cifiques examinent les modifications apport\u00e9es \u00e0 la configuration CI\/CD :<\/p>\n<pre><code># .github\/CODEOWNERS\n\/.github\/workflows\/   @your-org\/platform-security\n\/.gitlab-ci.yml       @your-org\/platform-security\n\/Jenkinsfile          @your-org\/platform-security\n\/terraform\/           @your-org\/infrastructure<\/code><\/pre>\n<p>Cela garantit que personne ne peut modifier les d\u00e9finitions de pipeline sans l&rsquo;approbation de l&rsquo;\u00e9quipe responsable de la s\u00e9curit\u00e9 CI\/CD. Combinez cela avec des r\u00e8gles de protection de branches qui exigent l&rsquo;approbation des CODEOWNERS.<\/p>\n<h3>Protection de branche sur les r\u00e9pertoires de configuration du pipeline<\/h3>\n<p>Appliquez des r\u00e8gles de protection de branche qui emp\u00eachent les pushs directs vers les branches contenant les d\u00e9finitions de pipeline. Au minimum :<\/p>\n<ul>\n<li>Exigez des revues de pull request avant de fusionner les modifications des fichiers de workflow.<\/li>\n<li>Exigez que les v\u00e9rifications de statut passent (y compris les analyses de s\u00e9curit\u00e9 des modifications de workflow elles-m\u00eames).<\/li>\n<li>D\u00e9sactivez les force pushs vers les branches prot\u00e9g\u00e9es.<\/li>\n<li>Exigez des commits sign\u00e9s pour les modifications de la configuration du pipeline.<\/li>\n<\/ul>\n<h3>Templates de pipeline immuables<\/h3>\n<p>GitHub Actions et GitLab CI supportent tous deux le r\u00e9f\u00e9rencement de d\u00e9finitions de pipeline depuis des d\u00e9p\u00f4ts externes g\u00e9r\u00e9s de mani\u00e8re centralis\u00e9e :<\/p>\n<p><strong>Workflows r\u00e9utilisables GitHub Actions :<\/strong><\/p>\n<pre><code># In your repository's workflow, reference a centrally managed template\njobs:\n  deploy:\n    uses: your-org\/shared-workflows\/.github\/workflows\/secure-deploy.yml@v2.1.0\n    with:\n      environment: production\n      artifact-name: app-binary\n    secrets: inherit<\/code><\/pre>\n<p><strong>Inclusions GitLab CI depuis des d\u00e9p\u00f4ts prot\u00e9g\u00e9s :<\/strong><\/p>\n<pre><code># .gitlab-ci.yml\ninclude:\n  - project: 'platform-team\/ci-templates'\n    ref: 'v3.0.0'\n    file: '\/templates\/secure-deploy.yml'\n\n# Local jobs can use templates but cannot override protected stages\ndeploy-production:\n  extends: .secure-deploy-template\n  variables:\n    TARGET_ENV: production<\/code><\/pre>\n<p>En \u00e9pinglant des versions sp\u00e9cifiques (tags ou SHA de commits) et en restreignant qui peut modifier le d\u00e9p\u00f4t de templates, vous garantissez que les \u00e9quipes individuelles ne peuvent pas alt\u00e9rer les contr\u00f4les de s\u00e9curit\u00e9 int\u00e9gr\u00e9s au processus de d\u00e9ploiement.<\/p>\n<h3>Emp\u00eacher les pipelines auto-modifiants<\/h3>\n<p>Un pipeline ne devrait jamais pouvoir modifier sa propre d\u00e9finition. Surveillez ces sch\u00e9mas :<\/p>\n<ul>\n<li>Des \u00e9tapes de pipeline qui \u00e9crivent dans <code>.github\/workflows\/<\/code> ou <code>.gitlab-ci.yml<\/code> et commitent les modifications.<\/li>\n<li>La g\u00e9n\u00e9ration dynamique de pipeline qui r\u00e9cup\u00e8re la configuration depuis des sources non fiables.<\/li>\n<li>Des variables de pipeline qui peuvent outrepasser des param\u00e8tres critiques pour la s\u00e9curit\u00e9, comme le runner \u00e0 utiliser ou l&rsquo;environnement dans lequel d\u00e9ployer.<\/li>\n<\/ul>\n<p>Si vous avez besoin d&rsquo;un comportement dynamique de pipeline, utilisez des templates param\u00e9tr\u00e9s avec un ensemble fixe d&rsquo;entr\u00e9es autoris\u00e9es plut\u00f4t que de permettre la modification arbitraire de la logique du pipeline.<\/p>\n<h2>Contr\u00f4les de d\u00e9ploiement<\/h2>\n<p>Les contr\u00f4les de d\u00e9ploiement sont les portes entre les \u00e9tapes du pipeline qui imposent la supervision humaine et la conformit\u00e9 aux politiques. C&rsquo;est l\u00e0 que la s\u00e9paration des responsabilit\u00e9s devient tangible.<\/p>\n<h3>R\u00e9viseurs requis et approbations manuelles<\/h3>\n<p>Les d\u00e9ploiements en production devraient exiger une approbation explicite de quelqu&rsquo;un d&rsquo;autre que l&rsquo;auteur du code. Les deux principales plateformes supportent cela nativement :<\/p>\n<ul>\n<li><strong>GitHub Environments<\/strong> permettent de configurer des r\u00e9viseurs requis. Lorsqu&rsquo;un job de workflow r\u00e9f\u00e9rence un environnement avec des r\u00e8gles de protection, le pipeline se met en pause jusqu&rsquo;\u00e0 ce qu&rsquo;un r\u00e9viseur autoris\u00e9 approuve.<\/li>\n<li><strong>GitLab Protected Environments<\/strong> restreignent quels utilisateurs ou groupes peuvent d\u00e9clencher des d\u00e9ploiements vers des environnements sp\u00e9cifiques. Combin\u00e9 avec <code>when: manual<\/code>, cela cr\u00e9e une porte d&rsquo;approbation.<\/li>\n<\/ul>\n<h3>GitHub Environments avec r\u00e8gles de protection<\/h3>\n<p>Les GitHub Environments sont un m\u00e9canisme puissant pour les contr\u00f4les de d\u00e9ploiement. Configurez-les avec :<\/p>\n<ul>\n<li><strong>R\u00e9viseurs requis :<\/strong> Sp\u00e9cifiez les individus ou \u00e9quipes qui doivent approuver avant l&rsquo;ex\u00e9cution du job. Utilisez au moins deux r\u00e9viseurs pour la production.<\/li>\n<li><strong>Minuterie d&rsquo;attente :<\/strong> Ajoutez un d\u00e9lai entre l&rsquo;approbation et l&rsquo;ex\u00e9cution, laissant le temps de d\u00e9tecter des erreurs ou de se coordonner avec les fen\u00eatres de changement.<\/li>\n<li><strong>Branches de d\u00e9ploiement :<\/strong> Restreignez les branches pouvant d\u00e9ployer vers l&rsquo;environnement. La production ne devrait accepter que les d\u00e9ploiements depuis <code>main<\/code> ou <code>release\/*<\/code>.<\/li>\n<li><strong>Secrets d&rsquo;environnement :<\/strong> Stockez les identifiants au niveau de l&rsquo;environnement, pas du d\u00e9p\u00f4t. Cela garantit que les secrets de staging ne sont pas disponibles pour les jobs de production et vice versa.<\/li>\n<\/ul>\n<h3>Gels de d\u00e9ploiement et fen\u00eatres de changement<\/h3>\n<p>Impl\u00e9mentez des gels de d\u00e9ploiement pendant les p\u00e9riodes commerciales critiques (par exemple, Black Friday, fin de trimestre) en :<\/p>\n<ul>\n<li>Utilisant des r\u00e8gles de protection d&rsquo;environnement planifi\u00e9es qui bloquent automatiquement les d\u00e9ploiements pendant les fen\u00eatres d\u00e9finies.<\/li>\n<li>Exigeant des approbations suppl\u00e9mentaires pendant les p\u00e9riodes de gel plut\u00f4t que de bloquer enti\u00e8rement \u2014 les correctifs d&rsquo;urgence devraient toujours \u00eatre possibles avec une supervision renforc\u00e9e.<\/li>\n<li>Enregistrant toutes les d\u00e9rogations au gel \u00e0 des fins d&rsquo;audit.<\/li>\n<\/ul>\n<h3>Canary et d\u00e9ploiement progressif comme m\u00e9canisme de contr\u00f4le<\/h3>\n<p>Les strat\u00e9gies de d\u00e9ploiement progressif ne sont pas seulement une pr\u00e9occupation de disponibilit\u00e9 \u2014 elles constituent un contr\u00f4le de s\u00e9curit\u00e9. Si un artefact compromis passe tous les autres contr\u00f4les, un d\u00e9ploiement canary limite le rayon d&rsquo;impact :<\/p>\n<ul>\n<li>D\u00e9ployez d&rsquo;abord vers 1 \u00e0 5 % du trafic avec des v\u00e9rifications de sant\u00e9 automatis\u00e9es.<\/li>\n<li>Exigez une seconde approbation manuelle pour poursuivre au-del\u00e0 de l&rsquo;\u00e9tape canary.<\/li>\n<li>Automatisez le rollback si les taux d&rsquo;erreur ou la latence d\u00e9passent les seuils.<\/li>\n<li>Traitez l&rsquo;\u00e9tape canary comme un environnement distinct avec ses propres exigences d&rsquo;approbation.<\/li>\n<\/ul>\n<h2>Audit et tra\u00e7abilit\u00e9<\/h2>\n<p>La s\u00e9paration des responsabilit\u00e9s et le moindre privil\u00e8ge ne sont efficaces que si vous pouvez v\u00e9rifier qu&rsquo;ils sont respect\u00e9s. L&rsquo;audit et la tra\u00e7abilit\u00e9 bouclent la boucle en fournissant la preuve de qui a fait quoi, quand et pourquoi.<\/p>\n<h3>Logs d&rsquo;ex\u00e9cution de pipeline comme pistes d&rsquo;audit<\/h3>\n<p>Les plateformes CI\/CD maintiennent des logs d\u00e9taill\u00e9s de chaque ex\u00e9cution de pipeline. Traitez ces logs comme des donn\u00e9es d&rsquo;audit pertinentes pour la s\u00e9curit\u00e9 :<\/p>\n<ul>\n<li>Conservez les logs de pipeline pendant au moins 90 jours (plus longtemps si votre cadre de conformit\u00e9 l&rsquo;exige).<\/li>\n<li>Exportez les logs vers un stockage centralis\u00e9 et inviolable (par exemple, SIEM, CloudWatch Logs, ou un bucket S3 d\u00e9di\u00e9 avec verrouillage d&rsquo;objet).<\/li>\n<li>Assurez-vous que les logs capturent quelle identit\u00e9 a d\u00e9clench\u00e9 le pipeline, quels secrets ont \u00e9t\u00e9 acc\u00e9d\u00e9s (mais pas leurs valeurs) et quelles approbations ont \u00e9t\u00e9 accord\u00e9es.<\/li>\n<\/ul>\n<h3>Lier les d\u00e9ploiements aux commits et aux approbateurs<\/h3>\n<p>Chaque d\u00e9ploiement en production devrait \u00eatre tra\u00e7able jusqu&rsquo;\u00e0 :<\/p>\n<ul>\n<li>Le SHA de commit Git sp\u00e9cifique qui a \u00e9t\u00e9 d\u00e9ploy\u00e9.<\/li>\n<li>La pull request qui a introduit le changement, incluant tous les r\u00e9viseurs et approbateurs.<\/li>\n<li>L&rsquo;identifiant d&rsquo;ex\u00e9cution du pipeline et la personne qui a approuv\u00e9 la porte de d\u00e9ploiement.<\/li>\n<li>Le digest de l&rsquo;artefact (SHA d&rsquo;image conteneur, hash de binaire) qui a \u00e9t\u00e9 d\u00e9ploy\u00e9.<\/li>\n<\/ul>\n<p>Cette cha\u00eene de tra\u00e7abilit\u00e9 devrait \u00eatre automatis\u00e9e. Si quelqu&rsquo;un demande \u00ab qu&rsquo;est-ce qui tourne en production et qui l&rsquo;a approuv\u00e9 \u00bb, la r\u00e9ponse devrait \u00eatre disponible en secondes, pas en heures.<\/p>\n<h3>Logs d&rsquo;audit cloud pour les changements initi\u00e9s par le pipeline<\/h3>\n<p>Les actions du pipeline laissent des traces dans les logs d&rsquo;audit du fournisseur cloud. Corr\u00e9lez-les avec vos logs CI\/CD :<\/p>\n<ul>\n<li><strong>AWS CloudTrail<\/strong> enregistre chaque appel API effectu\u00e9 par le r\u00f4le IAM assum\u00e9 par votre pipeline. Croisez l&rsquo;identifiant d&rsquo;ex\u00e9cution du pipeline avec le <code>userIdentity.sessionContext<\/code> de CloudTrail pour lier les changements cloud \u00e0 des ex\u00e9cutions de pipeline sp\u00e9cifiques.<\/li>\n<li><strong>GCP Cloud Audit Logs<\/strong> fournissent une tra\u00e7abilit\u00e9 similaire pour les actions des comptes de service.<\/li>\n<li><strong>Azure Activity Logs<\/strong> capturent les modifications de ressources effectu\u00e9es par les principaux de service du pipeline.<\/li>\n<\/ul>\n<h3>Alertes sur l&rsquo;escalade de privil\u00e8ges ou le contournement des politiques<\/h3>\n<p>Configurez des alertes pour les \u00e9v\u00e9nements qui indiquent que vos contr\u00f4les sont contourn\u00e9s :<\/p>\n<ul>\n<li>Un pipeline acc\u00e9dant \u00e0 des secrets dont il ne devrait pas avoir besoin (par exemple, l&rsquo;\u00e9tape de build acc\u00e9dant aux identifiants de base de donn\u00e9es de production).<\/li>\n<li>Des modifications aux r\u00e8gles de protection de branche ou aux fichiers CODEOWNERS.<\/li>\n<li>Des modifications aux politiques IAM attach\u00e9es aux comptes de service du pipeline.<\/li>\n<li>Des ex\u00e9cutions de pipeline d\u00e9clench\u00e9es depuis des branches non prot\u00e9g\u00e9es d\u00e9ployant vers des environnements prot\u00e9g\u00e9s.<\/li>\n<li>Des approbations de d\u00e9ploiement accord\u00e9es par la m\u00eame personne qui a \u00e9crit le code.<\/li>\n<\/ul>\n<p>Int\u00e9grez ces alertes dans votre workflow d&rsquo;op\u00e9rations de s\u00e9curit\u00e9 et traitez-les avec la m\u00eame urgence que les incidents de production.<\/p>\n<h2>Anti-patterns courants<\/h2>\n<p>Savoir quoi \u00e9viter est tout aussi important que savoir quoi impl\u00e9menter. Voici les anti-patterns que nous rencontrons le plus fr\u00e9quemment lors des \u00e9valuations de s\u00e9curit\u00e9 CI\/CD.<\/p>\n<h3>Un seul token admin pour toutes les op\u00e9rations CI\/CD<\/h3>\n<p>Un jeton d&rsquo;acc\u00e8s personnel avec une port\u00e9e admin, cr\u00e9\u00e9 par un ing\u00e9nieur senior, stock\u00e9 comme secret de d\u00e9p\u00f4t, et utilis\u00e9 par chaque job dans chaque pipeline. Quand cet ing\u00e9nieur quitte l&rsquo;organisation, personne ne r\u00e9voque le token parce que personne ne sait ce qui cessera de fonctionner. C&rsquo;est l&rsquo;anti-pattern le plus courant et le plus dangereux.<\/p>\n<p><strong>Correction :<\/strong> Remplacez par des comptes de service par \u00e9tape utilisant la f\u00e9d\u00e9ration OIDC. Aucun token statique, aucune identit\u00e9 partag\u00e9e.<\/p>\n<h3>D\u00e9sactiver la protection de branche \u00ab temporairement \u00bb<\/h3>\n<p>Un d\u00e9ploiement est bloqu\u00e9 parce qu&rsquo;une v\u00e9rification requise \u00e9choue. Quelqu&rsquo;un d\u00e9sactive la protection de branche pour pousser directement sur main, avec l&rsquo;intention de la r\u00e9activer plus tard. Il oublie, ou il la r\u00e9active mais manque un param\u00e8tre. Entre-temps, la fen\u00eatre non prot\u00e9g\u00e9e a permis un push direct qui a contourn\u00e9 la revue de code.<\/p>\n<p><strong>Correction :<\/strong> Ne d\u00e9sactivez jamais la protection de branche. Si une v\u00e9rification requise \u00e9choue, corrigez la v\u00e9rification ou utilisez un processus d&rsquo;urgence qui exige plusieurs approbations et cr\u00e9e une piste d&rsquo;audit.<\/p>\n<h3>Runners partag\u00e9s entre production et charges de travail de PR<\/h3>\n<p>Les pipelines de pull request provenant de forks s&rsquo;ex\u00e9cutent sur la m\u00eame infrastructure qui a acc\u00e8s r\u00e9seau aux syst\u00e8mes de production. Une PR malveillante peut exfiltrer des secrets, acc\u00e9der \u00e0 des services internes ou pivoter vers l&rsquo;infrastructure de production.<\/p>\n<p><strong>Correction :<\/strong> Utilisez des pools de runners s\u00e9par\u00e9s. Les charges de travail non fiables (PR, surtout celles provenant de forks) s&rsquo;ex\u00e9cutent sur des runners \u00e9ph\u00e9m\u00e8res et isol\u00e9s sans acc\u00e8s aux environnements sensibles. Les runners de d\u00e9ploiement en production sont restreints aux branches prot\u00e9g\u00e9es uniquement.<\/p>\n<h3>Acc\u00e8s SSH manuel quand les pipelines \u00e9chouent<\/h3>\n<p>Lorsqu&rsquo;un pipeline de d\u00e9ploiement \u00e9choue, un ing\u00e9nieur se connecte en SSH directement \u00e0 un serveur de production et d\u00e9ploie manuellement. Cela contourne chaque contr\u00f4le du pipeline : revue de code, tests automatis\u00e9s, signature d&rsquo;artefact, approbation de d\u00e9ploiement et journalisation d&rsquo;audit.<\/p>\n<p><strong>Correction :<\/strong> Investissez dans la fiabilit\u00e9 du pipeline pour que l&rsquo;intervention manuelle soit rarement n\u00e9cessaire. Quand elle l&rsquo;est, utilisez une proc\u00e9dure de bris de glace qui exige plusieurs approbations, cr\u00e9e une piste d&rsquo;audit et d\u00e9clenche une revue post-incident.<\/p>\n<h2>Conclusion<\/h2>\n<p>La s\u00e9paration des responsabilit\u00e9s et le moindre privil\u00e8ge ne sont pas des contraintes bureaucratiques impos\u00e9es par une \u00e9quipe de conformit\u00e9. Ce sont des contr\u00f4les d&rsquo;ing\u00e9nierie qui r\u00e9duisent directement le rayon d&rsquo;impact des incidents de s\u00e9curit\u00e9 dans votre pipeline de livraison logicielle.<\/p>\n<p>Une \u00e9tape de build compromise avec le moindre privil\u00e8ge peut produire un artefact malveillant \u2014 mais elle ne peut pas d\u00e9ployer cet artefact en production. Un identifiant de d\u00e9ploiement compromis limit\u00e9 au staging ne peut pas atteindre la production. Une pull request malveillante trait\u00e9e par un runner isol\u00e9 ne peut pas exfiltrer les secrets de production. Chaque contr\u00f4le limite ce qu&rsquo;un attaquant peut accomplir \u00e0 chaque \u00e9tape.<\/p>\n<p>Commencez par auditer les permissions actuelles de votre pipeline. Identifiez chaque compte de service, chaque identifiant stock\u00e9 et chaque secret auquel votre pipeline peut acc\u00e9der. Associez chacun \u00e0 l&rsquo;\u00e9tape et \u00e0 la t\u00e2che sp\u00e9cifique qui en a besoin. Puis commencez \u00e0 r\u00e9duire la port\u00e9e : remplacez les identifiants statiques par OIDC, divisez les comptes de service uniques en identit\u00e9s par \u00e9tape, ajoutez des portes d&rsquo;approbation pour les d\u00e9ploiements en production et prot\u00e9gez vos d\u00e9finitions de pipeline avec CODEOWNERS et la protection de branche.<\/p>\n<p>Vous n&rsquo;avez pas besoin de tout faire en une fois. Chaque am\u00e9lioration incr\u00e9mentale r\u00e9duit le risque. Mais commencez \u2014 car votre pipeline CI\/CD est probablement le syst\u00e8me le plus privil\u00e9gi\u00e9 et le moins scrut\u00e9 de toute votre infrastructure.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction La plupart des pipelines CI\/CD d\u00e9marrent avec un objectif simple : acheminer le code depuis la machine d&rsquo;un d\u00e9veloppeur vers la production le plus rapidement possible. En cours de route, quelqu&rsquo;un cr\u00e9e un compte de service, lui accorde des permissions larges, stocke les identifiants comme secret du pipeline, et passe \u00e0 autre chose. Cela &#8230; <a title=\"S\u00e9paration des Responsabilit\u00e9s et Moindre Privil\u00e8ge dans les Pipelines CI\/CD\" class=\"read-more\" href=\"https:\/\/secure-pipelines.com\/fr\/ci-cd-security\/separation-of-duties-least-privilege-ci-cd-pipelines\/\" aria-label=\"En savoir plus sur S\u00e9paration des Responsabilit\u00e9s et Moindre Privil\u00e8ge dans les Pipelines CI\/CD\">Lire la suite<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[49,51],"tags":[],"post_folder":[],"class_list":["post-500","post","type-post","status-publish","format-standard","hentry","category-ci-cd-security","category-pipeline-hardening"],"_links":{"self":[{"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/posts\/500","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/comments?post=500"}],"version-history":[{"count":1,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/posts\/500\/revisions"}],"predecessor-version":[{"id":516,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/posts\/500\/revisions\/516"}],"wp:attachment":[{"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/media?parent=500"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/categories?post=500"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/tags?post=500"},{"taxonomy":"post_folder","embeddable":true,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/post_folder?post=500"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}