Exercice 09 : GKE Workload Identity - Accès sécurisé aux services GCP
🎯 Objectifs
À la fin de cet exercice, vous serez capable de :
- ✅ Créer un cluster GKE avec Workload Identity Federation activé
- ✅ Configurer la liaison entre un KSA (Kubernetes Service Account) et un GSA (Google Service Account)
- ✅ Accéder à Cloud Storage depuis un pod sans monter de clé JSON
- ✅ Expliquer les risques des clés JSON et pourquoi Workload Identity les remplace
Durée estimée : 45 minutes
Difficulté : ⭐⭐⭐⭐☆ (Avancé)
Prérequis : Module Kubernetes Intermédiaire complété, gcloud CLI configurée
📖 Contexte
Le problème classique : votre application sur GKE a besoin d'accéder à Cloud Storage. La mauvaise solution (souvent utilisée) : créer un Service Account GCP, exporter une clé JSON, la stocker dans un Secret Kubernetes. Risques : la clé peut être exfiltrée, elle ne tourne pas automatiquement, elle n'a pas d'expiration.
Workload Identity est la solution sécurisée : elle lie l'identité du pod (son Kubernetes Service Account) directement à un Service Account GCP, sans aucune clé à gérer.
📋 Énoncé
Configurez Workload Identity pour qu'un pod puisse lire depuis Cloud Storage sans clé JSON.
🧭 Déroulement de l'exercice
Tâche 1 : Créer le cluster GKE avec Workload Identity
# Activer les APIs
gcloud services enable container.googleapis.com \
iam.googleapis.com \
storage.googleapis.com
PROJECT_ID=$(gcloud config get-value project)
REGION=europe-west9
# Créer le cluster GKE avec Workload Identity activé
gcloud container clusters create gke-workload-id \
--zone=${REGION}-a \
--num-nodes=2 \
--machine-type=e2-standard-2 \
--workload-pool="${PROJECT_ID}.svc.id.goog" \ # Active Workload Identity
--release-channel=stable
# Configurer kubectl
gcloud container clusters get-credentials gke-workload-id \
--zone=${REGION}-a
# Vérifier
kubectl get nodes
gcloud container clusters describe gke-workload-id \
--zone=${REGION}-a \
--format="value(workloadIdentityConfig.workloadPool)"
# → PROJECT_ID.svc.id.googIndice :
--workload-poolest le paramètre clé. Il identifie le pool d'identités Workload. Une fois activé, les pods peuvent "prouver" leur identité à GCP en échangeant leur token Kubernetes Service Account contre un token GCP.
Tâche 2 : Préparer le bucket et les Service Accounts
# Créer un bucket de test
BUCKET="${PROJECT_ID}-workload-id-test"
gcloud storage buckets create gs://$BUCKET --location=EU
echo "Fichier de test - accédé via Workload Identity" | \
gcloud storage cp - gs://$BUCKET/test.txt
# Créer un Google Service Account (GSA)
GSA_NAME="gsa-storage-reader"
gcloud iam service-accounts create $GSA_NAME \
--display-name="Service Account pour accès Cloud Storage"
GSA_EMAIL="${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com"
# Accorder les droits sur le bucket
gsutil iam ch serviceAccount:${GSA_EMAIL}:roles/storage.objectViewer gs://$BUCKET
echo "GSA créé : $GSA_EMAIL"Tâche 3 : Configurer la liaison Workload Identity
# Créer un namespace Kubernetes dédié
kubectl create namespace workload-id-demo
# Créer un Kubernetes Service Account (KSA)
kubectl create serviceaccount ksa-storage-reader \
--namespace workload-id-demo
# Étape clé : lier le KSA au GSA
# 1. Annoter le KSA avec l'email du GSA
kubectl annotate serviceaccount ksa-storage-reader \
--namespace workload-id-demo \
iam.gke.io/gcp-service-account=$GSA_EMAIL
# 2. Accorder au KSA le droit de "se faire passer pour" le GSA
gcloud iam service-accounts add-iam-policy-binding $GSA_EMAIL \
--role=roles/iam.workloadIdentityUser \
--member="serviceAccount:${PROJECT_ID}.svc.id.goog[workload-id-demo/ksa-storage-reader]"
# Vérifier la liaison
gcloud iam service-accounts get-iam-policy $GSA_EMAIL
# → Dans bindings : members: serviceAccount:PROJECT.svc.id.goog[ns/ksa]Tâche 4 : Déployer un pod qui utilise Workload Identity
cat > pod-test-workload-id.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
name: test-workload-id
namespace: workload-id-demo
spec:
serviceAccountName: ksa-storage-reader # Utiliser le KSA lié au GSA
containers:
- name: tester
image: google/cloud-sdk:slim
command: ["/bin/bash", "-c"]
args:
- |
echo "=== Test Workload Identity ==="
echo "Identité GCP du pod :"
gcloud auth list
echo ""
echo "=== Lecture depuis Cloud Storage ==="
gcloud storage cp gs://${BUCKET}/test.txt -
echo ""
echo "=== Test terminé avec succès ==="
sleep 3600
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
EOF
kubectl apply -f pod-test-workload-id.yaml
# Attendre que le pod soit Running
kubectl get pod test-workload-id -n workload-id-demo -wTâche 5 : Vérifier et comparer avec le cas sans Workload Identity
# Voir les logs du pod (preuve que ça fonctionne)
kubectl logs test-workload-id -n workload-id-demo
# Le pod peut lire le fichier S3 sans aucune clé JSON !
# Tester qu'un pod SANS le bon KSA ne peut PAS accéder
kubectl run pod-sans-acces \
--image=google/cloud-sdk:slim \
--namespace=workload-id-demo \
--restart=Never \
-- bash -c "gcloud storage cat gs://${BUCKET}/test.txt && sleep 60"
kubectl logs pod-sans-acces -n workload-id-demo
# → ERROR: ... Caller does not have storage.objects.get access
# Comparer les Service Accounts utilisés
kubectl get pod test-workload-id -n workload-id-demo \
-o jsonpath='{.spec.serviceAccountName}'
# → ksa-storage-reader (lié au GSA)
kubectl get pod pod-sans-acces -n workload-id-demo \
-o jsonpath='{.spec.serviceAccountName}'
# → default (pas de liaison Workload Identity)Tâche 6 : Nettoyer
kubectl delete namespace workload-id-demo
gcloud iam service-accounts delete $GSA_EMAIL --quiet
gcloud storage rm -r gs://$BUCKET
gcloud container clusters delete gke-workload-id --zone=${REGION}-a --quiet✅ Vérification du résultat
kubectl logs test-workload-idaffiche le contenu du fichier Cloud Storagegcloud auth listdans le pod montre l'identité du GSA (pas d'identité par défaut)- Le pod
pod-sans-accesreçoit une erreur de permission - Aucune clé JSON n'a été créée ni montée dans les pods
💡 À retenir
Pourquoi Workload Identity est supérieure aux clés JSON :
| Clé JSON | Workload Identity | |
|---|---|---|
| Rotation | ❌ Manuelle | ✅ Automatique |
| Expiration | ❌ Jamais (si pas configuré) | ✅ Tokens courts (1h) |
| Risque d'exfiltration | ❌ Élevé (fichier statique) | ✅ Faible (pas de secret) |
| Audit | Partiel | ✅ Complet dans Cloud Audit Logs |
| Complexité de setup | Simple mais risqué | Plus complexe mais sécurisé |
Le mécanisme en 3 étapes :
1. Pod présente son token KSA à l'API GKE Metadata Server
2. GKE Metadata Server vérifie la liaison KSA → GSA dans IAM
3. GCP échange le token KSA contre un token GSA à courte durée de vie✨ Solution Complète
# Les 3 opérations clés de Workload Identity
# 1. Activer lors de la création du cluster
gcloud container clusters create mon-cluster \
--workload-pool="${PROJECT_ID}.svc.id.goog"
# 2. Annoter le Kubernetes Service Account
kubectl annotate serviceaccount mon-ksa \
iam.gke.io/gcp-service-account=mon-gsa@${PROJECT_ID}.iam.gserviceaccount.com
# 3. Autoriser la liaison dans IAM
gcloud iam service-accounts add-iam-policy-binding mon-gsa@${PROJECT_ID}.iam.gserviceaccount.com \
--role=roles/iam.workloadIdentityUser \
--member="serviceAccount:${PROJECT_ID}.svc.id.goog[mon-namespace/mon-ksa]"