AWS / Cloud · Architecture / CI-CD

Déployer depuis GitLab sans clé AWS permanente : l’IaC OIDC du portfolio

Comment le pipeline obtient une session AWS temporaire et comment l’IaC sépare l’identité GitLab, la livraison du site et les droits de CloudFormation.

GitLab demande une session temporaire via OIDC; le rôle de déploiement a des droits CloudFormation et de publication S3 et peut transmettre un rôle d’exécution CloudFormation séparé.

Pour un mainteneur GitLab/AWS, OIDC permet de demander une session temporaire pour le projet et la branche autorisés. Le bootstrap IAM définit la confiance et les permissions; le pipeline demande la session puis utilise les opérations permises. Contrôlez le rôle obtenu avant de préparer une livraison.

Disposez d’un fournisseur IAM OIDC déjà créé, du rôle cible et de sa trust policy, ainsi que d’un job autorisé demandant un ID token pour l’audience prévue. Ce bootstrap est une configuration AWS préalable à faire administrer dans votre environnement. L’AWS CLI du job doit disposer de la session temporaire sans afficher token ni credentials. Si ces prérequis manquent, préparez la fédération selon la documentation GitLab avant ce contrôle.

La chaîne d’identité et de livraison

Le chemin configuré est le suivant :

Job GitLab sur main protégée
  → ID token OIDC (audience sts.amazonaws.com)
  → AWS STS / AssumeRoleWithWebIdentity
  → rôle IAM GitLabDeployPortfolio
       ├─ publication d’objets dans le bucket du portfolio
       └─ opérations CloudFormation bornées + iam:PassRole ciblé
            → PortfolioCloudFormationExecution
            → ressources des stacks portfolio

GitLab émet un ID token pour le job qui le demande. AWS STS accepte la demande AssumeRoleWithWebIdentity si le fournisseur fédéré et les conditions de confiance du rôle correspondent. STS renvoie alors des credentials temporaires pour le rôle. Le jeton OIDC est lui-même une donnée d’authentification temporaire : le pipeline l’écrit dans un fichier temporaire, ne l’affiche pas et le supprime à la fin du job.

Cette fédération évite de stocker une access key AWS longue durée pour cette voie de déploiement. Elle ne dispense pas de protéger le code CI, la branche, les variables protégées et les permissions associées au rôle.

Ce que déclare le bootstrap IAM

Le template CloudFormation de bootstrap IAM réutilise l’ARN d’un fournisseur IAM OIDC gitlab.com dans la trust policy; il ne crée pas le fournisseur lui-même. La confiance du rôle GitLabDeployPortfolio exige des correspondances exactes pour l’audience sts.amazonaws.com, le sujet du projet sur la branche main, la référence protégée, project_id et namespace_id. Le chemin du projet et les identifiants numériques sont propres à l’environnement et ne sont pas reproduits ici.

Les claims aud, sub, ref_protected, project_id et namespace_id définissent qui peut demander le rôle. Dans .gitlab-ci.yml, les jobs concernés ont aussi une règle qui les rend disponibles sur main protégée; certains sont manuels. La règle du pipeline et la trust policy sont deux contrôles distincts.

Adaptez la confiance si le chemin du projet, son namespace ou ses identifiants changent. AWS permet les conditions supplémentaires ref_protected, project_id et namespace_id pour GitLab.com. Pour une instance auto-hébergée, ne transposez pas ces conditions : vérifiez l’issuer et utilisez les conditions sub et aud décrites pour cette fédération.

Trois périmètres de permissions

Le rôle GitLab et le rôle CloudFormation n’ont pas la même fonction.

  1. GitLabDeployPortfolio est le rôle assumé via OIDC. Sa policy GitLabCloudFormationPortfolioPolicy limite les opérations Change Set et de consultation aux stacks lucat-portfolio-prod et lucat-portfolio-api. Elle conditionne la création du Change Set au rôle CloudFormation attendu. Une permission iam:PassRole ne vise que PortfolioCloudFormationExecution et exige iam:PassedToService égal à cloudformation.amazonaws.com.
  2. Le même rôle GitLab publie les fichiers du site directement dans S3. La policy borne les métadonnées au bucket du portfolio et la lecture, l’écriture ou la suppression aux objets de ce bucket. Ce chemin de publication n’est pas un passage par CloudFormation.
  3. PortfolioCloudFormationExecution est assumé par le service CloudFormation. Le bootstrap lui associe PortfolioCloudFormationSitePolicy, qui encadre la gestion des ressources d’infrastructure du site. Dans l’IaC consultée, cette politique couvre notamment le bucket, la distribution et la fonction CloudFront du portfolio, ainsi que des opérations Route 53 définies pour les ressources du site.

Le rôle de livraison encadre les actions GitLab; le rôle d’exécution encadre les ressources gérées par CloudFormation. Les permissions S3 directes du job GitLab suivent leur propre policy.

Comment le pipeline utilise ces permissions

Le job verify-aws-oidc de .gitlab-ci.yml demande un token avec l’audience sts.amazonaws.com, retire les variables de credentials classiques et appelle aws sts get-caller-identity. Il vérifie que l’ARN obtenu correspond au rôle portfolio. Ce contrôle ne démontre pas les permissions de livraison.

Les jobs de publication et de préparation de Change Set étendent ensuite le modèle OIDC commun. Le job de publication approuvée vérifie le bucket et l’artefact puis synchronise le site dans S3. Les jobs de préparation construisent un Change Set avec le rôle PortfolioCloudFormationExecution; le pipeline demande une revue du résultat et ne l’exécute pas dans ces étapes de préparation. Ces mécanismes sont présents dans la configuration suivie.

Contrôler le rôle puis décider de l’opération

Dans le job autorisé dont la session temporaire est configurée, lancez :

aws sts get-caller-identity

Comparez Account et l’ARN au compte et au rôle attendus. Une identité inattendue impose d’arrêter la livraison et de revoir la fédération. Le 27 septembre 2026, une pipeline du portfolio a obtenu une session STS et ce contrôle a confirmé le rôle attendu. Cette réponse ne prouve pas un droit d’écriture S3.

Pour publier un objet, distinguez trois étapes :

  1. Examinez les permissions du rôle et du bucket pour l’action et la clé visées, avec leurs conditions et éventuels refus. STS ne prouve pas s3:PutObject.
  2. Faites autoriser la mutation prévue : bucket, préfixe, fichiers et éventuelles suppressions de synchronisation. Une permission technique ne décide pas de réaliser l’action.
  3. Après l’exécution autorisée, vérifiez séparément l’objet et son contenu dans le périmètre attendu. Le contrôle d’identité ne remplace pas ce contrôle de résultat.

La sortie transmise au job suit Un job CI manque-t-il d’un fichier requis ou seulement d’un cache ?. L’accès lecteur à l’origine suit Déployer une distribution CloudFront avec une origine S3 privée.

Contrôles de sécurité

  • Contrôler le sujet, l’audience et les autres claims exacts dans la trust policy puis tester une identité autorisée et des contextes refusés sans exposer les tokens.
  • Vérifier séparément les permissions CloudFormation, iam:PassRole et l’accès direct aux objets S3. Un refus attendu sur un périmètre non autorisé doit être testé explicitement.
  • Relire le Change Set avant toute exécution. La préparation d’un Change Set n’équivaut pas à son déploiement.
  • Garder le token hors des logs et des artifacts; conserver une durée de vie et un périmètre limités pour les credentials temporaires.

La sécurité d’OIDC repose sur toute la chaîne : identité émise par GitLab, confiance IAM, permissions du rôle de livraison, rôle transmis à CloudFormation et contrôles du pipeline.

Sources techniques

  1. Configure OpenID Connect in AWS to retrieve temporary credentialsGitLab
  2. ID token authenticationGitLab
  3. AssumeRoleWithWebIdentityAWS
  4. Request temporary security credentialsAWS