Sécuriser les identifiants CI/CD avec OIDC
Section intitulée « Sécuriser les identifiants CI/CD avec OIDC »Un pipeline d’intégration continue et déploiement continu (CI/CD) qui détient une clé cloud permanente est une cible à haute valeur : une injection dans un script, un log bavard ou un job de pull request suffit à transformer un build en porte d’entrée. La position à tenir est nette : supprimer les identifiants statiques des jobs de déploiement et les remplacer par des jetons fédérés courts, limités à un dépôt, une branche et un environnement.
Un pipeline de déploiement ressemble à un atelier qui reçoit une autorisation pour ouvrir une réserve seulement pendant le temps nécessaire. L’objectif est d’éviter qu’un badge oublié dans un tiroir puisse ouvrir toutes les portes, longtemps après que son propriétaire est parti.
→ Lire l’explication complète de la marmotte
Le compromis central est assumé : la fédération retire le confort trompeur d’une clé copiée dans une variable et impose des règles d’identité plus précises. En échange, le vol d’un secret persistant ne donne plus accès au cloud pendant des mois. Ce coût de configuration est inférieur au coût d’une clé exfiltrée, même si une slide de vendeur promet l’inverse avec trois icônes et un bouclier bleu.
Audit des identifiants statiques du pipeline CI/CD
Section intitulée « Audit des identifiants statiques du pipeline CI/CD »Commencer par l’inventaire, pas par l’activation aveugle d’OpenID Connect (OIDC), protocole d’authentification fédérée fondé sur des jetons signés. Une migration sans inventaire déplace souvent la clé dans un coin moins visible du dépôt. Le secret devient alors « moderne », ce qui ne lui retire pas son talent pour finir dans un log.
-
Rechercher les identifiants dans les fichiers de pipeline, les manifestes de conteneurs, les scripts et les fichiers d’exemple. Chercher les préfixes des fournisseurs cloud, les URL avec mot de passe, les jetons personnels et les clés privées PEM (Privacy-Enhanced Mail).
-
Interroger l’interface ou l’API de la forge pour lister les secrets, variables protégées, variables d’organisation et variables d’environnement. La valeur n’est généralement pas relisible, heureusement. Le nom, la portée et les droits de lecture suffisent à identifier les concentrations de risque.
-
Classer chaque identifiant selon quatre propriétés : propriétaire, système cible, privilèges effectifs et mécanisme de rotation. Une clé sans propriétaire est un compte fantôme avec une date d’expiration théorique. Le révoquer sans vérifier les dépendances casse le déploiement, le conserver casse la sécurité, donc il faut identifier les deux avant de choisir.
-
Révoquer immédiatement les clés découvertes dans l’historique Git, même si le dépôt est privé. Un secret commité est compromis : le retirer du dernier commit ne modifie ni les clones, ni les caches, ni les artefacts. Utiliser un outil de détection tel que Gitleaks dans l’intégration continue, puis purger l’historique si la politique de conservation le permet.
# Recherche locale de motifs fréquents, hors répertoires générés.# Cette commande ne remplace pas un scanner de secrets : elle révèle les cas évidents.rg --hidden --glob '!**/.git/**' \ '(AKIA[0-9A-Z]{16}|-----BEGIN( RSA)? PRIVATE KEY-----|api[_-]?key\s*[:=]|password\s*[:=])' .
# Analyse de l'historique complet avec Gitleaks.# Échouer sur détection empêche l'introduction d'une nouvelle clé statique.gitleaks detect --source . --log-opts="--all" --redact --exit-code 1L’audit doit aussi couvrir les artefacts. Un fichier .npmrc, un cache Maven ou une image intermédiaire peut contenir un jeton alors que le fichier de pipeline paraît propre. Les journaux sont une autre surface : masquer une valeur connue ne masque pas une valeur transformée, encodée ou affichée caractère par caractère. Le masquage est un garde-fou d’interface, pas un mécanisme de confinement.
Pour cadrer les dépendances entre identités de forge, comptes cloud et environnements, consulter aussi les principes d’architecture cyber et la rubrique identités.
Authentification fédérée OIDC vers le fournisseur cloud
Section intitulée « Authentification fédérée OIDC vers le fournisseur cloud »OIDC remplace une clé API (Application Programming Interface) permanente par un jeton JSON Web Token (JWT), document signé contenant des attributs sur l’exécution courante. Le fournisseur CI émet ce jeton pour le job. Le fournisseur cloud vérifie sa signature, son audience et ses attributs, puis délivre des identifiants temporaires via sa gestion des identités et des accès, ou IAM (Identity and Access Management).
La recommandation est de créer un rôle par environnement sensible, au minimum deploy-test et deploy-production. Un rôle unique avec une variable ENV=production est une fiction administrative : la variable appartient au job, donc à tout code exécuté par ce job. La frontière doit être vérifiée par le fournisseur cloud, pas déclarée dans un fichier YAML (YAML Ain’t Markup Language).
Configurer ensuite le fournisseur OIDC de la forge dans le compte cloud. Exiger une audience dédiée au fournisseur cloud, vérifier l’émetteur exact et borner le sujet du jeton au dépôt et à l’environnement. Sur GitHub Actions, l’attribut sub d’un jeton demandé depuis un environnement prend notamment la forme repo:organisation/depot:environment:production.
La durée de session doit rester courte, typiquement 15 à 60 minutes, et ne jamais dépasser la durée maximale d’un déploiement plus une marge réduite. Une session de douze heures pour pousser une image de conteneur n’est pas de la résilience, c’est une clé statique avec un chapeau neuf.
Exemple OIDC GitHub Actions et rôle AWS
Section intitulée « Exemple OIDC GitHub Actions et rôle AWS »Cet exemple cible Amazon Web Services (AWS). Il suppose que le fournisseur OIDC token.actions.githubusercontent.com existe déjà dans IAM et que l’environnement GitHub production limite les branches autorisées et impose les validations nécessaires.
name: deploy-production
on: push: branches: [main]
permissions: contents: read id-token: write # Autorise uniquement l'émission du jeton fédéré OIDC.
jobs: deploy: runs-on: ubuntu-24.04 environment: production # Active les protections de l'environnement GitHub. permissions: contents: read id-token: write steps: - uses: actions/checkout@v4
- name: Obtenir des identifiants AWS temporaires uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::123456789012:role/deploy-production aws-region: eu-west-3 role-session-name: gha-production
- name: Vérifier l'identité obtenue run: aws sts get-caller-identityLa politique de confiance AWS doit refuser tout sujet différent de l’environnement de production :
{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "token.actions.githubusercontent.com:aud": "sts.amazonaws.com", "token.actions.githubusercontent.com:sub": "repo:organisation/depot:environment:production" } } }]}Le rôle deploy-production reçoit uniquement les actions nécessaires à la cible : écriture dans le registre d’images visé, mise à jour du service concerné, lecture des paramètres de production indispensables. Éviter AdministratorAccess, même temporairement. Un jeton court avec tous les droits reste un incendie court, pas un extincteur.
Isolation des jobs et des environnements sensibles
Section intitulée « Isolation des jobs et des environnements sensibles »Un job déclenché par une pull request externe est non fiable par définition. Son code, ses dépendances, son fichier de pipeline et parfois son image de build peuvent être contrôlés par un tiers. Aucun secret de déploiement, aucun jeton OIDC cloud et aucun accès au réseau interne ne doit lui être accordé.
Appliquer ces règles :
-
Exécuter les pull requests externes avec des permissions minimales de lecture. Désactiver l’accès aux secrets de dépôt et d’environnement.
-
Ne jamais utiliser un déclencheur exécutant le contenu d’une pull request avec le jeton du dépôt cible. Les variantes qui donnent les privilèges du dépôt principal à du code externe transforment une revue de code en mécanisme d’exfiltration.
-
Séparer les runners, machines exécutant les jobs, entre build non fiable et déploiement. Un runner auto-hébergé partagé peut conserver des espaces de travail, des couches de conteneur, des identifiants de registre ou des sockets. Nettoyer un répertoire après coup ne neutralise pas un démon de conteneur déjà compromis.
-
Protéger l’environnement
productionpar des branches autorisées, des approbations et des règles de déploiement. Ces contrôles doivent précéder l’émission du jeton OIDC, pas seulement l’exécution d’une étape esthétique appeléeapproval.
Un artefact produit par un job non fiable ne devient pas fiable parce qu’il porte l’étiquette release. Signer l’artefact, vérifier sa provenance et déployer uniquement une référence immuable, idéalement un condensat cryptographique d’image. Les mécanismes de signature relèvent de la même discipline que la gestion des clés décrite dans la section cryptographie.
Vérifier le refus entre test et production
Section intitulée « Vérifier le refus entre test et production »La séparation n’existe que si son échec est testé. Créer un workflow de test qui assume exclusivement le rôle deploy-test, puis tenter une action de production volontairement refusée. Le contrôle attendu est AccessDenied, pas une absence de log.
# Job de contrôle exécuté dans l'environnement test.# La commande de production doit échouer avec AccessDenied.- name: Prouver l'absence d'accès à la production run: | aws sts get-caller-identity if aws s3 ls s3://artefacts-production-confidentiels; then echo "Accès production accordé par erreur" >&2 exit 1 fiTester aussi le refus d’assumer directement le rôle de production depuis une branche de test et depuis une pull request externe. Conserver les événements d’émission de jetons, les appels AssumeRoleWithWebIdentity et les refus IAM dans le journal d’audit cloud. Une alerte doit déclencher sur un sujet OIDC inconnu, une audience inattendue, une élévation de privilège ou une session anormalement longue.
OIDC ne garantit pas l’intégrité du code autorisé à déployer. Si une branche protégée accepte une fusion malveillante, le jeton fédéré déploiera proprement le code malveillant, avec une traçabilité impeccable. La fédération réduit le vol d’identifiants ; elle ne remplace ni la revue, ni la protection de branche, ni la sécurité de la chaîne de dépendances.
Prévoir enfin la reprise : conserver une procédure d’urgence avec un rôle humain fortement authentifié, journalisé et limité dans le temps. Ne pas recréer une clé permanente « juste pour cette nuit ». Vingt ans de gestion d’incident apprennent que cette nuit a une mémoire remarquable.
🐝 Ce qui arrive si on s’en passe
Section intitulée « 🐝 Ce qui arrive si on s’en passe »Sans jeton fédéré, chaque déploiement repose sur une clé qui survit aux départs, aux migrations de forge et aux rotations oubliées. La conséquence la plus coûteuse est l’aveuglement : les appels cloud remontent alors sous une identité unique, sans dépôt, sans branche, sans numéro d’exécution, ce qui rend impossible de dater le début d’un usage illégitime ou de distinguer un déploiement légitime d’une réutilisation depuis une autre machine. La reprise suit la même pente : révoquer une clé partagée interrompt tous les pipelines qui l’utilisent, y compris ceux dont personne ne connaît la dépendance, donc l’arbitrage penche vers le maintien du secret compromis. S’ajoute une fenêtre d’exposition sans borne : un identifiant permanent capté dans un artefact ou un cache reste exploitable longtemps après la correction du pipeline, et aucune expiration ne referme la porte à la place des équipes.
🦫 Explication de la marmotte 🍫
Section intitulée « 🦫 Explication de la marmotte 🍫 »Un pipeline est une suite d’actions automatiques qui teste puis publie un logiciel. Pour publier dans un service en ligne, il faut prouver que cette action a le droit de modifier cet environnement. Le problème vient des mots de passe et clés gardés longtemps dans les réglages du pipeline : si quelqu’un les lit, il peut les réutiliser depuis ailleurs.
La solution consiste à demander une autorisation temporaire au moment du déploiement. Le service qui exécute le pipeline produit alors une preuve signée indiquant quel dépôt, quelle branche et quel environnement demandent l’accès. Le fournisseur en ligne vérifie cette preuve avant de donner des identifiants temporaires. Si la preuve concerne les tests, elle ne doit donner accès qu’aux tests. Si elle concerne la production, elle doit aussi respecter les règles prévues pour la production.
Les jobs qui exécutent du code envoyé par des personnes externes restent séparés. Ils ne reçoivent ni les secrets ni l’autorisation temporaire utilisée pour publier. Il faut tester ce refus volontairement : un job de test qui peut lire ou modifier la production révèle une erreur de réglage.
Si une preuve est refusée, le déploiement s’arrête. Si le code autorisé est malveillant, cette méthode ne le bloque pas : elle protège les accès, pas la qualité du code.
À lire aussi
- OIDC pour sécuriser les identifiants CI/CDRéduire le risque des clés API et jetons de déploiement CI/CD avec une fédération OIDC à durée courte.
- Sécuriser les secrets et permissions CI/CDSécuriser une pipeline CI/CD impose des secrets éphémères, des permissions minimales et une revue à quatre yeux réellement bloquante.
- Intégration continue avec Git : automatiser vos workflowsGuide technique sur l'intégration continue avec Git, détaillant les configurations, cas d'usage, risques et bonnes pratiques pour automatiser vos workflows.
- Signer commits et artefacts contre quelles attaquesSigner ses commits et ses artefacts : contre quoi, précisément, avec les limites, prérequis et règles d’exploitation à appliquer.
Pages voisines
La citent
- Écrire un Dockerfile durci avec condensé, multi-étapes et non root
- Comment utiliser CSA STAR et le questionnaire CAIQ
- OIDC pour sécuriser les identifiants CI/CD
Sécuriser les identifiants CI/CD avec OIDC
Elle cite
