{"id":480,"date":"2026-02-26T20:26:01","date_gmt":"2026-02-26T19:26:01","guid":{"rendered":"https:\/\/secure-pipelines.com\/?p=480"},"modified":"2026-03-24T12:54:46","modified_gmt":"2026-03-24T11:54:46","slug":"short-lived-credentials-workload-identity-federation-ci-cd","status":"publish","type":"post","link":"https:\/\/secure-pipelines.com\/fr\/ci-cd-security\/short-lived-credentials-workload-identity-federation-ci-cd\/","title":{"rendered":"Credentials \u00e0 Courte Dur\u00e9e de Vie et Workload Identity Federation dans les Pipelines CI\/CD"},"content":{"rendered":"<h2>Introduction<\/h2>\n<p>Si vous auditez les coffres-forts de secrets de la plupart des plateformes CI\/CD aujourd&rsquo;hui, vous trouverez un cimeti\u00e8re de credentials \u00e0 longue dur\u00e9e de vie : des cl\u00e9s d&rsquo;acc\u00e8s AWS cr\u00e9\u00e9es il y a des ann\u00e9es, des cl\u00e9s JSON de comptes de service GCP partag\u00e9es entre des dizaines de pipelines, des GitHub Personal Access Tokens avec des port\u00e9es larges, et des mots de passe de bases de donn\u00e9es qui n&rsquo;ont jamais \u00e9t\u00e9 renouvel\u00e9s. Ces secrets statiques constituent le vecteur d&rsquo;attaque le plus courant dans les compromissions de pipelines CI\/CD.<\/p>\n<p>La raison est simple. Un credential \u00e0 longue dur\u00e9e de vie est une cl\u00e9 passe-partout. Une fois qu&rsquo;un attaquant l&rsquo;obtient \u2014 via un log fuit\u00e9, une d\u00e9pendance compromise, un coffre-fort de secrets mal configur\u00e9, ou une attaque supply chain sur la plateforme CI elle-m\u00eame \u2014 il dispose d&rsquo;un acc\u00e8s persistant, souvent sur-privil\u00e9gi\u00e9, \u00e0 l&rsquo;infrastructure de production. Il n&rsquo;y a pas de compte \u00e0 rebours d&rsquo;expiration. Il n&rsquo;y a pas de r\u00e9vocation automatique. L&rsquo;attaquant peut utiliser ce credential depuis n&rsquo;importe quelle IP, n&rsquo;importe quel contexte, aussi longtemps qu&rsquo;il faut \u00e0 l&rsquo;\u00e9quipe de d\u00e9fense pour s&rsquo;en apercevoir.<\/p>\n<p>La workload identity federation change enti\u00e8rement la donne. Au lieu d&rsquo;injecter des secrets statiques dans les ex\u00e9cutions de pipelines, la plateforme CI elle-m\u00eame devient un fournisseur d&rsquo;identit\u00e9. Chaque ex\u00e9cution de pipeline re\u00e7oit un token \u00e0 courte dur\u00e9e de vie, sign\u00e9 cryptographiquement, qui prouve <em>ce qui<\/em> s&rsquo;ex\u00e9cute (quel d\u00e9p\u00f4t, quelle branche, quel workflow, quel environnement). Les fournisseurs cloud valident ce token et \u00e9mettent des credentials temporaires limit\u00e9s exactement aux permissions n\u00e9cessaires \u2014 des credentials qui expirent en minutes, pas en mois.<\/p>\n<p>Ce guide parcourt le probl\u00e8me en d\u00e9tail, explique comment fonctionne la workload identity federation au niveau protocolaire, fournit des exemples complets et fonctionnels pour GitHub Actions et GitLab CI avec AWS, GCP et Azure, couvre les patterns avanc\u00e9s, et inclut un guide de migration pratique pour les \u00e9quipes pr\u00eates \u00e0 \u00e9liminer leurs secrets \u00e0 longue dur\u00e9e de vie.<\/p>\n<h2>Le probl\u00e8me des credentials \u00e0 longue dur\u00e9e de vie<\/h2>\n<p>Avant de plonger dans la solution, il est utile de comprendre exactement pourquoi les credentials \u00e0 longue dur\u00e9e de vie sont si dangereux dans les contextes CI\/CD sp\u00e9cifiquement \u2014 et pas seulement en g\u00e9n\u00e9ral.<\/p>\n<h3>Pas d&rsquo;expiration ni de rotation automatique<\/h3>\n<p>Une cl\u00e9 d&rsquo;acc\u00e8s AWS IAM, une fois cr\u00e9\u00e9e, est valide ind\u00e9finiment sauf r\u00e9vocation explicite. Une cl\u00e9 JSON de compte de service GCP n&rsquo;a pas de date d&rsquo;expiration. Un GitHub PAT peut \u00eatre configur\u00e9 pour ne jamais expirer. En pratique, la plupart des \u00e9quipes cr\u00e9ent ces credentials une fois lors de la configuration initiale et n&rsquo;y touchent plus jamais. L&rsquo;\u00e2ge m\u00e9dian d&rsquo;un secret CI\/CD dans la plupart des organisations se mesure en ann\u00e9es.<\/p>\n<p>Cela signifie que m\u00eame si un credential a \u00e9t\u00e9 fuit\u00e9 il y a six mois, il est toujours valide aujourd&rsquo;hui. Les attaquants le savent et scannent r\u00e9guli\u00e8rement les d\u00e9p\u00f4ts publics, les images Docker et les logs CI \u00e0 la recherche de credentials qui ont pu \u00eatre expos\u00e9s \u00e0 un moment donn\u00e9 de l&rsquo;histoire.<\/p>\n<h3>Rayon d&rsquo;explosion \u00e9tendu<\/h3>\n<p>Les credentials CI\/CD tendent \u00e0 \u00eatre sur-privil\u00e9gi\u00e9s car ils doivent effectuer des t\u00e2ches diverses : construire des conteneurs, pousser vers des registres, d\u00e9ployer de l&rsquo;infrastructure, ex\u00e9cuter des migrations de bases de donn\u00e9es, invalider des caches. Plut\u00f4t que de cr\u00e9er des credentials \u00e0 port\u00e9e restreinte pour chaque t\u00e2che, les \u00e9quipes cr\u00e9ent g\u00e9n\u00e9ralement un credential puissant et le r\u00e9utilisent partout. Une seule cl\u00e9 fuit\u00e9e peut donner acc\u00e8s simultan\u00e9ment aux bases de donn\u00e9es de production, \u00e0 l&rsquo;infrastructure cloud et aux pipelines de d\u00e9ploiement.<\/p>\n<h3>Difficile \u00e0 auditer<\/h3>\n<p>Quand la m\u00eame cl\u00e9 de compte de service est utilis\u00e9e dans 50 d\u00e9p\u00f4ts, 200 pipelines et trois environnements, il devient quasi impossible de r\u00e9pondre aux questions de s\u00e9curit\u00e9 de base :<\/p>\n<ul>\n<li>Quel pipeline a effectu\u00e9 cet appel API vers la production \u00e0 3h du matin ?<\/li>\n<li>Ce credential a-t-il \u00e9t\u00e9 utilis\u00e9 depuis un runner CI autoris\u00e9 ou depuis la machine d&rsquo;un attaquant ?<\/li>\n<li>Quels d\u00e9p\u00f4ts d\u00e9pendent encore de cette cl\u00e9 si nous devons la renouveler ?<\/li>\n<\/ul>\n<p>Les credentials \u00e0 longue dur\u00e9e de vie ne fournissent aucune information contextuelle sur <em>qui<\/em> ou <em>quoi<\/em> les utilise. Chaque utilisation appara\u00eet de mani\u00e8re identique dans les logs d&rsquo;audit.<\/p>\n<h3>Stock\u00e9s dans les coffres-forts de secrets des plateformes CI<\/h3>\n<p>Les plateformes CI comme GitHub Actions, GitLab CI et Jenkins stockent les secrets dans leurs propres coffres-forts. Ce sont des cibles de grande valeur. Une seule compromission du coffre-fort de secrets de la plateforme CI expose tous les credentials de tous les projets. La compromission de CircleCI en janvier 2023 en est un exemple type : les attaquants ont compromis les syst\u00e8mes internes de CircleCI et exfiltr\u00e9 les secrets des clients, for\u00e7ant chaque client CircleCI \u00e0 renouveler chaque secret stock\u00e9 dans la plateforme.<\/p>\n<h3>Compromissions r\u00e9elles<\/h3>\n<p>Le sch\u00e9ma se r\u00e9p\u00e8te dans toute l&rsquo;industrie :<\/p>\n<ul>\n<li><strong>Codecov (2021) :<\/strong> Des attaquants ont modifi\u00e9 le Bash Uploader de Codecov pour exfiltrer les variables d&rsquo;environnement \u2014 y compris les secrets CI\/CD \u2014 des pipelines de milliers de clients. Les credentials \u00e0 longue dur\u00e9e de vie stock\u00e9s comme variables d&rsquo;environnement ont \u00e9t\u00e9 envoy\u00e9s vers des serveurs contr\u00f4l\u00e9s par les attaquants.<\/li>\n<li><strong>CircleCI (2023) :<\/strong> Un ordinateur portable d&#8217;employ\u00e9 compromis a conduit \u00e0 l&rsquo;exfiltration des secrets clients depuis le stockage de secrets de CircleCI. Chaque client a \u00e9t\u00e9 invit\u00e9 \u00e0 renouveler imm\u00e9diatement tous ses secrets.<\/li>\n<li><strong>Travis CI (2021) :<\/strong> Une vuln\u00e9rabilit\u00e9 a expos\u00e9 les secrets des builds de d\u00e9p\u00f4ts publics, y compris des cl\u00e9s AWS, des tokens GitHub et des credentials Docker Hub.<\/li>\n<li><strong>Uber (2022) :<\/strong> Un attaquant a acc\u00e9d\u00e9 aux syst\u00e8mes internes via un pipeline CI\/CD compromis, en exploitant des credentials cod\u00e9s en dur trouv\u00e9s dans des scripts PowerShell.<\/li>\n<\/ul>\n<p>Dans chaque cas, la cause racine \u00e9tait la m\u00eame : des credentials \u00e0 longue dur\u00e9e de vie stock\u00e9s dans les environnements CI fournissaient un acc\u00e8s persistant et sur-privil\u00e9gi\u00e9 que les attaquants pouvaient exploiter longtemps apr\u00e8s la compromission initiale.<\/p>\n<h2>Comment fonctionne la Workload Identity Federation<\/h2>\n<p>La workload identity federation remplace les credentials statiques par un flux d&rsquo;authentification dynamique, bas\u00e9 sur des tokens, construit sur OpenID Connect (OIDC). Voici comment cela fonctionne au niveau protocolaire.<\/p>\n<h3>Le flux OIDC<\/h3>\n<p>Le flux d&rsquo;authentification implique trois parties : la plateforme CI (fournisseur d&rsquo;identit\u00e9), le fournisseur cloud (partie de confiance) et l&rsquo;ex\u00e9cution du pipeline (workload).<\/p>\n<ol>\n<li><strong>\u00c9mission du token :<\/strong> Lorsqu&rsquo;un job de pipeline d\u00e9marre, la plateforme CI g\u00e9n\u00e8re un JWT (JSON Web Token) sign\u00e9 pour cette ex\u00e9cution sp\u00e9cifique. Ce token contient des claims sur le workload : quel d\u00e9p\u00f4t l&rsquo;a d\u00e9clench\u00e9, quelle branche, quel workflow, quel acteur et l&rsquo;environnement.<\/li>\n<li><strong>\u00c9change du token :<\/strong> Le pipeline pr\u00e9sente ce JWT au Security Token Service (STS) du fournisseur cloud et demande des credentials temporaires.<\/li>\n<li><strong>Validation :<\/strong> Le fournisseur cloud r\u00e9cup\u00e8re le document de d\u00e9couverte OIDC et les cl\u00e9s de signature de la plateforme CI. Il valide la signature du JWT, v\u00e9rifie que le token n&rsquo;a pas expir\u00e9 et confirme que les claims correspondent \u00e0 la politique de confiance configur\u00e9e.<\/li>\n<li><strong>\u00c9mission des credentials :<\/strong> Si la validation r\u00e9ussit, le fournisseur cloud \u00e9met des credentials \u00e0 courte dur\u00e9e de vie (g\u00e9n\u00e9ralement valides pour 1 heure ou moins) limit\u00e9s au r\u00f4le IAM ou au compte de service configur\u00e9 dans la politique de confiance.<\/li>\n<\/ol>\n<h3>La relation de confiance<\/h3>\n<p>Le fondement de la workload identity federation est une relation de confiance entre le syst\u00e8me IAM du fournisseur cloud et le fournisseur OIDC de la plateforme CI. Elle est configur\u00e9e une seule fois :<\/p>\n<ul>\n<li><strong>AWS :<\/strong> Une ressource IAM OIDC Identity Provider qui fait confiance \u00e0 <code>token.actions.githubusercontent.com<\/code> (pour GitHub Actions) ou <code>gitlab.com<\/code> (pour GitLab).<\/li>\n<li><strong>GCP :<\/strong> Un Workload Identity Pool et un Provider configur\u00e9s pour faire confiance \u00e0 l&rsquo;\u00e9metteur OIDC de la plateforme CI.<\/li>\n<li><strong>Azure :<\/strong> Un Federated Identity Credential sur un App Registration ou une Managed Identity.<\/li>\n<\/ul>\n<h3>Scoping bas\u00e9 sur les claims<\/h3>\n<p>La v\u00e9ritable puissance s\u00e9curitaire de la f\u00e9d\u00e9ration OIDC provient du scoping bas\u00e9 sur les claims. Le JWT \u00e9mis par la plateforme CI contient des claims contextuels riches. Vous configurez le fournisseur cloud pour n&rsquo;accepter que les tokens dont les claims correspondent \u00e0 des conditions sp\u00e9cifiques :<\/p>\n<ul>\n<li><strong>D\u00e9p\u00f4t :<\/strong> N&rsquo;accepter que les tokens de <code>my-org\/my-repo<\/code><\/li>\n<li><strong>Branche :<\/strong> N&rsquo;accepter que les tokens de la branche <code>main<\/code><\/li>\n<li><strong>Environnement :<\/strong> N&rsquo;accepter que les tokens de l&rsquo;environnement <code>production<\/code><\/li>\n<li><strong>Workflow :<\/strong> N&rsquo;accepter que les tokens d&rsquo;un fichier workflow sp\u00e9cifique<\/li>\n<\/ul>\n<p>Cela signifie que m\u00eame si un attaquant compromet un d\u00e9p\u00f4t diff\u00e9rent dans la m\u00eame organisation GitHub, il ne peut pas obtenir de credentials limit\u00e9s au r\u00f4le de d\u00e9ploiement en production \u2014 les claims ne correspondront pas.<\/p>\n<h3>Le flux visualis\u00e9<\/h3>\n<pre><code>\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510     1. Request JWT      \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502  CI Runner   \u2502 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25b6 \u2502  CI OIDC Provider \u2502\n\u2502  (Pipeline)  \u2502 \u25c0\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 \u2502  (GitHub\/GitLab)  \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518     2. Signed JWT        \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n      \u2502                                          \u2502\n      \u2502  3. Present JWT +                        \u2502\n      \u2502     Request credentials                  \u2502\n      \u25bc                                          \u2502\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510     4. Validate JWT      \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502  Cloud IAM  \u2502 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25b6  \u2502  OIDC Discovery   \u2502\n\u2502  (STS)      \u2502     (fetch public keys)  \u2502  + JWKS Endpoint  \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518                          \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n      \u2502\n      \u2502  5. Issue short-lived\n      \u2502     credentials (1hr)\n      \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502  Cloud APIs \u2502\n\u2502  (S3, GCS,  \u2502\n\u2502   etc.)     \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n<\/code><\/pre>\n<h2>GitHub Actions : F\u00e9d\u00e9ration OIDC<\/h2>\n<p>GitHub Actions dispose d&rsquo;un support OIDC natif. Chaque ex\u00e9cution de workflow peut demander un JWT sign\u00e9 au fournisseur OIDC de GitHub \u00e0 l&rsquo;adresse <code>token.actions.githubusercontent.com<\/code>. Voici comment configurer la f\u00e9d\u00e9ration avec chaque fournisseur cloud majeur.<\/p>\n<h3>AWS : IAM OIDC Provider + R\u00f4le IAM<\/h3>\n<p>Commencez par cr\u00e9er le fournisseur OIDC et le r\u00f4le IAM dans AWS. Voici la configuration Terraform :<\/p>\n<pre><code># Terraform: AWS OIDC Provider for GitHub Actions\nresource \"aws_iam_openid_connect_provider\" \"github_actions\" {\n  url             = \"https:\/\/token.actions.githubusercontent.com\"\n  client_id_list  = [\"sts.amazonaws.com\"]\n  thumbprint_list = [\"6938fd4d98bab03faadb97b34396831e3780aea1\"]\n}\n\n# IAM Role that GitHub Actions can assume\nresource \"aws_iam_role\" \"github_actions_deploy\" {\n  name = \"github-actions-deploy\"\n\n  assume_role_policy = jsonencode({\n    Version = \"2012-10-17\"\n    Statement = [\n      {\n        Effect = \"Allow\"\n        Principal = {\n          Federated = aws_iam_openid_connect_provider.github_actions.arn\n        }\n        Action = \"sts:AssumeRoleWithWebIdentity\"\n        Condition = {\n          StringEquals = {\n            \"token.actions.githubusercontent.com:aud\" = \"sts.amazonaws.com\"\n          }\n          StringLike = {\n            \"token.actions.githubusercontent.com:sub\" = \"repo:my-org\/my-repo:ref:refs\/heads\/main\"\n          }\n        }\n      }\n    ]\n  })\n}\n\n# Attach permissions to the role\nresource \"aws_iam_role_policy_attachment\" \"deploy_policy\" {\n  role       = aws_iam_role.github_actions_deploy.name\n  policy_arn = \"arn:aws:iam::policy\/my-deploy-policy\"\n}\n<\/code><\/pre>\n<p>Ensuite, utilisez le r\u00f4le dans votre workflow GitHub Actions :<\/p>\n<pre><code># .github\/workflows\/deploy.yml\nname: Deploy to AWS\non:\n  push:\n    branches: [main]\n\npermissions:\n  id-token: write   # Required for OIDC\n  contents: read\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@v4\n\n      - name: Configure AWS Credentials\n        uses: aws-actions\/configure-aws-credentials@v4\n        with:\n          role-to-assume: arn:aws:iam::123456789012:role\/github-actions-deploy\n          aws-region: us-east-1\n          role-session-name: github-actions-deploy-${{ github.run_id }}\n\n      - name: Deploy\n        run: |\n          aws s3 sync .\/dist s3:\/\/my-bucket\/\n          aws cloudfront create-invalidation --distribution-id E12345 --paths \"\/*\"\n<\/code><\/pre>\n<h3>GCP : Workload Identity Pool + Provider<\/h3>\n<p>GCP utilise la Workload Identity Federation avec des pools et des providers. Voici la configuration avec la CLI <code>gcloud<\/code> :<\/p>\n<pre><code># Create the Workload Identity Pool\ngcloud iam workload-identity-pools create \"github-actions-pool\" \\\n  --project=\"my-project\" \\\n  --location=\"global\" \\\n  --display-name=\"GitHub Actions Pool\"\n\n# Create the OIDC Provider\ngcloud iam workload-identity-pools providers create-oidc \"github-provider\" \\\n  --project=\"my-project\" \\\n  --location=\"global\" \\\n  --workload-identity-pool=\"github-actions-pool\" \\\n  --display-name=\"GitHub OIDC\" \\\n  --attribute-mapping=\"google.subject=assertion.sub,attribute.repository=assertion.repository,attribute.ref=assertion.ref\" \\\n  --issuer-uri=\"https:\/\/token.actions.githubusercontent.com\" \\\n  --attribute-condition=\"assertion.repository_owner=='my-org'\"\n\n# Grant the pool access to a service account\ngcloud iam service-accounts add-iam-policy-binding \\\n  deploy-sa@my-project.iam.gserviceaccount.com \\\n  --project=\"my-project\" \\\n  --role=\"roles\/iam.workloadIdentityUser\" \\\n  --member=\"principalSet:\/\/iam.googleapis.com\/projects\/PROJECT_NUMBER\/locations\/global\/workloadIdentityPools\/github-actions-pool\/attribute.repository\/my-org\/my-repo\"\n<\/code><\/pre>\n<p>Le workflow GitHub Actions pour GCP :<\/p>\n<pre><code># .github\/workflows\/deploy-gcp.yml\nname: Deploy to GCP\non:\n  push:\n    branches: [main]\n\npermissions:\n  id-token: write\n  contents: read\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@v4\n\n      - name: Authenticate to GCP\n        uses: google-github-actions\/auth@v2\n        with:\n          workload_identity_provider: \"projects\/PROJECT_NUMBER\/locations\/global\/workloadIdentityPools\/github-actions-pool\/providers\/github-provider\"\n          service_account: \"deploy-sa@my-project.iam.gserviceaccount.com\"\n\n      - name: Set up Cloud SDK\n        uses: google-github-actions\/setup-gcloud@v2\n\n      - name: Deploy to Cloud Run\n        run: |\n          gcloud run deploy my-service \\\n            --image gcr.io\/my-project\/my-app:${{ github.sha }} \\\n            --region us-central1\n<\/code><\/pre>\n<h3>Azure : Federated Credentials sur App Registration<\/h3>\n<p>Azure prend en charge les federated identity credentials sur les App Registrations et les Managed Identities. Cr\u00e9ez la f\u00e9d\u00e9ration avec Azure CLI :<\/p>\n<pre><code># Create an App Registration\naz ad app create --display-name \"github-actions-deploy\"\n\n# Create a federated credential\naz ad app federated-credential create \\\n  --id &lt;APP_OBJECT_ID&gt; \\\n  --parameters '{\n    \"name\": \"github-actions-main\",\n    \"issuer\": \"https:\/\/token.actions.githubusercontent.com\",\n    \"subject\": \"repo:my-org\/my-repo:ref:refs\/heads\/main\",\n    \"audiences\": [\"api:\/\/AzureADTokenExchange\"],\n    \"description\": \"GitHub Actions deploy from main branch\"\n  }'\n\n# Create a service principal and assign roles\naz ad sp create --id &lt;APP_CLIENT_ID&gt;\naz role assignment create \\\n  --assignee &lt;APP_CLIENT_ID&gt; \\\n  --role \"Contributor\" \\\n  --scope \/subscriptions\/&lt;SUBSCRIPTION_ID&gt;\/resourceGroups\/my-rg\n<\/code><\/pre>\n<p>Le workflow GitHub Actions pour Azure :<\/p>\n<pre><code># .github\/workflows\/deploy-azure.yml\nname: Deploy to Azure\non:\n  push:\n    branches: [main]\n\npermissions:\n  id-token: write\n  contents: read\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@v4\n\n      - name: Azure Login\n        uses: azure\/login@v2\n        with:\n          client-id: ${{ secrets.AZURE_CLIENT_ID }}\n          tenant-id: ${{ secrets.AZURE_TENANT_ID }}\n          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}\n\n      - name: Deploy to Azure Web App\n        uses: azure\/webapps-deploy@v3\n        with:\n          app-name: my-web-app\n          package: .\/dist\n<\/code><\/pre>\n<p><strong>Remarque :<\/strong> Avec Azure OIDC, vous stockez toujours le client ID, le tenant ID et le subscription ID comme secrets \u2014 mais ce sont des identifiants non sensibles, pas des credentials d&rsquo;authentification. Aucun client secret n&rsquo;est n\u00e9cessaire.<\/p>\n<h3>Conditions sur les claims : restreindre l&rsquo;acc\u00e8s<\/h3>\n<p>Le claim subject dans les tokens OIDC de GitHub Actions suit un format pr\u00e9visible. Utilisez ces patterns dans vos politiques de confiance :<\/p>\n<ul>\n<li><code>repo:my-org\/my-repo:ref:refs\/heads\/main<\/code> \u2014 Uniquement la branche main<\/li>\n<li><code>repo:my-org\/my-repo:environment:production<\/code> \u2014 Uniquement l&rsquo;environnement de production<\/li>\n<li><code>repo:my-org\/my-repo:pull_request<\/code> \u2014 Uniquement les workflows de pull request<\/li>\n<li><code>repo:my-org\/my-repo:ref:refs\/tags\/v*<\/code> \u2014 Uniquement les tags de version (utilisez <code>StringLike<\/code> dans AWS)<\/li>\n<\/ul>\n<p>Utilisez toujours la condition de claim la plus restrictive possible. \u00c9vitez les wildcards comme <code>repo:my-org\/*<\/code> sauf si vous avez v\u00e9ritablement besoin d&rsquo;un acc\u00e8s \u00e0 l&rsquo;\u00e9chelle de l&rsquo;organisation.<\/p>\n<h2>GitLab CI : F\u00e9d\u00e9ration OIDC<\/h2>\n<p>GitLab CI a introduit le support OIDC natif avec le mot-cl\u00e9 <code>id_tokens<\/code>. Le flux est similaire \u00e0 GitHub Actions mais avec quelques diff\u00e9rences dans la structure des claims et la configuration.<\/p>\n<h3>Demander des tokens OIDC dans GitLab CI<\/h3>\n<p>Dans GitLab CI, vous d\u00e9clarez les tokens OIDC dans la configuration de votre job en utilisant le mot-cl\u00e9 <code>id_tokens<\/code> :<\/p>\n<pre><code># .gitlab-ci.yml\ndeploy_to_aws:\n  stage: deploy\n  image: amazon\/aws-cli:latest\n  id_tokens:\n    AWS_OIDC_TOKEN:\n      aud: https:\/\/sts.amazonaws.com\n  script:\n    - |\n      CREDENTIALS=$(aws sts assume-role-with-web-identity \\\n        --role-arn arn:aws:iam::123456789012:role\/gitlab-deploy \\\n        --role-session-name \"gitlab-ci-${CI_PIPELINE_ID}\" \\\n        --web-identity-token \"${AWS_OIDC_TOKEN}\" \\\n        --duration-seconds 3600 \\\n        --query 'Credentials')\n      export AWS_ACCESS_KEY_ID=$(echo $CREDENTIALS | jq -r '.AccessKeyId')\n      export AWS_SECRET_ACCESS_KEY=$(echo $CREDENTIALS | jq -r '.SecretAccessKey')\n      export AWS_SESSION_TOKEN=$(echo $CREDENTIALS | jq -r '.SessionToken')\n      aws s3 sync .\/dist s3:\/\/my-bucket\/\n  rules:\n    - if: $CI_COMMIT_BRANCH == \"main\"\n<\/code><\/pre>\n<h3>Configuration AWS pour GitLab<\/h3>\n<p>Le fournisseur IAM OIDC pour GitLab utilise une URL d&rsquo;\u00e9metteur diff\u00e9rente :<\/p>\n<pre><code># Terraform: AWS OIDC Provider for GitLab\nresource \"aws_iam_openid_connect_provider\" \"gitlab\" {\n  url             = \"https:\/\/gitlab.com\"\n  client_id_list  = [\"https:\/\/sts.amazonaws.com\"]\n  thumbprint_list = [\"b3dd7606d2b5a8b4a13771dbecc9ee1cecafa38a\"]\n}\n\nresource \"aws_iam_role\" \"gitlab_deploy\" {\n  name = \"gitlab-deploy\"\n\n  assume_role_policy = jsonencode({\n    Version = \"2012-10-17\"\n    Statement = [\n      {\n        Effect = \"Allow\"\n        Principal = {\n          Federated = aws_iam_openid_connect_provider.gitlab.arn\n        }\n        Action = \"sts:AssumeRoleWithWebIdentity\"\n        Condition = {\n          StringEquals = {\n            \"gitlab.com:aud\" = \"https:\/\/sts.amazonaws.com\"\n          }\n          StringLike = {\n            \"gitlab.com:sub\" = \"project_path:my-group\/my-project:ref_type:branch:ref:main\"\n          }\n        }\n      }\n    ]\n  })\n}\n<\/code><\/pre>\n<h3>GCP Workload Identity Federation pour GitLab<\/h3>\n<pre><code># Create the OIDC Provider for GitLab\ngcloud iam workload-identity-pools providers create-oidc \"gitlab-provider\" \\\n  --project=\"my-project\" \\\n  --location=\"global\" \\\n  --workload-identity-pool=\"cicd-pool\" \\\n  --display-name=\"GitLab OIDC\" \\\n  --attribute-mapping=\"google.subject=assertion.sub,attribute.project_path=assertion.project_path,attribute.ref=assertion.ref\" \\\n  --issuer-uri=\"https:\/\/gitlab.com\" \\\n  --attribute-condition=\"assertion.namespace_path=='my-group'\"\n<\/code><\/pre>\n<p>Le job GitLab CI correspondant pour GCP :<\/p>\n<pre><code># .gitlab-ci.yml\ndeploy_to_gcp:\n  stage: deploy\n  image: google\/cloud-sdk:slim\n  id_tokens:\n    GCP_OIDC_TOKEN:\n      aud: https:\/\/iam.googleapis.com\/projects\/PROJECT_NUMBER\/locations\/global\/workloadIdentityPools\/cicd-pool\/providers\/gitlab-provider\n  script:\n    - |\n      echo \"${GCP_OIDC_TOKEN}\" &gt; \/tmp\/oidc_token.txt\n      gcloud iam workload-identity-pools create-cred-config \\\n        \"projects\/PROJECT_NUMBER\/locations\/global\/workloadIdentityPools\/cicd-pool\/providers\/gitlab-provider\" \\\n        --service-account=\"deploy-sa@my-project.iam.gserviceaccount.com\" \\\n        --output-file=\/tmp\/cred_config.json \\\n        --credential-source-file=\/tmp\/oidc_token.txt\n      gcloud auth login --cred-file=\/tmp\/cred_config.json\n      gcloud run deploy my-service --image gcr.io\/my-project\/my-app:${CI_COMMIT_SHA} --region us-central1\n  rules:\n    - if: $CI_COMMIT_BRANCH == \"main\"\n<\/code><\/pre>\n<h3>Diff\u00e9rences de filtrage des claims par rapport \u00e0 GitHub Actions<\/h3>\n<p>Les tokens OIDC de GitLab utilisent un format de claim subject diff\u00e9rent de celui de GitHub Actions :<\/p>\n<ul>\n<li><strong>GitLab :<\/strong> <code>project_path:my-group\/my-project:ref_type:branch:ref:main<\/code><\/li>\n<li><strong>GitHub :<\/strong> <code>repo:my-org\/my-repo:ref:refs\/heads\/main<\/code><\/li>\n<\/ul>\n<p>GitLab inclut \u00e9galement des claims suppl\u00e9mentaires utilisables pour le filtrage :<\/p>\n<ul>\n<li><code>namespace_id<\/code> et <code>namespace_path<\/code> \u2014 Le groupe ou l&rsquo;espace de noms utilisateur<\/li>\n<li><code>project_id<\/code> et <code>project_path<\/code> \u2014 Le projet sp\u00e9cifique<\/li>\n<li><code>pipeline_source<\/code> \u2014 Comment le pipeline a \u00e9t\u00e9 d\u00e9clench\u00e9 (push, merge_request, schedule, etc.)<\/li>\n<li><code>environment<\/code> \u2014 L&rsquo;environnement de d\u00e9ploiement, s&rsquo;il est d\u00e9fini<\/li>\n<li><code>ref_protected<\/code> \u2014 Si la ref est une branche prot\u00e9g\u00e9e<\/li>\n<\/ul>\n<p>Le claim <code>ref_protected<\/code> est particuli\u00e8rement utile : vous pouvez configurer des politiques de confiance qui n&rsquo;acceptent que les tokens provenant de branches prot\u00e9g\u00e9es, ajoutant une couche de s\u00e9curit\u00e9 suppl\u00e9mentaire.<\/p>\n<h2>Patterns avanc\u00e9s<\/h2>\n<h3>Cha\u00eenage OIDC : CI vers Vault vers Cloud<\/h3>\n<p>HashiCorp Vault peut agir comme un broker d&rsquo;identit\u00e9 interm\u00e9diaire entre votre plateforme CI et les fournisseurs cloud. C&rsquo;est utile lorsque vous avez besoin d&rsquo;une gestion centralis\u00e9e des secrets, de credentials dynamiques pour les bases de donn\u00e9es ou d&rsquo;autres services non-cloud, ou d&rsquo;une piste d&rsquo;audit unifi\u00e9e entre toutes les plateformes CI.<\/p>\n<pre><code># Configure Vault JWT auth backend for GitHub Actions\nvault auth enable jwt\n\nvault write auth\/jwt\/config \\\n  oidc_discovery_url=\"https:\/\/token.actions.githubusercontent.com\" \\\n  bound_issuer=\"https:\/\/token.actions.githubusercontent.com\"\n\n# Create a role that maps GitHub Actions claims to Vault policies\nvault write auth\/jwt\/role\/deploy \\\n  role_type=\"jwt\" \\\n  bound_audiences=\"https:\/\/vault.mycompany.com\" \\\n  bound_claims_type=\"glob\" \\\n  bound_claims='{\"repository\":\"my-org\/my-repo\",\"ref\":\"refs\/heads\/main\"}' \\\n  user_claim=\"repository\" \\\n  policies=\"deploy-policy\" \\\n  ttl=\"15m\"\n<\/code><\/pre>\n<p>Le workflow GitHub Actions utilisant Vault comme broker :<\/p>\n<pre><code># .github\/workflows\/deploy-via-vault.yml\nname: Deploy via Vault\non:\n  push:\n    branches: [main]\n\npermissions:\n  id-token: write\n  contents: read\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@v4\n\n      - name: Import Secrets from Vault\n        uses: hashicorp\/vault-action@v3\n        with:\n          url: https:\/\/vault.mycompany.com\n          method: jwt\n          role: deploy\n          jwtGithubAudience: https:\/\/vault.mycompany.com\n          secrets: |\n            aws\/creds\/deploy access_key | AWS_ACCESS_KEY_ID ;\n            aws\/creds\/deploy secret_key | AWS_SECRET_ACCESS_KEY ;\n            aws\/creds\/deploy security_token | AWS_SESSION_TOKEN\n\n      - name: Deploy\n        run: aws s3 sync .\/dist s3:\/\/my-bucket\/\n<\/code><\/pre>\n<h3>Identit\u00e9s par environnement<\/h3>\n<p>Cr\u00e9ez des r\u00f4les IAM s\u00e9par\u00e9s pour chaque environnement, chacun avec des politiques de confiance progressivement plus strictes :<\/p>\n<pre><code># Terraform: Per-environment roles\nlocals {\n  environments = {\n    dev = {\n      branch    = \"*\"\n      condition = \"StringLike\"\n    }\n    staging = {\n      branch    = \"refs\/heads\/main\"\n      condition = \"StringEquals\"\n    }\n    production = {\n      branch    = \"refs\/heads\/main\"\n      condition = \"StringEquals\"\n    }\n  }\n}\n\nresource \"aws_iam_role\" \"deploy\" {\n  for_each = local.environments\n  name     = \"github-actions-deploy-${each.key}\"\n\n  assume_role_policy = jsonencode({\n    Version = \"2012-10-17\"\n    Statement = [\n      {\n        Effect = \"Allow\"\n        Principal = {\n          Federated = aws_iam_openid_connect_provider.github_actions.arn\n        }\n        Action = \"sts:AssumeRoleWithWebIdentity\"\n        Condition = {\n          StringEquals = {\n            \"token.actions.githubusercontent.com:aud\" = \"sts.amazonaws.com\"\n          }\n          (each.value.condition) = {\n            \"token.actions.githubusercontent.com:sub\" = \"repo:my-org\/my-repo:environment:${each.key}\"\n          }\n        }\n      }\n    ]\n  })\n}\n<\/code><\/pre>\n<p>Dans GitHub Actions, utilisez les environnements pour limiter automatiquement la port\u00e9e du token OIDC :<\/p>\n<pre><code>jobs:\n  deploy-prod:\n    runs-on: ubuntu-latest\n    environment: production  # This changes the OIDC subject claim\n    steps:\n      - uses: aws-actions\/configure-aws-credentials@v4\n        with:\n          role-to-assume: arn:aws:iam::123456789012:role\/github-actions-deploy-production\n          aws-region: us-east-1\n<\/code><\/pre>\n<h3>Kubernetes Workload Identity pour les \u00e9tapes de d\u00e9ploiement<\/h3>\n<p>Si votre pipeline CI d\u00e9ploie sur Kubernetes, vous pouvez cha\u00eener les identit\u00e9s : le runner CI s&rsquo;authentifie aupr\u00e8s du cluster via OIDC, et les pods du cluster utilisent Kubernetes workload identity pour acc\u00e9der aux ressources cloud :<\/p>\n<pre><code># GKE Workload Identity: Annotate the Kubernetes service account\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: app-deploy-sa\n  namespace: production\n  annotations:\n    iam.gke.io\/gcp-service-account: app-sa@my-project.iam.gserviceaccount.com\n<\/code><\/pre>\n<h3>Patterns d&rsquo;acc\u00e8s cross-account<\/h3>\n<p>Pour les organisations avec plusieurs comptes AWS, vous pouvez cha\u00eener les assumptions de r\u00f4les. Le runner CI assume un r\u00f4le dans un compte \u00ab CI \u00bb central via OIDC, puis assume des r\u00f4les dans les comptes cibles :<\/p>\n<pre><code># Step 1: Assume the hub role via OIDC\n- uses: aws-actions\/configure-aws-credentials@v4\n  with:\n    role-to-assume: arn:aws:iam::HUB_ACCOUNT:role\/github-actions-hub\n    aws-region: us-east-1\n\n# Step 2: Assume a role in the target account\n- uses: aws-actions\/configure-aws-credentials@v4\n  with:\n    role-to-assume: arn:aws:iam::TARGET_ACCOUNT:role\/deploy-role\n    aws-region: us-east-1\n    role-chaining: true\n<\/code><\/pre>\n<h3>Combiner OIDC avec Terraform<\/h3>\n<p>Les d\u00e9ploiements Terraform b\u00e9n\u00e9ficient \u00e9norm\u00e9ment de l&rsquo;OIDC car ils n\u00e9cessitent g\u00e9n\u00e9ralement des permissions d&rsquo;infrastructure larges. Configurez le provider AWS pour utiliser le r\u00f4le assum\u00e9 via OIDC :<\/p>\n<pre><code># terraform\/providers.tf\nprovider \"aws\" {\n  region = \"us-east-1\"\n\n  # No credentials configured here \u2014 they come from\n  # the environment variables set by the OIDC step\n  default_tags {\n    tags = {\n      ManagedBy   = \"terraform\"\n      Repository  = \"my-org\/my-infra\"\n      Environment = var.environment\n    }\n  }\n}\n\n# terraform\/backend.tf\nterraform {\n  backend \"s3\" {\n    bucket         = \"my-terraform-state\"\n    key            = \"infra\/terraform.tfstate\"\n    region         = \"us-east-1\"\n    # State backend also uses the OIDC credentials\n    # No access_key or secret_key needed\n  }\n}\n<\/code><\/pre>\n<h2>Consid\u00e9rations de s\u00e9curit\u00e9<\/h2>\n<p>La workload identity federation est une am\u00e9lioration massive par rapport aux credentials \u00e0 longue dur\u00e9e de vie, mais elle n&rsquo;est pas infaillible. Voici les risques \u00e0 conna\u00eetre et \u00e0 att\u00e9nuer.<\/p>\n<h3>Politiques de confiance trop larges<\/h3>\n<p>L&rsquo;erreur la plus courante est de configurer des politiques de confiance trop permissives. Exemples de configurations dangereuses :<\/p>\n<ul>\n<li><strong>Faire confiance \u00e0 une organisation enti\u00e8re :<\/strong> <code>repo:my-org\/*<\/code> signifie que n&rsquo;importe quel d\u00e9p\u00f4t de l&rsquo;organisation peut assumer le r\u00f4le. Un d\u00e9p\u00f4t compromis ou malveillant obtient l&rsquo;acc\u00e8s \u00e0 la production.<\/li>\n<li><strong>Faire confiance \u00e0 toutes les branches :<\/strong> <code>repo:my-org\/my-repo:*<\/code> signifie qu&rsquo;une branche de fonctionnalit\u00e9 avec du code non test\u00e9 peut acc\u00e9der aux credentials de production.<\/li>\n<li><strong>Restriction d&rsquo;audience manquante :<\/strong> Sans v\u00e9rification du claim <code>aud<\/code>, des tokens destin\u00e9s \u00e0 un service pourraient \u00eatre rejou\u00e9s contre un autre.<\/li>\n<\/ul>\n<p>Suivez toujours le principe du moindre privil\u00e8ge : restreignez au d\u00e9p\u00f4t, \u00e0 la branche et \u00e0 l&rsquo;environnement sp\u00e9cifiques n\u00e9cessaires.<\/p>\n<h3>Mauvaise configuration de l&rsquo;audience du token<\/h3>\n<p>Le claim audience (<code>aud<\/code>) sp\u00e9cifie le destinataire pr\u00e9vu du token. Si votre politique de confiance ne valide pas l&rsquo;audience, un attaquant qui obtient un token destin\u00e9 \u00e0 un autre service pourrait l&rsquo;utiliser pour assumer votre r\u00f4le IAM. Validez toujours le claim audience dans vos politiques de confiance.<\/p>\n<h3>Compromission du fournisseur OIDC<\/h3>\n<p>Si le fournisseur OIDC de la plateforme CI est compromis (par exemple, un attaquant peut forger des JWT), toutes les relations de confiance construites sur ce fournisseur sont compromises. Les mesures d&rsquo;att\u00e9nuation incluent :<\/p>\n<ul>\n<li>Surveiller les avis de s\u00e9curit\u00e9 de la plateforme CI<\/li>\n<li>Utiliser des restrictions de claims suppl\u00e9mentaires au-del\u00e0 du simple subject<\/li>\n<li>Impl\u00e9menter des restrictions bas\u00e9es sur l&rsquo;IP lorsque c&rsquo;est support\u00e9<\/li>\n<li>D\u00e9finir des dur\u00e9es de session courtes (15 minutes au lieu d&rsquo;1 heure)<\/li>\n<li>Activer CloudTrail, GCP Audit Logs ou Azure Activity Logs pour d\u00e9tecter les acc\u00e8s f\u00e9d\u00e9r\u00e9s anormaux<\/li>\n<\/ul>\n<h3>Surveillance et audit<\/h3>\n<p>L&rsquo;acc\u00e8s f\u00e9d\u00e9r\u00e9 doit \u00eatre surveill\u00e9 comme tout autre m\u00e9canisme d&rsquo;authentification. Configurez des alertes pour :<\/p>\n<ul>\n<li>Les assumptions de r\u00f4les depuis des d\u00e9p\u00f4ts ou branches inattendus<\/li>\n<li>Les patterns d&rsquo;acc\u00e8s inhabituels (par exemple, un r\u00f4le de production assum\u00e9 \u00e0 3h du matin sans d\u00e9ploiement pr\u00e9vu)<\/li>\n<li>Les tentatives \u00e9chou\u00e9es d&rsquo;assumption de r\u00f4le (peuvent indiquer un attaquant qui sonde les politiques de confiance)<\/li>\n<li>Les modifications des configurations de fournisseur OIDC ou des politiques de confiance<\/li>\n<\/ul>\n<pre><code># AWS CloudTrail filter for OIDC role assumptions\n{\n  \"eventName\": \"AssumeRoleWithWebIdentity\",\n  \"requestParameters\": {\n    \"roleArn\": \"arn:aws:iam::123456789012:role\/github-actions-deploy-production\"\n  }\n}\n<\/code><\/pre>\n<h3>Strat\u00e9gies de repli<\/h3>\n<p>La f\u00e9d\u00e9ration OIDC d\u00e9pend de services externes (endpoint OIDC de la plateforme CI, STS cloud). Planifiez les pannes :<\/p>\n<ul>\n<li>Maintenez un jeu de credentials \u00e0 longue dur\u00e9e de vie \u00ab break-glass \u00bb dans un coffre-fort s\u00e9curis\u00e9 (par exemple, AWS Secrets Manager, 1Password), accessible uniquement aux ing\u00e9nieurs seniors<\/li>\n<li>Documentez la proc\u00e9dure break-glass : quand l&rsquo;utiliser, qui peut l&rsquo;autoriser, comment auditer son utilisation<\/li>\n<li>Configurez des alertes lorsque les credentials break-glass sont utilis\u00e9s<\/li>\n<li>Renouvelez les credentials break-glass apr\u00e8s chaque utilisation<\/li>\n<\/ul>\n<h2>Guide de migration : des credentials \u00e0 longue dur\u00e9e de vie aux credentials \u00e0 courte dur\u00e9e de vie<\/h2>\n<p>La migration des credentials \u00e0 longue dur\u00e9e de vie vers la workload identity federation est un changement \u00e0 forte valeur ajout\u00e9e et \u00e0 faible risque lorsqu&rsquo;il est effectu\u00e9 de mani\u00e8re syst\u00e9matique. Voici une approche par phases.<\/p>\n<h3>Phase 1 : Inventaire<\/h3>\n<p>Commencez par cataloguer chaque secret de votre plateforme CI\/CD :<\/p>\n<pre><code># GitHub: List all secrets for a repository\ngh secret list --repo my-org\/my-repo\n\n# GitHub: List organization secrets\ngh secret list --org my-org\n\n# GitLab: List project variables\ncurl --header \"PRIVATE-TOKEN: $GITLAB_TOKEN\" \\\n  \"https:\/\/gitlab.com\/api\/v4\/projects\/$PROJECT_ID\/variables\"\n<\/code><\/pre>\n<p>Pour chaque secret, documentez :<\/p>\n<ul>\n<li>Ce que c&rsquo;est (cl\u00e9 AWS, cl\u00e9 GCP, mot de passe de base de donn\u00e9es, token API)<\/li>\n<li>Ce \u00e0 quoi il acc\u00e8de (quel compte cloud, quel service)<\/li>\n<li>Quels pipelines l&rsquo;utilisent<\/li>\n<li>Quand il a \u00e9t\u00e9 renouvel\u00e9 pour la derni\u00e8re fois<\/li>\n<li>S&rsquo;il peut \u00eatre remplac\u00e9 par la f\u00e9d\u00e9ration OIDC<\/li>\n<\/ul>\n<h3>Phase 2 : Identifier les candidats<\/h3>\n<p>Bons candidats pour le remplacement par OIDC :<\/p>\n<ul>\n<li>Cl\u00e9s d&rsquo;acc\u00e8s AWS IAM utilis\u00e9es en CI\/CD<\/li>\n<li>Cl\u00e9s JSON de comptes de service GCP<\/li>\n<li>Client secrets de service principals Azure<\/li>\n<li>Tout credential utilis\u00e9 pour s&rsquo;authentifier aupr\u00e8s d&rsquo;un fournisseur cloud qui supporte OIDC<\/li>\n<\/ul>\n<p>Non candidats pour OIDC (n\u00e9cessitent des approches diff\u00e9rentes) :<\/p>\n<ul>\n<li>Mots de passe de bases de donn\u00e9es (utilisez les credentials dynamiques de Vault \u00e0 la place)<\/li>\n<li>Cl\u00e9s API de services tiers (utilisez Vault ou un gestionnaire de secrets)<\/li>\n<li>Cl\u00e9s SSH pour les op\u00e9rations Git (utilisez des deploy keys ou des tokens GitHub App)<\/li>\n<li>Mots de passe de registres de conteneurs (utilisez l&rsquo;authentification native du registre cloud via OIDC)<\/li>\n<\/ul>\n<h3>Phase 3 : D\u00e9ploiement progressif<\/h3>\n<ol>\n<li><strong>Commencez par le non-production :<\/strong> Configurez la f\u00e9d\u00e9ration OIDC pour un seul pipeline non-production. Validez son fonctionnement fiable pendant une semaine.<\/li>\n<li><strong>\u00c9tendez aux autres pipelines non-production :<\/strong> Convertissez les pipelines dev et staging restants. D\u00e9veloppez la confiance et la documentation.<\/li>\n<li><strong>Pilote production :<\/strong> Choisissez un pipeline de production avec un bon monitoring. Ex\u00e9cutez OIDC en parall\u00e8le du credential existant pendant une semaine (le pipeline utilise OIDC, mais l&rsquo;ancien credential existe toujours comme solution de repli).<\/li>\n<li><strong>D\u00e9ploiement complet en production :<\/strong> Convertissez les pipelines de production restants. Conservez les anciens credentials uniquement comme break-glass.<\/li>\n<\/ol>\n<h3>Phase 4 : D\u00e9commissionner les anciens credentials<\/h3>\n<p>Une fois que l&rsquo;OIDC fonctionne de mani\u00e8re fiable :<\/p>\n<ol>\n<li><strong>D\u00e9sactivez, ne supprimez pas :<\/strong> D\u00e9sactivez d&rsquo;abord l&rsquo;ancien credential. Attendez deux semaines pour vous assurer que rien ne casse.<\/li>\n<li><strong>Surveillez l&rsquo;utilisation :<\/strong> V\u00e9rifiez CloudTrail, GCP Audit Logs ou l&rsquo;\u00e9quivalent pour toute utilisation de l&rsquo;ancien credential.<\/li>\n<li><strong>Supprimez :<\/strong> Une fois que vous \u00eates s\u00fbr que le credential n&rsquo;est plus utilis\u00e9, supprimez-le.<\/li>\n<li><strong>Supprimez des secrets CI :<\/strong> Supprimez le secret du coffre-fort de secrets de votre plateforme CI.<\/li>\n<\/ol>\n<pre><code># AWS: Deactivate an old access key\naws iam update-access-key \\\n  --user-name ci-deploy \\\n  --access-key-id AKIAIOSFODNN7EXAMPLE \\\n  --status Inactive\n\n# After validation period, delete it\naws iam delete-access-key \\\n  --user-name ci-deploy \\\n  --access-key-id AKIAIOSFODNN7EXAMPLE\n<\/code><\/pre>\n<h3>Validation<\/h3>\n<p>Confirmez que la migration est compl\u00e8te :<\/p>\n<ul>\n<li>Tous les pipelines CI\/CD s&rsquo;authentifient via OIDC (v\u00e9rifiez les logs de workflow)<\/li>\n<li>Aucun credential cloud \u00e0 longue dur\u00e9e de vie ne reste dans les coffres-forts de secrets CI (\u00e0 l&rsquo;exception des credentials break-glass document\u00e9s)<\/li>\n<li>Les utilisateurs IAM ou comptes de service pr\u00e9c\u00e9demment utilis\u00e9s par le CI sont supprim\u00e9s ou n&rsquo;ont plus de cl\u00e9s d&rsquo;acc\u00e8s<\/li>\n<li>La surveillance et les alertes sont en place pour l&rsquo;acc\u00e8s f\u00e9d\u00e9r\u00e9<\/li>\n<li>Les proc\u00e9dures break-glass sont document\u00e9es et test\u00e9es<\/li>\n<\/ul>\n<h2>Conclusion<\/h2>\n<p>La workload identity federation est le changement \u00e0 plus fort impact que la plupart des \u00e9quipes peuvent apporter \u00e0 leur posture de s\u00e9curit\u00e9 CI\/CD. Elle \u00e9limine le vecteur d&rsquo;attaque le plus courant \u2014 les credentials \u00e0 longue dur\u00e9e de vie \u2014 et le remplace par un syst\u00e8me plus s\u00e9curis\u00e9 par d\u00e9faut : \u00e0 courte dur\u00e9e de vie, automatiquement limit\u00e9 en port\u00e9e, auditable et r\u00e9sistant aux mouvements lat\u00e9raux.<\/p>\n<p>Le chemin de migration est simple. Commencez par un pipeline et un fournisseur cloud. Configurez la relation de confiance OIDC, mettez \u00e0 jour le workflow pour utiliser l&rsquo;authentification f\u00e9d\u00e9r\u00e9e, validez que cela fonctionne, puis passez au pipeline suivant. En quelques semaines, vous pouvez \u00e9liminer chaque credential cloud \u00e0 longue dur\u00e9e de vie de votre plateforme CI\/CD.<\/p>\n<p>Les outils sont matures et bien support\u00e9s. GitHub Actions, GitLab CI et les trois principaux fournisseurs cloud disposent d&rsquo;un support de f\u00e9d\u00e9ration OIDC pr\u00eat pour la production. Les actions officielles GitHub Actions (<code>aws-actions\/configure-aws-credentials<\/code>, <code>google-github-actions\/auth<\/code>, <code>azure\/login<\/code>) g\u00e8rent automatiquement l&rsquo;\u00e9change de tokens. Les ressources Terraform existent pour la configuration en infrastructure-as-code.<\/p>\n<p>Il n&rsquo;y a aucune raison de conserver des credentials \u00e0 longue dur\u00e9e de vie dans vos pipelines CI\/CD. Le risque est \u00e9lev\u00e9, le co\u00fbt de migration est faible et l&rsquo;am\u00e9lioration de la s\u00e9curit\u00e9 est imm\u00e9diate. Commencez d\u00e8s aujourd&rsquo;hui.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Si vous auditez les coffres-forts de secrets de la plupart des plateformes CI\/CD aujourd&rsquo;hui, vous trouverez un cimeti\u00e8re de credentials \u00e0 longue dur\u00e9e de vie : des cl\u00e9s d&rsquo;acc\u00e8s AWS cr\u00e9\u00e9es il y a des ann\u00e9es, des cl\u00e9s JSON de comptes de service GCP partag\u00e9es entre des dizaines de pipelines, des GitHub Personal Access &#8230; <a title=\"Credentials \u00e0 Courte Dur\u00e9e de Vie et Workload Identity Federation dans les Pipelines CI\/CD\" class=\"read-more\" href=\"https:\/\/secure-pipelines.com\/fr\/ci-cd-security\/short-lived-credentials-workload-identity-federation-ci-cd\/\" aria-label=\"En savoir plus sur Credentials \u00e0 Courte Dur\u00e9e de Vie et Workload Identity Federation 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-480","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\/480","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=480"}],"version-history":[{"count":1,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/posts\/480\/revisions"}],"predecessor-version":[{"id":494,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/posts\/480\/revisions\/494"}],"wp:attachment":[{"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/media?parent=480"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/categories?post=480"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/tags?post=480"},{"taxonomy":"post_folder","embeddable":true,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/post_folder?post=480"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}