> ## Content Index
> Fetch the complete content index at: https://www.sfeir.dev/llms.txt
> Use this file to discover other available public pages before exploring further.

# GCP et GitLab Privé : Authentifier vos Pipelines CI/CD en Keyless avec Workload Identity
- URL: https://www.sfeir.dev/cloud/gcp-et-gitlab-prive-authentifier-vos-pipelines-ci-cd-en-keyless-avec-workload-identity/
- Published: 2025-02-14T14:41:39.000Z
- Updated: 2025-02-14T14:41:39.000Z
- Description: Découvrez comment configurer Workload Identity via Terraform pour sécuriser vos pipelines Gitlab avec OIDC, sans JSON Keys, tout en simplifiant la gestion des identités et renforçant leur sécurité.
- Author: Thomas GRUSON
- Tags: Sécurité, GCP, Gitlab, Terraform, Cloud

## Pourquoi utiliser Google Workload Identity ?

Objectifs de l'article

Dans un monde où la sécurité et l'efficacité des pipelines CI/CD sont primordiales, l'utilisation de Google Workload Identity afin de s'authentifier facilement et de manière sécurisée aux services de la GCP peut apporter des avantages significatifs.

Cet article vous guidera à travers chaque étape de cette intégration.

Nous utiliserons du code[ Terraform](https://www.sfeir.dev/cloud/les-modules-terraform-un-guide-pratique/) afin de tracer et d'automatiser la configuration, ce qui vous permettra également de récupérer facilement les actions effectuées. 

**Objectifs de l'article :**

1. **Comprendre Google Workload Identity** : Nous expliquerons ce qu'est Google Workload Identity et pourquoi il est aujourd'hui un choix de premier ordre dans l'authentification aux services Google.
2. **Configurer Google Workload Identity** : Vous apprendrez à configurer un Workload Identity Pool Provider et un Workload Identity Pool en utilisant Terraform.
3. **Autoriser la CI/CD d'un repository à s'authentifier** : Nous détaillerons comment créer, configurer un Service Account et le lier à un dépôt [**GitLab**](https://www.sfeir.dev/tendances/rex-remote-foundation-certification-by-gitlab/).
4. **Intégrer dans GitLab CI/CD** : Vous verrez comment intégrer cette configuration dans vos pipelines CI/CD GitLab, avec des exemples de fichiers `.gitlab-ci.yml`.

## Qu'est que Google Workload Identity exactement ?

Lien avec l'objectif de l'article

Pour bien comprendre l’intégration de Google Workload Identity dans un environnement GitLab CI/CD on-premise, il est essentiel de saisir les concepts de la fédération d’identité et leur application dans ce contexte.

## **Fédération d'identité : GitLab, ses utilisateurs et ses groupes**

La fédération d’identité permet à des utilisateurs et groupes d’un système externe (comme GitLab) de s’authentifier et d’accéder à des ressources dans un autre système (comme Google Cloud) sans avoir à gérer des identités distinctes dans chaque système. Dans notre cas, GitLab et ses utilisateurs/groupes seront fédérés avec Google Cloud pour accéder aux ressources nécessaires à l’exécution des pipelines CI/CD.

## Représentation dans Google Cloud : Workload Identity Pool et Pool Provider

Pour réaliser cette fédération d'identité, nous allons utiliser deux concepts clés de Google Cloud : le **Workload Identity Pool** et le **Workload Identity Pool Provider**.

- **Workload Identity Pool** : Un Workload Identity Pool est une collection d’identités externes qui peuvent être mappées à des identités Google Cloud. Il sert de conteneur pour les identités provenant de systèmes externes comme GitLab.
- **Workload Identity Pool Provider** : Un Provider au sein d’un Workload Identity Pool définit comment les identités externes sont mappées et authentifiées. Il décrit les protocoles d’authentification et les règles de mapping des identités.

👍

****Bonnes pratiques** ****: un seul Pool Provider par Pool**  
Il est recommandé de n’avoir qu’un seul Pool Provider par Workload Identity Pool pour simplifier la gestion et éviter les conflits de configuration.

## Choix du protocole d'authentification : OIDC

Nous allons utiliser le protocole OIDC (OpenID Connect), car GitLab, même en version on-premise, supporte ce protocole.

OIDC repose sur OAuth 2.0 et permet une authentification sécurisée. Google Workload Identity supporte aussi d’autres protocoles comme SAML et JWT, mais OIDC reste notre choix privilégié ici pour sa compatibilité avec GitLab.

## **Les Avantages de Workload Identity par rapport aux JSON Keys**

L’utilisation de Google Workload Identity offre plusieurs avantages significatifs par rapport à l’ancienne méthode dépréciée basée sur les JSON Keys pour l’authentification dans Google Cloud.

1. **Sécurité renforcée**

Les JSON Keys sont des clés statiques stockées sur des serveurs ou des machines, ce qui les rend vulnérables à des fuites accidentelles ou des accès non autorisés. En revanche, Workload Identity utilise une approche de fédération d’identité qui permet de limiter les accès temporaires et dynamiques.

La rotation automatique des tokens d’identification dans Workload Identity supprime la nécessité de gérer manuellement les clés d’accès, réduisant ainsi le risque d’attaques potentielles.

1. **Simplification de la gestion des identités**

Avec Workload Identity, il n’est plus nécessaire de gérer des fichiers de clés ou de distribuer ces fichiers aux utilisateurs ou aux pipelines CI/CD. Tout est géré de manière transparente à travers le mapping des identités externes vers des comptes de service Google Cloud.

Les accès sont accordés via des permissions IAM standard sans manipulation des secrets, ce qui simplifie la gestion et l’audit.

1. **Moins de responsabilités pour l’infrastructure**

Les JSON Keys nécessitent de suivre des pratiques strictes pour assurer qu’elles ne soient pas exposées (mises à jour régulières, stockage sécurisé). Workload Identity élimine ce fardeau en utilisant des jetons éphémères qui n’ont pas besoin d’être stockés à long terme.

**4\. Meilleure intégration avec les environnements cloud natifs**

Workload Identity est mieux intégré aux workflows cloud modernes, notamment pour les environnements CI/CD, car il s’intègre directement aux fournisseurs d’identité comme GitLab, ce qui facilite la configuration et la maintenance à long terme.

## En résumé

Google Workload Identity permet à des identités externes, comme celles de GitLab, de s’authentifier auprès de Google Cloud en tant que comptes de service via des protocoles sécurisés comme OIDC. Cette approche élimine la gestion des clés statiques (JSON Keys) en faveur de jetons temporaires, renforçant ainsi la sécurité. La configuration se fait via le Workload Identity Pool Provider, qui définit les règles d’authentification et permet une gestion simplifiée et intégrée des identités entre les environnements.

## Configuration de Workload Identity 

On établit le lien GCP - Gitlab

Pour intégrer Google Workload Identity avec GitLab dans un environnement privé, il est nécessaire de configurer le **Workload Identity Pool** et le **Workload Identity Pool Provider** afin de gérer de manière sécurisée l’authentification des pipelines GitLab. Voici le guide pas à pas de la configuration en utilisant Terraform.

👍

****Source** ****: le git repository du code de l'article**  
Voici le lien vers un [repository git public](https://github.com/Thomgrus/gitlab-gcp-workload-identity-sample?ref=sfeir.dev) pour consulter les fichiers de configuration détaillés dans l'article. 

## Configuration du provider terraform Google

```hcl
provider "google" {
  project = var.google_project_id
  region  = var.google_region
  default_labels = {
    project = "gitlab-workload-identity"
  }
}
```

Les variables `google_project_id` et `google_region` permettent de spécifier le projet et la région Google Cloud. Assurez-vous de les définir dans votre configuration :

```hcl
variable "google_project_id" {
  description = "Identifiant du projet GCP où le Workload Identity sera configuré"
  type        = string
}

variable "google_region" {
  description = "Région du projet GCP"
  type        = string
  default     = "europe-west1"  # ou la région de votre choix
}
```

## **Création du Workload Identity Pool**

Le **Workload Identity Pool** agit comme un conteneur pour les identités GitLab externes, nous permettant de fédérer des identités GitLab dans Google Cloud.

```hcl
# Create a pool of identity providers (GitLab)
resource "google_iam_workload_identity_pool" "gitlab_pool" {
  workload_identity_pool_id = "private-gitlab-pool"
}

```

Ce pool, nommé `private-gitlab-pool`, contiendra toutes les identités issues de GitLab, fédérées pour accéder aux ressources GCP.

## **Récupération de la clé publique GitLab**

Comme le serveur GitLab est privé, google ne peut pas récupérer la clef publique depuis son infrastructure cloud. Ce n'est pas un problème si nous exécutons le code terraform depuis un environnement qui a accès au serveur Gitlab. Nous devons alors récupérer un fichier JSON Web Key Set (JWKS) pour permettre la vérification des jetons JWT provenant de GitLab. Ce fichier contient les clés publiques utilisées pour valider les signatures de ces jetons.

```hcl
# Download JWKS file from GitLab (public key used to verify JWT token)
data "http" "jwks_gitlab" {
  url = "${var.gitlab_url}/oauth/discovery/keys"

  # Optional request headers
  request_headers = {
    Accept = "application/json"
  }
}
```

La variable `gitlab_url` est nécessaire pour définir l’URL de votre instance GitLab. Ajoutez cette variable dans votre fichier de configuration Terraform :

```hcl
variable "gitlab_url" {
  description = "URL de l'instance GitLab privée"
  type        = string
  default     = "https://my-private-gitlab.com"
}
```

## **Configuration du Workload Identity Pool Provider**

Le **Workload Identity Pool Provider** gère la validation des identités provenant de GitLab. En définissant l’attribut oidc, nous précisons l’URL de l’émetteur GitLab et les clés pour valider les jetons JWT.

```hcl
resource "google_iam_workload_identity_pool_provider" "gitlab_pool_provider" {
  workload_identity_pool_id          = google_iam_workload_identity_pool.gitlab_pool.workload_identity_pool_id
  workload_identity_pool_provider_id = "private-gitlab-pool-provider"

  attribute_mapping = {
    "google.subject"           = "assertion.sub", # Identifiant principal
    "attribute.aud"            = "assertion.aud",
    "attribute.project_path"   = "assertion.project_path",
    "attribute.project_id"     = "assertion.project_id",
    "attribute.namespace_id"   = "assertion.namespace_id",
    "attribute.namespace_path" = "assertion.namespace_path",
    "attribute.user_email"     = "assertion.user_email",
    "attribute.ref"            = "assertion.ref",
    "attribute.ref_type"       = "assertion.ref_type",
  }
  
  oidc {
    issuer_uri = var.gitlab_url
    jwks_json  = data.http.jwks_gitlab.response_body
  }
}
```

Cette configuration mappe les attributs de GitLab vers des identités GCP via les attributs de l’objet `attribute_mapping`. Le `google.subject` est requis, et les autres attributs (`aud`, `project_id`, `namespace_id`, etc.) permettent d’ajouter des détails supplémentaires à chaque identité.

## **Récupération des informations utiles**

Enfin, nous ajoutons des outputs pour obtenir les informations de la configuration appliquée utiles dans les étapes suivantes pour référencer le Pool et le Pool Provider.

```hcl
output "GCP_WORKLOAD_IDENTITY_PROVIDER" {
  value = google_iam_workload_identity_pool_provider.gitlab_pool_provider.name
}

output "GCP_WORKLOAD_IDENTITY_POOL" {
  value = google_iam_workload_identity_pool.gitlab_pool.name
}
```

En suivant ces étapes, le lien entre Google Cloud et GitLab est maintenant établi, permettant à GitLab de fédérer des identités vers GCP et d’accéder aux ressources Google de manière sécurisée.

## ****De Gitlab vers un Service Account Google**

Autoriser une identité Gitlab à utiliser un SA Google

Pour permettre aux jobs GitLab CI/CD d’accéder aux ressources Google Cloud via un **Service Account (SA)**, nous configurons un module nommé `workload-identity-account`. Ce module va faciliter la création d’un Service Account et la liaison avec une identité GitLab en utilisant **Workload Identity**.

👍

****Source** ****: le module est dans le même repository**  
Voici le lien vers [le module](https://github.com/Thomgrus/gitlab-gcp-workload-identity-sample/tree/main/terraform/workload-identity-account?ref=sfeir.dev).

## **Création du Service Account (SA)**

Le Service Account est dédié aux jobs GitLab Runner pour s’authentifier dans GCP

```hcl
resource "google_service_account" "sa" {
  project      = var.google_project_id
  account_id   = var.service_account_name
  display_name = var.service_account_name
  description  = "Service account used by Gitlab Runner in order to authenticate to GCP"
}
```

Les variables `google_project_id` et `service_account_name` sont requises pour spécifier le nom du compte de service et dans quel projet GCP il sera créé.

```hcl
variable "service_account_name" {
  description = "The name of the service account to create"
  type        = string
}

variable "google_project_id" {
  description = "The ID of the project in which the service account will be created"
  type        = string
}
```

## **Créer la liaison Workload Identity**

💡

On peut utiliser différents attributs de l'identité configurée via le ****Workload Identity Pool Provider** dans `attribute_mapping` pour autoriser des identités gitlab à utiliser des Service Accounts Google.  
Dans cet exemple on prendra simplement le project\_path du projet gitlab.

Le Service Account est associé au **Workload Identity Pool** via une autorisation `roles/iam.workloadIdentityUser`, permettant à une identité GitLab d’assumer le rôle défini pour accéder aux ressources :

```hcl
# Create a workload identity binding for the service account
resource "google_service_account_iam_member" "workload_identity_binding" {
  service_account_id = google_service_account.sa.id
  role               = "roles/iam.workloadIdentityUser"
  member             = "principalSet://iam.googleapis.com/${var.gitlab_pool_name}/attribute.project_path/${var.gitlab_project_path}"
}
```

L'attribut `member` contient une référence au **principalSet**, identifiant unique pour les **identités GitLab** dans le **Workload Identity Pool**. La valeur `${var.gitlab_pool_name}` correspond au nom du pool GitLab configuré dans GCP, tandis que `${var.gitlab_project_path}` fait référence au chemin du projet GitLab. Cette configuration autorise spécifiquement les jobs exécutés sur ce projet GitLab à se faire passer pour le SA.

```hcl
variable "gitlab_pool_name" {
  description = "The name of the gitlab pool"
  type        = string
}

variable "gitlab_project_path" {
  description = "The path of the gitlab project"
  type        = string
}
```

**En pratique, dans GitLab CI/CD**, ce lien permet à un job d’assumer l’identité du Service Account et d’accéder aux ressources sans JSON Key, rendant l’authentification plus sécurisée et simplifiée.

## **Tips : Impersonation du Service Account**

Cette partie est facultative. Dans le but d'améliorer la flexibilité et assurer un fonctionnement identique en local et dans le CI/CD, nous autorisons le Service Account à s'utiliser lui-même 🧐 :

```hcl
resource "google_service_account_iam_member" "impersonate" {
  service_account_id = google_service_account.sa.id
  role               = "roles/iam.serviceAccountUser"
  member             = google_service_account.sa.member
}

resource "google_service_account_iam_member" "impersonate_token_creator" {
  service_account_id = google_service_account.sa.id
  role               = "roles/iam.serviceAccountTokenCreator"
  member             = google_service_account.sa.member
}
```

Nous verrons par la suite un exemple avec du code terraform exécuté dans un job Gitlab CI/CD qui montrera tout l'intérêt de cette configuration.

## **Appel du module dans le code principal**

Une fois le module `workload-identity-account` configuré, nous pouvons l’invoquer dans le code principal Terraform pour créer un Service Account spécifique, le lier au projet GitLab et configurer les permissions nécessaires pour GitLab CI/CD.

Voici comment appeler le module dans le fichier principal :

```hcl
module "workload-identity-account" {
  for_each             = var.project_path_to_sa
  source               = "./workload-identity-account"
  google_project_id    = var.google_project_id
  service_account_name = each.value
  gitlab_project_path  = each.key
  gitlab_pool_name     = google_iam_workload_identity_pool.gitlab_pool.name
}
```

Dans cet appel :

- `for_each` itère sur une map avec en clef le path du projet gitlab et en valeur le nom du service account créé et lié à ce projet.
- `source` pointe vers le chemin du module, ici `./workload-identity-account`.
- `google_project_id` et `service_account_name` définissent respectivement le projet GCP et le nom du Service Account.
- `gitlab_project_path` est le chemin du projet GitLab auquel le Service Account sera associé.
- `gitlab_pool_name` fait référence au nom du Workload Identity Pool, ici récupéré depuis le pool `gitlab_pool` précédemment créé.

Voici la nouvelle variable nécessaire:

```hcl
variable "project_path_to_sa" {
  description = "Gitlab project path to SA name"
  type        = map(string)
}
```

Il ne reste plus qu'à configurer les variables nécessaires dans un fichier `terraform.tfvars` par exemple exécuter le code Terraform

```hcl
google_project_id = "my-google-project-id"
gitlab_url        = "https://my-private-gitlab.com"

project_path_to_sa = {
  "test/sandbox-workload-identity" = "gitlab-sandbox-wi"
}
```

```shell
terraform init
terraform apply
```

💡

****Authentification au provider Google**  
Une manière simple de s'authentifier en local au provider Google terraform est d'utiliser le cli de Google `gcloud`  
Ainsi si vous avez les accès nécessaires, `gcloud auth application-default login` permet de rapidement démarrer. Sinon vous pouvez vous référer à la documentation du provider Google : [https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/getting\_started#adding-credentials](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/getting%5Fstarted?ref=sfeir.dev#adding-credentials)

👍

****Bonnes pratiques : ne pas utiliser un backend local**  
Par défaut terraform utilise un backend local sauvegardé à l'endroit de l'exécution du code terraform. Il est recommendé d'utiliser un backend décentralisé pour pouvoir sécuriser et collaborer sur la stack mise en place. Vous pouvez vous référer à cette documentation : [https://developer.hashicorp.com/terraform/language/backend](https://developer.hashicorp.com/terraform/language/backend?ref=sfeir.dev)

## Dans la Gitlab CI/CD maintenant

Sans json\_key !

Pour pouvoir réaliser l'authentification dans vos pipelines GitLab CI/CD, on va utiliser la variable d'environnement `GOOGLE_APPLICATION_CREDENTIALS` comme avec une json\_key mais en se basant sur l'id\_token généré par Gitlab.

Pour cela on utilise un modèle de job `.gcp-auth` qui génère un jeton d’authentification et configure l’environnement pour utiliser Workload Identity. Ensuite, on pourra réutiliser ce modèle de manière flexible dans d’autres jobs nécessitant une authentification GCP.

## **Créer le modèle .gcp-auth**

Dans un fichier `.gitlab-ci.yml` : 

```yaml
.gcp-auth:
    id_tokens:
        WORKLOAD_IDENTITY_TOKEN:
            aud: https://iam.googleapis.com/## Remplacez ici par le nom du Workload Identity pool provider provenant de l'output Terraform `GCP_WORKLOAD_IDENTITY_PROVIDER` ##
    variables:
        GCP_WORKLOAD_IDENTITY_PROVIDER: ## Remplacez ici par `GCP_WORKLOAD_IDENTITY_PROVIDER` ##
        GOOGLE_APPLICATION_CREDENTIALS: $CI_BUILDS_DIR/.workload_identity.wlconfig
    before_script:
        - |
            if [ -z "${SERVICE_ACCOUNT}" ]; then
                echo "Erreur : la variable SERVICE_ACCOUNT n’est pas définie. Veuillez définir une variable SERVICE_ACCOUNT avec l'email du service account à utiliser."
                exit 1
            fi
        - |-
            # Enregistre le jeton JWT dans un fichier
            echo $WORKLOAD_IDENTITY_TOKEN > $CI_BUILDS_DIR/.workload_identity.jwt
            
            # Configure les credentials dans un fichier JSON pour impersonate le Service Account
            cat << EOF > $GOOGLE_APPLICATION_CREDENTIALS
            {
                "type": "external_account",
                "audience": "//iam.googleapis.com/$GCP_WORKLOAD_IDENTITY_PROVIDER",
                "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
                "token_url": "https://sts.googleapis.com/v1/token",
                "credential_source": {
                    "file": "$CI_BUILDS_DIR/.workload_identity.jwt"
                },
                "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/$SERVICE_ACCOUNT:generateAccessToken"
            }
            EOF
```

Dans ce job `.gcp-auth` :

- `id_tokens` : configure un jeton jwt Gitlab pour le Workload Identity Pool Provider provisionné par terraform plus haut dans l'article. Le champ audience doit être mis à jour pour inclure le nom de votre Workload Identity Pool Provider.

💡

La valeur de `GCP_WORKLOAD_IDENTITY_PROVIDER` est de la forme :  
`projects/` **`PROJECT_NUMBER`**`/locations/global/workloadIdentityPools/` **`WORKLOAD_IDENTITY_POOL_NAME`**`/providers/` **`WORKLOAD_IDENTITY_POOL_PROVIDER_NAME`**  
Avec dans notre cas :  
**`WORKLOAD_IDENTITY_POOL_NAME`** \= `private-gitlab-pool`  
**`WORKLOAD_IDENTITY_POOL_PROVIDER_NAME`** \= `private-gitlab-pool`\-provider

- `variables` : définit les variables nécessaires, dont `GCP_WORKLOAD_IDENTITY_PROVIDER` pour le nom complet du Pool Provider et `GOOGLE_APPLICATION_CREDENTIALS` pour le fichier de configuration de GCP que l'on va généré dans le `before_script`.
- `before_script` : vérifie que la variable `SERVICE_ACCOUNT` est bien définie, puis crée un fichier, localisé à l'endroit défini par `GOOGLE_APPLICATION_CREDENTIALS` , configurant l’authentification à l’aide du Workload Identity pour impersonate le Service Account spécifié.

## **Utiliser .gcp-auth dans d’autres jobs**

Ensuite, vous pouvez étendre ce modèle `.gcp-auth` dans un job spécifique, comme un job Terraform plan :

```yaml
tf-plan:
    extends: .gcp-auth
    variables:
        SERVICE_ACCOUNT: gitlab-sandbox-wi@my-google-project-id.iam.gserviceaccount.com # Remplacez par l'email du Service Account à impersonate
    image: hashicorp/terraform:1.9
    script:
        - terraform init
        - terraform plan
```

Dans ce job tf-plan :

- `extends: .gcp-auth` : permet d’hériter de la configuration de .gcp-auth pour l’authentification.
- `SERVICE_ACCOUNT` : définit l’email du Service Account à utiliser pour ce job.
- `script` : exécute les commandes Terraform avec les permissions et le contexte de sécurité établis par le Workload Identity.

## **Résultat attendu**

Avec cette configuration, chaque job CI/CD qui étend `.gcp-auth` peut accéder de manière sécurisée aux ressources GCP en utilisant l’authentification dynamique du Workload Identity, sans JSON Key. Cela simplifie également la gestion de l’infrastructure et réduit les risques de sécurité, car il n’est plus nécessaire de stocker des clés d’accès statiques dans vos pipelines CI/CD.