Lección 2 — Le socle : organisation et identités

IAM au moindre privilège et comptes de service

6 min de lectura

Este contenido aún no está traducido. Se muestra la versión original.

IAM au moindre privilège et comptes de service

Les trois mots de l'IAM

IAM (Identity and Access Management) répond à « qui peut faire quoi sur quelle ressource ». Une liaison (binding) associe :

  • un membre : user:, group:, serviceAccount: (identité d'un programme) ;
  • un rôle : un paquet de permissions, par exemple roles/aiplatform.user qui permet d'appeler les modèles Vertex AI ;
  • une ressource : projet, bucket, clé KMS, service Cloud Run…

Le moindre privilège consiste à donner le plus petit rôle, sur la plus petite ressource, au plus petit groupe.

flowchart LR
  subgraph Mauvais["À éviter"]
    A1["Compute par défaut"] -->|"roles/editor sur le projet"| R1["Tout le projet"]
  end
  subgraph Bon["Le module"]
    A2["lab-archi-ia-app (dédié)"] -->|"roles/aiplatform.user (projet)"| R2["Appeler Gemini"]
    A2 -->|"roles/storage.objectViewer (1 bucket)"| R3["Lire les documents"]
    A2 -->|"roles/modelarmor.user"| R4["Filtrer prompts et réponses"]
  end
RôlePourquoi l'assistant en a besoinCe qu'il ne permet pas
roles/aiplatform.userappeler Gemini sur Vertex AIsupprimer des ressources Vertex, gérer IAM
roles/storage.objectViewer sur le bucketlire les documents de connaissanceslire les autres buckets, écrire
roles/modelarmor.userappeler Model Armormodifier les modèles Model Armor
roles/logging.logWriter, roles/monitoring.metricWriterécrire ses journaux et métriqueslire les journaux des autres
files/apis_iam.tf (extrait)
resource "google_service_account" "app" {
  account_id   = "${var.prefix}-app"
  display_name = "Assistant interne (Cloud Run)"
}

resource "google_project_iam_member" "app_roles" {
  for_each = toset([
    "roles/aiplatform.user",
    "roles/logging.logWriter",
    "roles/monitoring.metricWriter",
    "roles/modelarmor.user",
  ])
  project = var.project_id
  role    = each.value
  member  = google_service_account.app.member
}

# Lecture du seul bucket de connaissances, pas de tous les buckets du projet.
resource "google_storage_bucket_iam_member" "app_reads_kb" {
  bucket = google_storage_bucket.kb.name
  role   = "roles/storage.objectViewer"
  member = google_service_account.app.member
}

Pas de clés de comptes de service

Une clé de compte de service est un fichier JSON qui permet à n'importe qui le possédant d'agir comme ce compte, sans expiration par défaut. C'est la première cause de fuite d'identifiants cloud. Les alternatives :

Où tourne le codeIdentité sans clé
Cloud Run, Cloud Functions, GKEle compte de service attaché (ici template.service_account)
Poste d'un développeurgcloud auth application-default login (ses propres droits)
CI GitHub / GitLabWorkload Identity Federation (jeton OIDC échangé contre un jeton Google)

La contrainte d'organisation iam.disableServiceAccountKeyCreation interdit d'en créer.

Le compte Compute par défaut (PROJECT_NUMBER-compute@developer.gserviceaccount.com) a souvent roles/editor. Pourquoi est-ce dangereux pour une plateforme IA ?

Contrôler la posture en lecture seule

Le script check_posture.py appelle trois API en lecture (Service Usage, Resource Manager getIamPolicy, IAM) puis passe le tout à une fonction pure, evaluate, testable sans réseau.

files/check_posture.py (extrait)
for b in bindings:
    for m in b.get("members", []):
        if m in PUBLIC:                       # allUsers, allAuthenticatedUsers
            public.append(f"{m} -> {b['role']}")
        if m == default_sa:
            default_sa_roles.append(b["role"])
        if b["role"] in PRIMITIVE:            # roles/owner, roles/editor
            (sa_primitive if m.startswith("serviceAccount:") else humans_primitive).append(m)

Le rapport masque les adresses (user:al***@exemple.fr) : un rapport circule, il ne doit pas devenir une fuite de données personnelles.

pip install -r requirements.txt
pytest -q                                    # 4 tests, sans réseau
gcloud auth application-default login
python check_posture.py --project mon-projet # code de sortie 1 s'il y a un FAIL

Quelle ressource Terraform utiliser pour ajouter roles/aiplatform.user à un groupe sans risquer d'effacer les autres membres de ce rôle ?

Exercice

Ajoutez au script un contrôle : « aucun utilisateur individuel (user:) ne doit avoir roles/aiplatform.admin ; seuls des groupes le peuvent ». Écrivez aussi le test correspondant.

Voir la solution

Dans evaluate, après la boucle :

admins = [m for b in bindings if b["role"] == "roles/aiplatform.admin"
          for m in b.get("members", []) if m.startswith("user:")]
out.append(("WARN" if admins else "OK", "Admins Vertex AI nominatifs",
            ", ".join(mask(m) for m in admins) or "aucun (groupes uniquement)"))

Et dans test_check_posture.py :

def test_admin_vertex_nominatif():
    policy = {"bindings": [{"role": "roles/aiplatform.admin", "members": ["user:bob@exemple.fr"]}]}
    r = levels(evaluate(N, set(EXPECTED_APIS), policy, {}))
    assert r["Admins Vertex AI nominatifs"] == "WARN"

Résultat obtenu

Exécution réelle le 2026-10-15 sur un projet de test (identifiant masqué), en lecture seule :

$ pytest -q
....                                                                     [100%]
4 passed in 0.01s
$ python check_posture.py --project <projet-de-test>
[WARN] API attendues                        manquantes : cloudkms.googleapis.com, iap.googleapis.com, modelarmor.googleapis.com, accesscontextmanager.googleapis.com
[OK  ] Accès public (allUsers)              aucun
[FAIL] Compte Compute par défaut            a roles/editor
[OK  ] Comptes de service owner/editor      aucun
[OK  ] Humains owner/editor                 1 (cible : 3 au plus, idéalement via un groupe)
[OK  ] Clés de comptes de service           aucune clé utilisateur
[WARN] Audit accès aux données Vertex AI    manque DATA_READ, DATA_WRITE

7 contrôles : 1 FAIL, 2 WARN

Lecture : le projet de test a le défaut classique (compte Compute par défaut en roles/editor), et les journaux d'accès aux données de Vertex AI ne sont pas activés. Le module Terraform corrige le second point (leçon 3.2) ; le premier se corrige en retirant le rôle après avoir donné un compte dédié à chaque service.

Je sais faire

  • Choisir des rôles prédéfinis minimaux et les poser à la bonne granularité (projet ou ressource)
  • Expliquer pourquoi _member plutôt que _binding ou _policy
  • Remplacer une clé de compte de service par une identité sans clé
  • Lancer un contrôle de posture IAM en lecture seule et interpréter le rapport
Siguiente