{"id":501,"date":"2026-01-31T12:15:30","date_gmt":"2026-01-31T11:15:30","guid":{"rendered":"https:\/\/secure-pipelines.com\/?p=501"},"modified":"2026-03-24T12:55:40","modified_gmt":"2026-03-24T11:55:40","slug":"secure-deployment-workflows-ci-cd-pipeline-production","status":"publish","type":"post","link":"https:\/\/secure-pipelines.com\/fr\/ci-cd-security\/secure-deployment-workflows-ci-cd-pipeline-production\/","title":{"rendered":"Workflows de D\u00e9ploiement S\u00e9curis\u00e9s : Du Pipeline CI\/CD \u00e0 la Production"},"content":{"rendered":"<p>Votre pipeline CI\/CD peut disposer de contr\u00f4les de s\u00e9curit\u00e9 herm\u00e9tiques \u2014 commits sign\u00e9s, d\u00e9pendances \u00e9pingl\u00e9es, analyses SAST, signature d&rsquo;images de conteneurs \u2014 mais tout cela ne sert \u00e0 rien si le processus de d\u00e9ploiement lui-m\u00eame est faible. Le d\u00e9ploiement est le point de jonction critique o\u00f9 la s\u00e9curit\u00e9 du pipeline rencontre la s\u00e9curit\u00e9 de la production. Un workflow de d\u00e9ploiement compromis peut contourner tous les contr\u00f4les en amont que vous avez mis en place, poussant du code malveillant directement dans l&rsquo;environnement dont d\u00e9pendent vos clients.<\/p>\n<p>Ce guide explique comment construire des workflows de d\u00e9ploiement s\u00e9curis\u00e9s de bout en bout : choisir le bon mod\u00e8le de d\u00e9ploiement, appliquer des portes de validation et des approbations, v\u00e9rifier les artefacts au moment du d\u00e9ploiement, d\u00e9ployer les changements de mani\u00e8re progressive, et maintenir une piste d&rsquo;audit compl\u00e8te du commit \u00e0 la production.<\/p>\n<h2 class=\"wp-block-heading\">Mod\u00e8les de D\u00e9ploiement : Push-Based vs Pull-Based (GitOps)<\/h2>\n<p>La premi\u00e8re d\u00e9cision architecturale qui fa\u00e7onne votre posture de s\u00e9curit\u00e9 en mati\u00e8re de d\u00e9ploiement est le choix entre un mod\u00e8le push-based ou pull-based.<\/p>\n<h3 class=\"wp-block-heading\">D\u00e9ploiements Push-Based (pilot\u00e9s par le CI)<\/h3>\n<p>Dans un mod\u00e8le push-based traditionnel, le pipeline CI\/CD construit l&rsquo;artefact puis le pousse directement vers l&rsquo;environnement cible. GitHub Actions d\u00e9ploie sur Kubernetes via <code>kubectl apply<\/code>, ou un job GitLab CI ex\u00e9cute <code>helm upgrade<\/code> contre un cluster. Le pipeline lui-m\u00eame d\u00e9tient les identifiants d&rsquo;acc\u00e8s \u00e0 l&rsquo;environnement de production.<\/p>\n<p>Ce mod\u00e8le est simple mais comporte un risque inh\u00e9rent : le runner CI dispose d&rsquo;un acc\u00e8s direct en \u00e9criture \u00e0 la production. Si un attaquant compromet le pipeline \u2014 via une d\u00e9pendance empoisonn\u00e9e, une pull request malveillante ou un secret vol\u00e9 \u2014 il h\u00e9rite imm\u00e9diatement de cet acc\u00e8s \u00e0 la production.<\/p>\n<h3 class=\"wp-block-heading\">D\u00e9ploiements Pull-Based (GitOps)<\/h3>\n<p>Dans un mod\u00e8le pull-based ou GitOps, un contr\u00f4leur d\u00e9di\u00e9 s&rsquo;ex\u00e9cutant \u00e0 l&rsquo;int\u00e9rieur de l&rsquo;environnement cible \u2014 tel que <strong>Flux<\/strong> ou <strong>ArgoCD<\/strong> \u2014 surveille un d\u00e9p\u00f4t Git pour d\u00e9tecter les changements d&rsquo;\u00e9tat souhait\u00e9s. Lorsqu&rsquo;un nouveau manifeste est commit\u00e9 (g\u00e9n\u00e9ralement par le pipeline CI mettant \u00e0 jour un tag d&rsquo;image), le contr\u00f4leur r\u00e9cup\u00e8re le changement et r\u00e9concilie le cluster pour correspondre \u00e0 l&rsquo;\u00e9tat souhait\u00e9.<\/p>\n<p>L&rsquo;avantage en mati\u00e8re de s\u00e9curit\u00e9 est significatif. Le pipeline CI n&rsquo;a jamais besoin d&rsquo;identifiants directs vers le cluster de production. La surface d&rsquo;attaque se r\u00e9duit car l&rsquo;agent de d\u00e9ploiement vit \u00e0 l&rsquo;int\u00e9rieur du cluster et ne r\u00e9cup\u00e8re que depuis une source connue. La d\u00e9tection de d\u00e9rive est int\u00e9gr\u00e9e : si quelqu&rsquo;un modifie manuellement une ressource, le contr\u00f4leur la ram\u00e8ne \u00e0 l&rsquo;\u00e9tat correspondant \u00e0 Git.<\/p>\n<p><strong>Recommandation :<\/strong> Pour les charges de travail de production, privil\u00e9giez un mod\u00e8le pull-based GitOps. R\u00e9servez les d\u00e9ploiements push-based aux environnements de d\u00e9veloppement et de staging o\u00f9 la rapidit\u00e9 prime sur le contr\u00f4le d&rsquo;acc\u00e8s strict. M\u00eame dans les configurations push-based, appliquez rigoureusement le principe du moindre privil\u00e8ge aux identifiants de d\u00e9ploiement.<\/p>\n<h2 class=\"wp-block-heading\">Portes de D\u00e9ploiement : Approbations Manuelles et Environnements Prot\u00e9g\u00e9s<\/h2>\n<p>Les pipelines automatis\u00e9s sont rapides, mais le d\u00e9ploiement en production ne devrait pas se faire sans v\u00e9rification humaine pour les changements \u00e0 fort impact. Les portes de d\u00e9ploiement introduisent des points de contr\u00f4le qui n\u00e9cessitent une approbation explicite avant qu&rsquo;une release ne soit ex\u00e9cut\u00e9e.<\/p>\n<h3 class=\"wp-block-heading\">Environnements GitHub et R\u00e9viseurs Obligatoires<\/h3>\n<p>GitHub Actions prend en charge les <strong>Environments<\/strong> avec des r\u00e8gles de protection. Vous pouvez exiger qu&rsquo;un ou plusieurs r\u00e9viseurs approuvent un d\u00e9ploiement avant que le job ne s&rsquo;ex\u00e9cute. Cela est configur\u00e9 dans les param\u00e8tres du d\u00e9p\u00f4t et appliqu\u00e9 au niveau de la plateforme \u2014 le code du pipeline ne peut pas le contourner.<\/p>\n<pre><code># .github\/workflows\/deploy.yml\njobs:\n  deploy-production:\n    runs-on: ubuntu-latest\n    environment:\n      name: production\n      url: https:\/\/app.example.com\n    steps:\n      - name: Checkout\n        uses: actions\/checkout@v4\n\n      - name: Verify artifact signature\n        run: |\n          cosign verify \\\n            --key cosign.pub \\\n            ghcr.io\/myorg\/myapp:${{ github.sha }}\n\n      - name: Deploy to production\n        run: |\n          helm upgrade --install myapp .\/chart \\\n            --set image.tag=${{ github.sha }} \\\n            --namespace production\n<\/code><\/pre>\n<p>Avec l&rsquo;environnement <code>production<\/code> configur\u00e9 pour exiger des r\u00e9viseurs, ce job se met en pause et attend l&rsquo;approbation avant d&rsquo;ex\u00e9cuter toute \u00e9tape. L&rsquo;approbateur voit exactement quel commit et quelle ex\u00e9cution de workflow a d\u00e9clench\u00e9 le d\u00e9ploiement.<\/p>\n<h3 class=\"wp-block-heading\">Environnements Prot\u00e9g\u00e9s GitLab<\/h3>\n<p>GitLab propose des <strong>environnements prot\u00e9g\u00e9s<\/strong> qui restreignent quels utilisateurs ou groupes peuvent d\u00e9clencher des d\u00e9ploiements. Combin\u00e9s avec des jobs manuels, cela cr\u00e9e un workflow d&rsquo;approbation robuste.<\/p>\n<pre><code># .gitlab-ci.yml\ndeploy_production:\n  stage: deploy\n  environment:\n    name: production\n    url: https:\/\/app.example.com\n  rules:\n    - if: $CI_COMMIT_BRANCH == \"main\"\n      when: manual\n  script:\n    - cosign verify --key cosign.pub $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA\n    - helm upgrade --install myapp .\/chart\n        --set image.tag=$CI_COMMIT_SHA\n        --namespace production\n  resource_group: production\n<\/code><\/pre>\n<p>La directive <code>when: manual<\/code> exige qu&rsquo;un utilisateur clique sur \u00ab Play \u00bb dans l&rsquo;interface GitLab. Le <code>resource_group<\/code> garantit qu&rsquo;un seul d\u00e9ploiement s&rsquo;ex\u00e9cute \u00e0 la fois, \u00e9vitant les conditions de concurrence.<\/p>\n<h3 class=\"wp-block-heading\">Approbations via Slack et ChatOps<\/h3>\n<p>Pour les \u00e9quipes qui vivent dans Slack, l&rsquo;int\u00e9gration des workflows d&rsquo;approbation avec le chat offre de la visibilit\u00e9 et des temps de r\u00e9ponse rapides. Des outils comme <strong>Opsgenie<\/strong>, <strong>PagerDuty<\/strong> ou des bots Slack personnalis\u00e9s peuvent publier une demande de d\u00e9ploiement dans un canal et attendre qu&rsquo;un utilisateur autoris\u00e9 approuve via un bouton ou une r\u00e9action. L&rsquo;exigence cl\u00e9 est que le m\u00e9canisme d&rsquo;approbation soit auditable et ne puisse pas \u00eatre falsifi\u00e9 \u2014 utilisez des tokens d&rsquo;application Slack v\u00e9rifi\u00e9s et journalisez chaque d\u00e9cision d&rsquo;approbation.<\/p>\n<h2 class=\"wp-block-heading\">V\u00e9rification des Artefacts au Moment du D\u00e9ploiement<\/h2>\n<p>Signer les artefacts pendant la phase de build n&rsquo;est que la moiti\u00e9 de l&rsquo;\u00e9quation. Vous devez <strong>v\u00e9rifier<\/strong> ces signatures au moment du d\u00e9ploiement. Sinon, un attaquant qui obtient l&rsquo;acc\u00e8s \u00e0 votre registre peut remplacer une image sign\u00e9e par une image non sign\u00e9e ou re-sign\u00e9e malveillante.<\/p>\n<h3 class=\"wp-block-heading\">V\u00e9rification Cosign Avant le D\u00e9ploiement<\/h3>\n<p>Ajoutez une \u00e9tape de v\u00e9rification explicite dans votre pipeline de d\u00e9ploiement qui s&rsquo;ex\u00e9cute avant toute commande de d\u00e9ploiement. Si la v\u00e9rification \u00e9choue, le pipeline doit s&rsquo;arr\u00eater imm\u00e9diatement.<\/p>\n<pre><code># V\u00e9rifier la signature de l'image avant le d\u00e9ploiement\ncosign verify \\\n  --certificate-identity \"https:\/\/github.com\/myorg\/myapp\/.github\/workflows\/build.yml@refs\/heads\/main\" \\\n  --certificate-oidc-issuer \"https:\/\/token.actions.githubusercontent.com\" \\\n  ghcr.io\/myorg\/myapp@sha256:abc123...\n\n# V\u00e9rifier la provenance SLSA\ncosign verify-attestation \\\n  --type slsaprovenance \\\n  --certificate-identity \"https:\/\/github.com\/slsa-framework\/slsa-github-generator\/.github\/workflows\/generator_container_slsa3.yml@refs\/tags\/v1.9.0\" \\\n  --certificate-oidc-issuer \"https:\/\/token.actions.githubusercontent.com\" \\\n  ghcr.io\/myorg\/myapp@sha256:abc123...\n<\/code><\/pre>\n<h3 class=\"wp-block-heading\">Contr\u00f4leurs d&rsquo;Admission : Kyverno et Sigstore Policy Controller<\/h3>\n<p>La v\u00e9rification au niveau du pipeline est bonne, mais elle peut \u00eatre contourn\u00e9e si quelqu&rsquo;un d\u00e9ploie directement sur le cluster en utilisant <code>kubectl<\/code>. Les <strong>contr\u00f4leurs d&rsquo;admission<\/strong> appliquent la v\u00e9rification au niveau du serveur API Kubernetes \u2014 aucune image non sign\u00e9e ne peut entrer dans le cluster, quelle que soit la m\u00e9thode de soumission.<\/p>\n<p><strong>Kyverno<\/strong> est un moteur de politiques natif Kubernetes qui peut v\u00e9rifier les signatures d&rsquo;images et les attestations dans le cadre de son webhook d&rsquo;admission :<\/p>\n<pre><code>apiVersion: kyverno.io\/v1\nkind: ClusterPolicy\nmetadata:\n  name: require-signed-images\nspec:\n  validationFailureAction: Enforce\n  background: false\n  rules:\n    - name: verify-signature\n      match:\n        any:\n          - resources:\n              kinds:\n                - Pod\n      verifyImages:\n        - imageReferences:\n            - \"ghcr.io\/myorg\/*\"\n          attestors:\n            - entries:\n                - keyless:\n                    subject: \"https:\/\/github.com\/myorg\/*\"\n                    issuer: \"https:\/\/token.actions.githubusercontent.com\"\n          attestations:\n            - type: https:\/\/slsa.dev\/provenance\/v1\n              conditions:\n                - all:\n                    - key: \"{{ builder.id }}\"\n                      operator: Equals\n                      value: \"https:\/\/github.com\/slsa-framework\/slsa-github-generator\/.github\/workflows\/generator_container_slsa3.yml@refs\/tags\/v1.9.0\"\n<\/code><\/pre>\n<p>Le <strong>Sigstore Policy Controller<\/strong> (anciennement cosigned) offre des fonctionnalit\u00e9s similaires et est maintenu par le projet Sigstore. Il s&rsquo;int\u00e8gre \u00e9troitement aux workflows de signature keyless et constitue un choix solide si votre organisation s&rsquo;est standardis\u00e9e sur l&rsquo;\u00e9cosyst\u00e8me Sigstore.<\/p>\n<p>La combinaison de la v\u00e9rification au niveau du pipeline et du contr\u00f4le d&rsquo;admission au niveau du cluster cr\u00e9e une d\u00e9fense en profondeur : m\u00eame si une couche est contourn\u00e9e, l&rsquo;autre intercepte les artefacts non autoris\u00e9s.<\/p>\n<h2 class=\"wp-block-heading\">D\u00e9ploiements Progressifs : Canary, Blue-Green et Feature Flags<\/h2>\n<p>D\u00e9ployer une nouvelle version sur 100 % du trafic instantan\u00e9ment repr\u00e9sente un risque pour la s\u00e9curit\u00e9 et la fiabilit\u00e9. Les strat\u00e9gies de d\u00e9ploiement progressif vous permettent de d\u00e9tecter les probl\u00e8mes \u2014 y compris les probl\u00e8mes de s\u00e9curit\u00e9 \u2014 avant qu&rsquo;ils n&rsquo;affectent tous les utilisateurs.<\/p>\n<h3 class=\"wp-block-heading\">D\u00e9ploiements Canary<\/h3>\n<p>Un d\u00e9ploiement canary achemine un faible pourcentage du trafic (par exemple, 5 %) vers la nouvelle version tandis que la majorit\u00e9 continue d&rsquo;atteindre la version stable. Si des m\u00e9triques telles que les taux d&rsquo;erreur, la latence ou les signaux de s\u00e9curit\u00e9 (connexions sortantes inattendues, escalades de privil\u00e8ges \u00e9lev\u00e9es) se d\u00e9gradent, le canary est automatiquement annul\u00e9.<\/p>\n<p>Des outils comme <strong>Flagger<\/strong> (pour Kubernetes), <strong>AWS App Mesh<\/strong> et <strong>Istio<\/strong> automatisent l&rsquo;analyse canary. Flagger, par exemple, peut \u00eatre configur\u00e9 pour surveiller des m\u00e9triques Prometheus personnalis\u00e9es et promouvoir ou annuler automatiquement :<\/p>\n<pre><code>apiVersion: flagger.app\/v1beta1\nkind: Canary\nmetadata:\n  name: myapp\n  namespace: production\nspec:\n  targetRef:\n    apiVersion: apps\/v1\n    kind: Deployment\n    name: myapp\n  progressDeadlineSeconds: 600\n  service:\n    port: 8080\n  analysis:\n    interval: 1m\n    threshold: 5\n    maxWeight: 50\n    stepWeight: 10\n    metrics:\n      - name: request-success-rate\n        thresholdRange:\n          min: 99\n        interval: 1m\n      - name: request-duration\n        thresholdRange:\n          max: 500\n        interval: 1m\n<\/code><\/pre>\n<h3 class=\"wp-block-heading\">D\u00e9ploiements Blue-Green<\/h3>\n<p>Les d\u00e9ploiements blue-green maintiennent deux environnements identiques. L&rsquo;environnement \u00ab blue \u00bb ex\u00e9cute la version actuelle ; le \u00ab green \u00bb ex\u00e9cute la nouvelle. Le trafic est bascul\u00e9 d&rsquo;un coup (g\u00e9n\u00e9ralement via un load balancer ou un changement DNS) apr\u00e8s que l&rsquo;environnement green a pass\u00e9 les v\u00e9rifications de sant\u00e9 et la validation de s\u00e9curit\u00e9. Si quelque chose tourne mal, le retour au blue est instantan\u00e9.<\/p>\n<p>L&rsquo;avantage en mati\u00e8re de s\u00e9curit\u00e9 est un chemin de rollback propre et pr\u00e9visible. Il n&rsquo;y a pas d&rsquo;\u00e9tat partiel \u00e0 analyser, et la version pr\u00e9c\u00e9dente reste pleinement op\u00e9rationnelle tout au long du d\u00e9ploiement.<\/p>\n<h3 class=\"wp-block-heading\">Feature Flags comme Contr\u00f4les de S\u00e9curit\u00e9<\/h3>\n<p>Les feature flags d\u00e9couplent le d\u00e9ploiement de la release. Le code est d\u00e9ploy\u00e9 en production mais reste inactif derri\u00e8re un flag. Cela donne aux \u00e9quipes de s\u00e9curit\u00e9 un interrupteur d&rsquo;urgence : si une fonctionnalit\u00e9 nouvellement publi\u00e9e introduit une vuln\u00e9rabilit\u00e9 ou se comporte de mani\u00e8re inattendue, elle peut \u00eatre d\u00e9sactiv\u00e9e instantan\u00e9ment sans rollback complet. Des outils comme <strong>LaunchDarkly<\/strong>, <strong>Unleash<\/strong> et <strong>OpenFeature<\/strong> fournissent une gestion centralis\u00e9e des flags avec des journaux d&rsquo;audit indiquant qui a bascul\u00e9 quoi et quand.<\/p>\n<h2 class=\"wp-block-heading\">Strat\u00e9gies de Rollback<\/h2>\n<p>Chaque plan de d\u00e9ploiement doit inclure un plan de rollback. Quand les choses tournent mal \u2014 et elles tourneront mal \u2014 la rapidit\u00e9 et la fiabilit\u00e9 de votre rollback d\u00e9terminent directement le rayon d&rsquo;impact.<\/p>\n<h3 class=\"wp-block-heading\">Rollback Automatique en Cas d&rsquo;\u00c9chec du Health Check<\/h3>\n<p>Kubernetes prend nativement en charge le rollback via son contr\u00f4leur de d\u00e9ploiement. Si les nouveaux pods \u00e9chouent aux sondes readiness ou liveness, le d\u00e9ploiement se bloque et peut \u00eatre automatiquement invers\u00e9 :<\/p>\n<pre><code># V\u00e9rifier le statut du d\u00e9ploiement et effectuer un rollback si n\u00e9cessaire\nkubectl rollout status deployment\/myapp --namespace production --timeout=300s\nif [ $? -ne 0 ]; then\n  echo \"Le d\u00e9ploiement a \u00e9chou\u00e9, lancement du rollback\"\n  kubectl rollout undo deployment\/myapp --namespace production\n  exit 1\nfi\n<\/code><\/pre>\n<p>Dans un mod\u00e8le GitOps, le rollback signifie reverter le commit Git qui a introduit le changement. Le contr\u00f4leur d\u00e9tecte le revert et r\u00e9concilie le cluster vers l&rsquo;\u00e9tat pr\u00e9c\u00e9dent. Cela pr\u00e9serve la piste d&rsquo;audit compl\u00e8te dans Git.<\/p>\n<h3 class=\"wp-block-heading\">D\u00e9ploiements Immuables<\/h3>\n<p>Les d\u00e9ploiements immuables traitent chaque release comme une nouvelle instance jetable. Au lieu de mettre \u00e0 jour les conteneurs en place, vous d\u00e9ployez un ensemble enti\u00e8rement nouveau de ressources et d\u00e9commissionnez les anciens. Cela \u00e9limine la d\u00e9rive de configuration et garantit que ce qui a \u00e9t\u00e9 test\u00e9 est exactement ce qui s&rsquo;ex\u00e9cute en production. Combin\u00e9s aux digests d&rsquo;images (plut\u00f4t qu&rsquo;aux tags mutables comme <code>latest<\/code>), les d\u00e9ploiements immuables garantissent la reproductibilit\u00e9 binaire.<\/p>\n<h2 class=\"wp-block-heading\">S\u00e9paration des Identit\u00e9s de Build et de D\u00e9ploiement<\/h2>\n<p>L&rsquo;une des am\u00e9liorations de s\u00e9curit\u00e9 les plus impactantes que vous puissiez apporter est de garantir que l&rsquo;identit\u00e9 utilis\u00e9e pour construire les artefacts est diff\u00e9rente de celle utilis\u00e9e pour les d\u00e9ployer. Cela limite le rayon d&rsquo;impact d&rsquo;une compromission dans l&rsquo;une ou l&rsquo;autre phase.<\/p>\n<h3 class=\"wp-block-heading\">Identifiants Diff\u00e9rents<\/h3>\n<p>Le pipeline de build devrait avoir des identifiants pour pousser des images vers un registre et les signer \u2014 mais aucun acc\u00e8s \u00e0 l&rsquo;infrastructure de production. Le pipeline de d\u00e9ploiement (ou le contr\u00f4leur GitOps) devrait avoir des identifiants pour r\u00e9cup\u00e9rer les images et appliquer les manifestes \u2014 mais aucun acc\u00e8s aux d\u00e9p\u00f4ts de code source ou aux cl\u00e9s de signature.<\/p>\n<p>En pratique, cela signifie utiliser des comptes de service s\u00e9par\u00e9s, des r\u00f4les IAM ou des claims OIDC pour chaque phase. Sur AWS, le r\u00f4le de build pourrait avoir des permissions pour le push ECR et la signature KMS, tandis que le r\u00f4le de d\u00e9ploiement a des permissions pour EKS et Secrets Manager mais pas pour le push ECR.<\/p>\n<h3 class=\"wp-block-heading\">Runners Diff\u00e9rents<\/h3>\n<p>Poussez la s\u00e9paration plus loin en ex\u00e9cutant les jobs de build et de d\u00e9ploiement sur des runners physiquement diff\u00e9rents. Les jobs de build s&rsquo;ex\u00e9cutent sur des runners \u00e9ph\u00e9m\u00e8res et polyvalents. Les jobs de d\u00e9ploiement s&rsquo;ex\u00e9cutent sur des runners d\u00e9di\u00e9s et renforc\u00e9s qui se trouvent dans un p\u00e9rim\u00e8tre r\u00e9seau plus proche de l&rsquo;environnement de production. Cela emp\u00eache un runner de build compromis de pivoter vers la production.<\/p>\n<p>Pour un traitement plus approfondi de la s\u00e9paration des identit\u00e9s et des principes de moindre privil\u00e8ge dans le CI\/CD, consultez notre guide sur la <a href=\"https:\/\/secure-pipelines.com\/fr\/ci-cd-security\/separation-of-duties-least-privilege-ci-cd-pipelines\/\">S\u00e9paration des Responsabilit\u00e9s et le Moindre Privil\u00e8ge dans les Pipelines CI\/CD<\/a>.<\/p>\n<h2 class=\"wp-block-heading\">Gels de D\u00e9ploiement et Fen\u00eatres de Changement<\/h2>\n<p>Chaque moment n&rsquo;est pas propice au d\u00e9ploiement. Les gels de d\u00e9ploiement \u2014 des p\u00e9riodes durant lesquelles les changements en production sont interdits \u2014 r\u00e9duisent les risques pendant les \u00e9v\u00e9nements \u00e0 fort trafic, les vacances, les transitions d&rsquo;astreinte ou la r\u00e9ponse active aux incidents.<\/p>\n<p>Impl\u00e9mentez les gels au niveau de la plateforme, pas seulement comme un accord d&rsquo;\u00e9quipe. Les Environments GitHub prennent en charge les <strong>politiques de branches de d\u00e9ploiement<\/strong> et les <strong>temporisateurs d&rsquo;attente<\/strong>. GitLab permet les <strong>gels de d\u00e9ploiement<\/strong> configur\u00e9s via l&rsquo;interface ou l&rsquo;API avec des planifications de type cron. Pour les workflows bas\u00e9s sur Kubernetes, vous pouvez appliquer les gels avec une politique OPA\/Gatekeeper ou Kyverno qui rejette les d\u00e9ploiements pendant des fen\u00eatres temporelles sp\u00e9cifiques.<\/p>\n<pre><code># Politique Kyverno pour appliquer un gel de d\u00e9ploiement\napiVersion: kyverno.io\/v1\nkind: ClusterPolicy\nmetadata:\n  name: deployment-freeze\nspec:\n  validationFailureAction: Enforce\n  background: false\n  rules:\n    - name: block-deployments-during-freeze\n      match:\n        any:\n          - resources:\n              kinds:\n                - Deployment\n              namespaces:\n                - production\n      preconditions:\n        all:\n          - key: \"{{ time_now() }}\"\n            operator: GreaterThan\n            value: \"2026-03-27T00:00:00Z\"  # D\u00e9but du gel\n          - key: \"{{ time_now() }}\"\n            operator: LessThan\n            value: \"2026-03-30T00:00:00Z\"  # Fin du gel\n      validate:\n        message: \"Les d\u00e9ploiements en production sont gel\u00e9s jusqu'au 30 mars. Contactez l'\u00e9quipe plateforme pour les exceptions d'urgence.\"\n        deny: {}\n<\/code><\/pre>\n<p>Documentez un processus d&rsquo;exception pour les correctifs de s\u00e9curit\u00e9 urgents qui doivent \u00eatre d\u00e9ploy\u00e9s pendant un gel, incluant qui peut autoriser l&rsquo;exception et comment elle est journalis\u00e9e.<\/p>\n<h2 class=\"wp-block-heading\">Piste d&rsquo;Audit : Lier les D\u00e9ploiements aux Commits, Approbateurs et Ex\u00e9cutions de Pipeline<\/h2>\n<p>Un workflow de d\u00e9ploiement s\u00e9curis\u00e9 produit une piste d&rsquo;audit compl\u00e8te et inalt\u00e9rable. Pour chaque d\u00e9ploiement en production, vous devriez pouvoir r\u00e9pondre \u00e0 : <em>Qu&rsquo;est-ce qui<\/em> a \u00e9t\u00e9 d\u00e9ploy\u00e9 ? <em>Qui<\/em> l&rsquo;a approuv\u00e9 ? <em>Quel<\/em> pipeline l&rsquo;a construit ? <em>\u00c0 quel<\/em> commit cela remonte-t-il ?<\/p>\n<h3 class=\"wp-block-heading\">Journaux d&rsquo;Audit au Niveau de la Plateforme<\/h3>\n<p><strong>AWS CloudTrail<\/strong> enregistre les appels API vers EKS, ECS et Lambda, y compris qui a initi\u00e9 le d\u00e9ploiement et depuis quelle source. Les <strong>journaux d&rsquo;audit GCP<\/strong> fournissent une couverture similaire pour GKE et Cloud Run. Assurez-vous que ces journaux sont envoy\u00e9s vers un magasin de logs centralis\u00e9 et immuable (tel qu&rsquo;un bucket S3 d\u00e9di\u00e9 avec verrouillage d&rsquo;objet ou un SIEM) o\u00f9 ils ne peuvent pas \u00eatre falsifi\u00e9s par un attaquant ayant compromis l&rsquo;environnement de d\u00e9ploiement.<\/p>\n<h3 class=\"wp-block-heading\">Tra\u00e7abilit\u00e9 au Niveau du Pipeline<\/h3>\n<p>Annotez les ressources Kubernetes avec des m\u00e9tadonn\u00e9es de d\u00e9ploiement afin de pouvoir remonter d&rsquo;un pod en cours d&rsquo;ex\u00e9cution jusqu&rsquo;\u00e0 la source exacte :<\/p>\n<pre><code># Inclure dans votre chart Helm ou overlay Kustomize\nmetadata:\n  labels:\n    app.kubernetes.io\/version: \"{{ .Values.image.tag }}\"\n  annotations:\n    deploy.example.com\/commit-sha: \"{{ .Values.commitSha }}\"\n    deploy.example.com\/pipeline-url: \"{{ .Values.pipelineUrl }}\"\n    deploy.example.com\/approved-by: \"{{ .Values.approvedBy }}\"\n    deploy.example.com\/deployed-at: \"{{ now | date \\\"2006-01-02T15:04:05Z\\\" }}\"\n<\/code><\/pre>\n<p>Dans GitHub Actions, transmettez ces valeurs via le workflow de d\u00e9ploiement :<\/p>\n<pre><code>- name: Deploy with traceability\n  run: |\n    helm upgrade --install myapp .\/chart \\\n      --set image.tag=${{ github.sha }} \\\n      --set commitSha=${{ github.sha }} \\\n      --set pipelineUrl=\"https:\/\/github.com\/${{ github.repository }}\/actions\/runs\/${{ github.run_id }}\" \\\n      --set approvedBy=\"${{ github.actor }}\" \\\n      --namespace production\n<\/code><\/pre>\n<h2 class=\"wp-block-heading\">Surveillance Post-D\u00e9ploiement<\/h2>\n<p>Le d\u00e9ploiement ne s&rsquo;arr\u00eate pas quand la nouvelle version est en cours d&rsquo;ex\u00e9cution. La surveillance post-d\u00e9ploiement ferme la boucle de r\u00e9troaction et d\u00e9tecte les probl\u00e8mes que les v\u00e9rifications pr\u00e9-d\u00e9ploiement ont manqu\u00e9s.<\/p>\n<h3 class=\"wp-block-heading\">D\u00e9tection d&rsquo;Anomalies<\/h3>\n<p>\u00c9tablissez des m\u00e9triques de r\u00e9f\u00e9rence pour le comportement normal de l&rsquo;application : taux de requ\u00eates, taux d&rsquo;erreurs, percentiles de latence, utilisation CPU\/m\u00e9moire et mod\u00e8les de connexions r\u00e9seau. Apr\u00e8s chaque d\u00e9ploiement, comparez les m\u00e9triques actuelles avec la r\u00e9f\u00e9rence. Des outils comme <strong>Prometheus + Alertmanager<\/strong>, <strong>Datadog<\/strong> et <strong>Grafana Alerting<\/strong> peuvent d\u00e9clencher des alertes lorsque les m\u00e9triques post-d\u00e9ploiement d\u00e9vient au-del\u00e0 des seuils.<\/p>\n<p>Du point de vue de la s\u00e9curit\u00e9, portez une attention particuli\u00e8re aux connexions r\u00e9seau sortantes inattendues, aux nouveaux processus lanc\u00e9s \u00e0 l&rsquo;int\u00e9rieur des conteneurs, aux appels syst\u00e8me \u00e9lev\u00e9s et aux augmentations soudaines des \u00e9checs d&rsquo;authentification. Ceux-ci peuvent indiquer qu&rsquo;un artefact compromis a travers\u00e9 le pipeline.<\/p>\n<h3 class=\"wp-block-heading\">M\u00e9triques DORA pour la S\u00e9curit\u00e9<\/h3>\n<p>Les quatre m\u00e9triques DORA \u2014 fr\u00e9quence de d\u00e9ploiement, d\u00e9lai de mise en production des changements, taux d&rsquo;\u00e9chec des changements et temps moyen de r\u00e9cup\u00e9ration \u2014 sont g\u00e9n\u00e9ralement utilis\u00e9es pour mesurer la performance DevOps. Elles sont tout aussi pr\u00e9cieuses pour la s\u00e9curit\u00e9 :<\/p>\n<ul class=\"wp-block-list\">\n<li><strong>Fr\u00e9quence de d\u00e9ploiement<\/strong> indique \u00e0 quelle fr\u00e9quence vous pouvez livrer des correctifs de s\u00e9curit\u00e9. Une fr\u00e9quence plus \u00e9lev\u00e9e signifie une rem\u00e9diation plus rapide.<\/li>\n<li><strong>D\u00e9lai de mise en production des changements<\/strong> mesure la rapidit\u00e9 avec laquelle un correctif de s\u00e9curit\u00e9 passe du commit \u00e0 la production. Des d\u00e9lais longs signifient des fen\u00eatres d&rsquo;exposition prolong\u00e9es.<\/li>\n<li><strong>Taux d&rsquo;\u00e9chec des changements<\/strong> suit la fr\u00e9quence \u00e0 laquelle les d\u00e9ploiements causent des incidents. Un taux \u00e9lev\u00e9 sugg\u00e8re des tests ou une v\u00e9rification inad\u00e9quats \u2014 un probl\u00e8me de s\u00e9curit\u00e9.<\/li>\n<li><strong>Temps moyen de r\u00e9cup\u00e9ration (MTTR)<\/strong> mesure la rapidit\u00e9 avec laquelle vous pouvez effectuer un rollback ou rem\u00e9dier \u00e0 un mauvais d\u00e9ploiement. Un MTTR bas limite le rayon d&rsquo;impact de tout incident, y compris une br\u00e8che de s\u00e9curit\u00e9.<\/li>\n<\/ul>\n<p>Suivez ces m\u00e9triques par environnement et corr\u00e9lez-les avec les \u00e9v\u00e9nements de s\u00e9curit\u00e9. Si votre taux d&rsquo;\u00e9chec des changements augmente apr\u00e8s l&rsquo;adoption d&rsquo;un nouveau mod\u00e8le de d\u00e9ploiement, enqu\u00eatez avant que cela ne devienne un risque de s\u00e9curit\u00e9.<\/p>\n<h2 class=\"wp-block-heading\">Synth\u00e8se : Un Pipeline de D\u00e9ploiement S\u00e9curis\u00e9 Complet<\/h2>\n<p>Voici un workflow GitHub Actions complet qui int\u00e8gre les pratiques discut\u00e9es ci-dessus \u2014 v\u00e9rification des artefacts, approbations bas\u00e9es sur les environnements, tra\u00e7abilit\u00e9 du d\u00e9ploiement et rollback automatique :<\/p>\n<pre><code># .github\/workflows\/secure-deploy.yml\nname: Secure Deployment\n\non:\n  workflow_run:\n    workflows: [\"Build and Sign\"]\n    types: [completed]\n    branches: [main]\n\njobs:\n  verify-and-deploy:\n    runs-on: ubuntu-latest\n    if: ${{ github.event.workflow_run.conclusion == 'success' }}\n    environment:\n      name: production\n      url: https:\/\/app.example.com\n    permissions:\n      id-token: write\n      contents: read\n    steps:\n      - name: Checkout manifests\n        uses: actions\/checkout@v4\n\n      - name: Install cosign\n        uses: sigstore\/cosign-installer@v3\n\n      - name: Verify image signature (keyless)\n        run: |\n          IMAGE=\"ghcr.io\/myorg\/myapp@${{ github.event.workflow_run.head_sha }}\"\n          cosign verify \\\n            --certificate-identity \"https:\/\/github.com\/myorg\/myapp\/.github\/workflows\/build.yml@refs\/heads\/main\" \\\n            --certificate-oidc-issuer \"https:\/\/token.actions.githubusercontent.com\" \\\n            \"$IMAGE\"\n\n      - name: Verify SLSA provenance\n        run: |\n          IMAGE=\"ghcr.io\/myorg\/myapp@${{ github.event.workflow_run.head_sha }}\"\n          cosign verify-attestation \\\n            --type slsaprovenance \\\n            --certificate-identity \"https:\/\/github.com\/slsa-framework\/slsa-github-generator\/.github\/workflows\/generator_container_slsa3.yml@refs\/tags\/v1.9.0\" \\\n            --certificate-oidc-issuer \"https:\/\/token.actions.githubusercontent.com\" \\\n            \"$IMAGE\"\n\n      - name: Configure AWS credentials (deploy role)\n        uses: aws-actions\/configure-aws-credentials@v4\n        with:\n          role-to-assume: arn:aws:iam::123456789012:role\/deploy-production\n          aws-region: us-east-1\n\n      - name: Deploy to EKS\n        run: |\n          aws eks update-kubeconfig --name production-cluster\n          helm upgrade --install myapp .\/chart \\\n            --set image.tag=${{ github.event.workflow_run.head_sha }} \\\n            --set commitSha=${{ github.event.workflow_run.head_sha }} \\\n            --set pipelineUrl=\"https:\/\/github.com\/${{ github.repository }}\/actions\/runs\/${{ github.run_id }}\" \\\n            --set approvedBy=\"${{ github.actor }}\" \\\n            --namespace production \\\n            --wait --timeout 300s\n\n      - name: Verify rollout\n        run: |\n          kubectl rollout status deployment\/myapp \\\n            --namespace production --timeout=300s\n\n      - name: Rollback on failure\n        if: failure()\n        run: |\n          echo \"Le d\u00e9ploiement a \u00e9chou\u00e9 \u2014 lancement du rollback\"\n          kubectl rollout undo deployment\/myapp --namespace production\n          echo \"::error::D\u00e9ploiement annul\u00e9 suite \u00e0 un \u00e9chec\"\n<\/code><\/pre>\n<p>Et le pipeline GitLab CI \u00e9quivalent avec des contr\u00f4les similaires :<\/p>\n<pre><code># .gitlab-ci.yml\nstages:\n  - verify\n  - deploy\n  - validate\n\nverify_artifact:\n  stage: verify\n  image: bitnami\/cosign:latest\n  script:\n    - cosign verify\n        --certificate-identity \"https:\/\/gitlab.com\/myorg\/myapp\/\/.gitlab-ci.yml@refs\/heads\/main\"\n        --certificate-oidc-issuer \"https:\/\/gitlab.com\"\n        $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA\n  rules:\n    - if: $CI_COMMIT_BRANCH == \"main\"\n\ndeploy_production:\n  stage: deploy\n  environment:\n    name: production\n    url: https:\/\/app.example.com\n  resource_group: production\n  needs: [verify_artifact]\n  rules:\n    - if: $CI_COMMIT_BRANCH == \"main\"\n      when: manual\n  script:\n    - aws eks update-kubeconfig --name production-cluster\n    - helm upgrade --install myapp .\/chart\n        --set image.tag=$CI_COMMIT_SHA\n        --set commitSha=$CI_COMMIT_SHA\n        --set pipelineUrl=$CI_PIPELINE_URL\n        --set approvedBy=$GITLAB_USER_LOGIN\n        --namespace production\n        --wait --timeout 300s\n\nvalidate_deployment:\n  stage: validate\n  needs: [deploy_production]\n  script:\n    - kubectl rollout status deployment\/myapp --namespace production --timeout=300s\n  after_script:\n    - |\n      if [ \"$CI_JOB_STATUS\" == \"failed\" ]; then\n        echo \"Rollback du d\u00e9ploiement\"\n        kubectl rollout undo deployment\/myapp --namespace production\n      fi\n  rules:\n    - if: $CI_COMMIT_BRANCH == \"main\"\n<\/code><\/pre>\n<h2 class=\"wp-block-heading\">R\u00e9sum\u00e9 et Guides Connexes<\/h2>\n<p>Les workflows de d\u00e9ploiement s\u00e9curis\u00e9s n\u00e9cessitent une d\u00e9fense en profondeur \u00e0 chaque phase : choisir le bon mod\u00e8le de d\u00e9ploiement, appliquer des portes de validation et des approbations, v\u00e9rifier les artefacts \u00e0 la fronti\u00e8re du cluster, d\u00e9ployer les changements de mani\u00e8re progressive, maintenir des chemins de rollback propres, s\u00e9parer les identit\u00e9s de build et de d\u00e9ploiement, respecter les fen\u00eatres de changement et tout journaliser. Aucun contr\u00f4le unique n&rsquo;est suffisant \u00e0 lui seul. La combinaison de la v\u00e9rification au niveau du pipeline, de l&rsquo;application par les contr\u00f4leurs d&rsquo;admission, des d\u00e9ploiements progressifs et de la journalisation d&rsquo;audit compl\u00e8te cr\u00e9e un processus de d\u00e9ploiement \u00e0 la fois rapide et s\u00e9curis\u00e9.<\/p>\n<p>Continuez \u00e0 d\u00e9velopper vos connaissances en CI\/CD s\u00e9curis\u00e9 avec ces guides connexes :<\/p>\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/secure-pipelines.com\/fr\/ci-cd-security\/separation-of-duties-least-privilege-ci-cd-pipelines\/\">S\u00e9paration des Responsabilit\u00e9s et Moindre Privil\u00e8ge dans les Pipelines CI\/CD<\/a> \u2014 Plong\u00e9e approfondie dans la s\u00e9paration des identit\u00e9s, les identifiants \u00e0 port\u00e9e limit\u00e9e et le principe du moindre privil\u00e8ge \u00e0 travers votre pipeline.<\/li>\n<li><a href=\"https:\/\/secure-pipelines.com\/fr\/non-categorise\/defensive-patterns-mitigations-ci-cd-pipeline-attacks\/\">Mod\u00e8les D\u00e9fensifs et Att\u00e9nuations pour les Attaques de Pipelines CI\/CD<\/a> \u2014 Contre-mesures pratiques pour les vecteurs d&rsquo;attaque les plus courants ciblant les syst\u00e8mes CI\/CD.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Votre pipeline CI\/CD peut disposer de contr\u00f4les de s\u00e9curit\u00e9 herm\u00e9tiques \u2014 commits sign\u00e9s, d\u00e9pendances \u00e9pingl\u00e9es, analyses SAST, signature d&rsquo;images de conteneurs \u2014 mais tout cela ne sert \u00e0 rien si le processus de d\u00e9ploiement lui-m\u00eame est faible. Le d\u00e9ploiement est le point de jonction critique o\u00f9 la s\u00e9curit\u00e9 du pipeline rencontre la s\u00e9curit\u00e9 de la &#8230; <a title=\"Workflows de D\u00e9ploiement S\u00e9curis\u00e9s : Du Pipeline CI\/CD \u00e0 la Production\" class=\"read-more\" href=\"https:\/\/secure-pipelines.com\/fr\/ci-cd-security\/secure-deployment-workflows-ci-cd-pipeline-production\/\" aria-label=\"En savoir plus sur Workflows de D\u00e9ploiement S\u00e9curis\u00e9s : Du Pipeline CI\/CD \u00e0 la Production\">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-501","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\/501","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=501"}],"version-history":[{"count":2,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/posts\/501\/revisions"}],"predecessor-version":[{"id":573,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/posts\/501\/revisions\/573"}],"wp:attachment":[{"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/media?parent=501"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/categories?post=501"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/tags?post=501"},{"taxonomy":"post_folder","embeddable":true,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/post_folder?post=501"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}