Le modèle de permissions BigQuery sépare l’accès aux données de l’accès au compute. Chacun doit être accordé à la portée appropriée.
Le principe fondamental : séparer les données du compute
Le pattern essentiel sépare deux préoccupations :
Au niveau du projet : les permissions de compute. Accordez bigquery.jobUser pour donner aux utilisateurs la capacité d’exécuter des requêtes. C’est la permission “pouvez-vous utiliser BigQuery du tout ?”. Elle leur permet d’exécuter des jobs mais ne détermine pas les données accessibles.
Au niveau du dataset : les permissions sur les données. Accordez bigquery.dataViewer ou bigquery.dataEditor pour contrôler les données que les utilisateurs peuvent voir et modifier. Cela détermine quelles tables sont accessibles.
Un utilisateur avec jobUser sur project-analytics et dataViewer sur project-warehouse.sales_data peut exécuter des requêtes dans project-analytics qui lisent depuis project-warehouse.sales_data. Il ne peut pas lire depuis des datasets pour lesquels il n’a pas dataViewer. Il ne peut pas exécuter de requêtes dans des projets pour lesquels il n’a pas jobUser.
Ce modèle à deux axes est ce qui fait fonctionner les patterns multi-projets : vous contrôlez où s’exécute le compute indépendamment de là où vivent les données.
Rôles prédéfinis à utiliser
Google fournit des rôles prédéfinis spécifiques à BigQuery. Utilisez-les à la place des rôles basiques (Owner, Editor, Viewer), qui préexistent à IAM et accordent des accès étendus et mal délimités.
| Rôle | Ce qu’il accorde | Portée typique |
|---|---|---|
bigquery.dataViewer | Lire les tables et vues | Dataset |
bigquery.dataEditor | Créer, mettre à jour, supprimer des tables | Dataset |
bigquery.jobUser | Exécuter des requêtes et jobs | Projet |
bigquery.user | Lister les datasets + exécuter des requêtes | Projet |
bigquery.admin | Contrôle total de BigQuery | Rarement nécessaire |
Le rôle bigquery.user est un superset de jobUser qui permet également aux utilisateurs de lister les datasets et d’en créer de nouveaux. Pour la plupart des utilisateurs analytics, jobUser avec des autorisations explicites dataViewer est plus approprié car il empêche la création accidentelle de datasets.
Stratégie des comptes de service
Créez des comptes de service dédiés pour chaque fonction de votre stack de données :
sa-dbt-dev@analytics-dev.iam.gserviceaccount.comsa-dbt-prod@analytics-prod.iam.gserviceaccount.comsa-fivetran@analytics-prod.iam.gserviceaccount.comsa-looker@analytics-prod.iam.gserviceaccount.comsa-airflow@analytics-prod.iam.gserviceaccount.comChaque compte de service obtient uniquement les permissions dont il a besoin :
- dbt production :
bigquery.dataEditor(pour créer des tables) +bigquery.jobUser(pour exécuter des requêtes) - Looker :
bigquery.dataVieweruniquement. Il ne doit jamais créer ni modifier des tables. - Fivetran/ingestion :
bigquery.dataEditorsur les datasets bruts uniquement, pas sur les modèles en aval. - Airflow/orchestrateur :
bigquery.jobUserpour déclencher des jobs, potentiellementdataViewerpour vérifier les dépendances.
Renouvelez les clés des comptes de service tous les 90 jours lorsque vous utilisez des fichiers de clés. Workload Identity Federation est préféré pour les charges hébergées sur GCP — Cloud Run ou GKE peuvent s’authentifier sans gestion de clés.
Pour le développement local, l’usurpation d’identité de compte de service (service account impersonation) est le pattern recommandé. Les développeurs s’authentifient via OAuth (leur propre identité) mais usurpent l’identité d’un compte de service avec les permissions appropriées. Cela évite la distribution de fichiers de clés tout en maintenant des pistes d’audit claires.
Ce qu’il faut éviter
Les rôles basiques (Owner, Editor, Viewer) accordent des permissions étendues sur tous les services GCP, pas seulement BigQuery. Un Editor peut modifier des buckets Cloud Storage, des instances Compute Engine et tout le reste. N’utilisez jamais ces rôles pour le contrôle d’accès BigQuery. Si quelqu’un a Editor sur un projet “parce qu’il avait besoin d’accéder à BigQuery”, c’est un problème de sécurité déguisé en choix de commodité.
bigquery.admin au niveau du projet donne un contrôle total sur toutes les ressources BigQuery d’un projet. La plupart des utilisateurs n’en ont pas besoin. La plupart des comptes de service certainement pas. Accordez l’accès admin uniquement aux quelques personnes qui administrent réellement les paramètres BigQuery — la gestion des réservations, la définition de quotas au niveau du projet, ou la configuration de l’audit logging.
L’accès trop large aux datasets se produit quand les équipes accordent dataViewer sur tous les datasets pour éviter les tickets de demande d’accès. Cela va à l’encontre du but de l’isolation au niveau du dataset. Si quelqu’un a besoin d’accéder à des données spécifiques, accordez l’accès à ce dataset spécifique. Oui, cela crée plus de liaisons IAM. C’est le but recherché.
Les autorisations admin étendues pour éviter les frictions d’accès. Cela crée des risques de sécurité, du bruit dans les audits et de la confusion. Quand des identifiants sont compromis, le rayon d’explosion est l’ensemble du projet. Ce pattern émerge généralement quand quelqu’un avait besoin d’accès rapidement et que les permissions n’ont jamais été nettoyées.
L’IAM en tant que code
La solution au désordre des permissions est de traiter l’IAM comme du code : définissez les permissions dans Terraform ou similaire, exigez une revue pour les modifications, et auditez régulièrement.
Commencez par identifier les principals avec trop de permissions :
- Tout utilisateur avec
bigquery.adminau niveau du projet (la plupart n’en ont pas besoin) - Les comptes de service avec
dataEditorsur des datasets qu’ils ne font que lire - Les rôles basiques (Owner/Editor/Viewer) accordés n’importe où
Réduisez les permissions au minimum requis. Cela peut provoquer des problèmes d’accès temporaires, mais mieux vaut les traiter intentionnellement que les découvrir lors d’un incident.
# Example: Terraform IAM for a dbt production service accountresource "google_bigquery_dataset_iam_member" "dbt_prod_editor" { for_each = toset(["base", "intermediate", "marts"]) dataset_id = each.value role = "roles/bigquery.dataEditor" member = "serviceAccount:sa-dbt-prod@analytics-prod.iam.gserviceaccount.com"}
resource "google_project_iam_member" "dbt_prod_job_user" { project = "analytics-prod" role = "roles/bigquery.jobUser" member = "serviceAccount:sa-dbt-prod@analytics-prod.iam.gserviceaccount.com"}Les permissions définies en code sont révisables, auditables et reproductibles.