Premiers pas avec Terraform et Firebase

Firebase commence à prendre en charge Terraform. Si vous faites partie d'une équipe qui souhaite automatiser et standardiser la création de projets Firebase avec des ressources spécifiques provisionnées et des services activés, Terraform avec Firebase peut être une bonne solution.

Le workflow de base pour utiliser Terraform avec Firebase comprend les étapes suivantes:

  • Créer et personnaliser un fichier de configuration Terraform (un fichier .tf) qui spécifie l'infrastructure que vous souhaitez provisionner (c'est-à-dire les ressources que vous souhaitez provisionner et les services que vous souhaitez activer).

  • À l'aide de commandes gcloud CLI qui interagissent avec Terraform pour provisionner l'infrastructure spécifiée dans le fichier .tf.

Que pouvez-vous faire avec Terraform et Firebase ?

L'exemple de workflow généralisé dans ce guide consiste à créer un projet Firebase avec une application Android. Mais vous pouvez faire bien plus avec Terraform, par exemple:

  • Supprimez et modifiez l'infrastructure existante à l'aide de Terraform.

  • Gérer la configuration et les tâches spécifiques au produit à l'aide de Terraform, par exemple:

    • Activer les fournisseurs de connexion Firebase Authentication.
    • Créer des buckets Cloud Storage ou des instances de base de données, et déployer Firebase Security Rules pour eux.

Vous pouvez utiliser des fichiers de configuration et des commandes Terraform standards pour effectuer toutes ces tâches. Pour vous aider, nous vous avons fourni des exemples de fichiers de configuration Terraform pour plusieurs cas d'utilisation courants.



Workflow généralisé pour utiliser Terraform avec Firebase

Conditions préalables

Ce guide est une introduction à l'utilisation de Terraform avec Firebase. Il suppose donc que vous avez des connaissances de base sur Terraform. Assurez-vous d'avoir rempli les conditions préalables suivantes avant de commencer ce workflow.

  • Installez Terraform et familiarisez-vous avec Terraform à l'aide de ses tutoriels officiels.

  • Installez Google Cloud CLI (gcloud CLI). Connectez-vous à l'aide d'un compte utilisateur ou d'un compte de service.

    • Si vous utilisez un compte utilisateur, vous devez avoir accepté les conditions d'utilisation de Firebase. Vous avez accepté les conditions d'utilisation de Firebase si vous pouvez afficher un projet Firebase dans la console Firebase.
    • Pour que Terraform puisse effectuer certaines actions (par exemple, créer des projets), les conditions suivantes doivent être remplies :
      • L'utilisateur ou le compte de service doit disposer des droits d'accès IAM applicables pour ces actions.
      • Si l'utilisateur ou le compte de service fait partie d'une organisation Google Cloud, les règles de l'organisation doivent autoriser le compte à effectuer ces actions.


Étape 1:Créez et personnalisez un fichier de configuration Terraform

Un fichier de configuration Terraform nécessite deux sections principales (décrites en détail ci-dessous):

Configurer votre provider

Une configuration provider est requise, quels que soient les produits ou services Firebase concernés.

  1. Créez un fichier de configuration Terraform (comme un fichier main.tf) dans votre répertoire local.

    Dans ce guide, vous utiliserez ce fichier de configuration pour spécifier à la fois la configuration provider et toute l'infrastructure que vous souhaitez que Terraform crée. Notez toutefois que vous avez la possibilité d'inclure la configuration du fournisseur.

    Vous disposez des options suivantes pour inclure une configuration provider au reste de votre configuration Terraform:

    • Option 1:incluez-le en haut d'un seul fichier de configuration .tf Terraform (comme indiqué dans ce guide).

      • Utilisez cette option si vous débutez avec Terraform ou si vous essayez simplement Terraform avec Firebase.
    • Option 2:incluez-le dans un fichier .tf distinct (comme un fichier provider.tf), en dehors du fichier .tf dans lequel vous spécifiez l'infrastructure à créer (comme un fichier main.tf).

      • Utilisez cette option si vous faites partie d'une équipe plus importante qui doit standardiser la configuration.
      • Lorsque vous exécutez des commandes Terraform, le fichier provider.tf et le fichier main.tf doivent se trouver dans le même répertoire.

  2. Incluez la configuration provider suivante en haut du fichier main.tf.

    Vous devez utiliser le fournisseur google-beta, car il s'agit d'une version bêta de l'utilisation de Firebase avec Terraform. Soyez prudent lorsque vous l'utilisez en production.

    # Terraform configuration to set up providers by version.
    terraform {
      required_providers {
        google-beta = {
          source  = "hashicorp/google-beta"
          version = "~> 5.0"
        }
      }
    }
    
    # Configures the provider to use the resource block's specified project for quota checks.
    provider "google-beta" {
      user_project_override = true
    }
    
    # Configures the provider to not use the resource block's specified project for quota checks.
    # This provider should only be used during project creation and initializing services.
    provider "google-beta" {
      alias = "no_user_project_override"
      user_project_override = false
    }

    Découvrez les différents types d'attributs liés au projet (y compris ce que ce guide appelle le "projet de vérification des quotas") lorsque vous utilisez Terraform avec Firebase.

  3. Passez à la section suivante pour finaliser votre fichier de configuration et spécifier l'infrastructure à créer.

Spécifier l'infrastructure à créer à l'aide de blocs resource

Dans votre fichier de configuration Terraform (pour ce guide, votre fichier main.tf), vous devez spécifier toute l'infrastructure que vous souhaitez que Terraform crée (c'est-à-dire toutes les ressources que vous souhaitez provisionner et tous les services que vous souhaitez activer). Dans ce guide, vous trouverez la liste complète de toutes les ressources Firebase compatibles avec Terraform.

  1. Ouvrez votre fichier main.tf.

  2. Dans la configuration provider, incluez la configuration suivante des blocs resource.

    Cet exemple de base crée un projet Firebase, puis une application Android Firebase dans ce projet.

    # Terraform configuration to set up providers by version.
    ...
    
    # Configures the provider to use the resource block's specified project for quota checks.
    ...
    
    # Configures the provider to not use the resource block's specified project for quota checks.
    ...
    
    # Creates a new Google Cloud project.
    resource "google_project" "default" {
      provider   = google-beta.no_user_project_override
    
      name       = "Project Display Name"
      project_id = "project-id-for-new-project"
      # Required for any service that requires the Blaze pricing plan
      # (like Firebase Authentication with GCIP)
      billing_account = "000000-000000-000000"
    
      # Required for the project to display in any list of Firebase projects.
      labels = {
        "firebase" = "enabled"
      }
    }
    
    # Enables required APIs.
    resource "google_project_service" "default" {
      provider = google-beta.no_user_project_override
      project  = google_project.default.project_id
      for_each = toset([
        "cloudbilling.googleapis.com",
        "cloudresourcemanager.googleapis.com",
        "firebase.googleapis.com",
        # Enabling the ServiceUsage API allows the new project to be quota checked from now on.
        "serviceusage.googleapis.com",
      ])
      service = each.key
    
      # Don't disable the service if the resource block is removed by accident.
      disable_on_destroy = false
    }
    
    # Enables Firebase services for the new project created above.
    resource "google_firebase_project" "default" {
      provider = google-beta
      project  = google_project.default.project_id
    
      # Waits for the required APIs to be enabled.
      depends_on = [
        google_project_service.default
      ]
    }
    
    # Creates a Firebase Android App in the new project created above.
    resource "google_firebase_android_app" "default" {
      provider = google-beta
    
      project      = google_project.default.project_id
      display_name = "My Awesome Android app"
      package_name = "awesome.package.name"
    
      # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
      depends_on = [
        google_firebase_project.default,
      ]
    }

Si vous ne connaissez pas l'infrastructure des projets et des applications en tant que ressources, consultez la documentation suivante:

# Terraform configuration to set up providers by version.
...

# Configures the provider to use the resource block's specified project for quota checks.
...

# Configures the provider to not use the resource block's specified project for quota checks.
...

# Creates a new Google Cloud project.
resource "google_project" "default" {
  # Use the provider that enables the setup of quota checks for a new project
  provider   = google-beta.no_user_project_override

  name            = "Project Display Name"        // learn more about the project name
  project_id      = "project-id-for-new-project"  // learn more about the project ID
  # Required for any service that requires the Blaze pricing plan
  # (like Firebase Authentication with GCIP)
  billing_account = "000000-000000-000000"

  # Required for the project to display in any list of Firebase projects.
  labels = {
    "firebase" = "enabled"  // learn more about the Firebase-enabled label
  }
}

# Enables required APIs.
resource "google_project_service" "default" {
  # Use the provider without quota checks for enabling APIS
  provider = google-beta.no_user_project_override
  project  = google_project.default.project_id
  for_each = toset([
    "cloudbilling.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "firebase.googleapis.com",
    # Enabling the ServiceUsage API allows the new project to be quota checked from now on.
    "serviceusage.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created above.
# This action essentially "creates a Firebase project" and allows the project to use
# Firebase services (like Firebase Authentication) and
# Firebase tooling (like the Firebase console).
# Learn more about the relationship between Firebase projects and Google Cloud.
resource "google_firebase_project" "default" {
  # Use the provider that performs quota checks from now on
  provider = google-beta

  project  = google_project.default.project_id

  # Waits for the required APIs to be enabled.
  depends_on = [
    google_project_service.default
  ]
}

# Creates a Firebase Android App in the new project created above.
# Learn more about the relationship between Firebase Apps and Firebase projects.
resource "google_firebase_android_app" "default" {
  provider = google-beta

  project      = google_project.default.project_id
  display_name = "My Awesome Android app"  # learn more about an app's display name
  package_name = "awesome.package.name"    # learn more about an app's package name

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.default,
  ]
}


Étape 2:Exécutez des commandes Terraform pour créer l'infrastructure spécifiée

Pour provisionner les ressources et activer les services spécifiés dans votre fichier main.tf, exécutez les commandes suivantes à partir du même répertoire que votre fichier main.tf. Pour en savoir plus sur ces commandes, consultez la documentation Terraform.

  1. Si vous exécutez des commandes Terraform dans le répertoire pour la première fois, vous devez initialiser le répertoire de configuration et installer le fournisseur Terraform Google. Pour ce faire, exécutez la commande suivante:

    terraform init
  2. Créez l'infrastructure spécifiée dans votre fichier main.tf en exécutant la commande suivante:

    terraform apply
  3. Vérifiez que tout a été provisionné ou activé comme prévu:

    • Option 1:Affichez la configuration dans votre terminal en exécutant la commande suivante:

      terraform show
    • Option 2:afficher votre projet Firebase dans la console Firebase.



Ressources Firebase compatibles avec Terraform

Les ressources Firebase et Google suivantes sont compatibles avec Terraform. Nous ajoutons de nouvelles ressources en permanence. Par conséquent, si vous ne voyez pas la ressource que vous souhaitez gérer avec Terraform, vérifiez bientôt si elle est disponible ou demandez-la en soumettant un problème dans le dépôt GitHub.


Gestion des projets et des applications Firebase

  • google_firebase_project : activez les services Firebase sur un projet Google Cloud existant.

  • Applications Firebase


Firebase Authentication

  • google_identity_platform_config : activez Google Cloud Identity Platform (GCIP), qui est le backend de Firebase Authentication, et fournissez des paramètres d'authentification au niveau du projet.

    • Pour configurer Firebase Authentication via Terraform, vous devez activer GCIP. Veillez à consulter l'exemple de fichier .tf pour savoir comment configurer Firebase Authentication.

    • Le projet dans lequel Terraform activera le GCIP et/ou Firebase Authentication doit être associé au forfait Blaze (c'est-à-dire que le projet doit disposer d'un compte Cloud Billing associé). Vous pouvez le faire de manière programmatique en définissant l'attribut billing_account dans la ressource google_project.

    • Cette ressource permet également d'effectuer davantage de configurations, telles que les méthodes de connexion locales (anonyme, e-mail/mot de passe et authentification par téléphone, par exemple), ainsi que les fonctions de blocage et les domaines autorisés.

  • google_identity_platform_default_supported_idp_config : configurez des fournisseurs d'identité fédérés courants, tels que Google, Facebook ou Apple.

  • identity_platform_oauth_idp_config : configurez des sources de fournisseur d'identité (IdP) OAuth arbitraires.

  • google_identity_platform_inbound_saml_config : configure les intégrations SAML.

Non compatible:

  • Configurer l'authentification multifacteur (MFA) via Terraform

Firebase Data Connect


Firebase Realtime Database

Non compatible:

  • Déployer des Firebase Realtime Database Security Rules via Terraform (découvrez comment déployer ces Rules à l'aide d'autres outils, y compris d'options programmatiques)

Cloud Firestore

  • google_firestore_database : créez une instance Cloud Firestore.

  • google_firestore_index : active les requêtes efficaces pour Cloud Firestore.

  • google_firestore_document : insère un document spécifique dans une collection pour une instance Cloud Firestore

    Important:N'utilisez pas de données réelles d'utilisateur final ni de données de production dans ce document de référence.


Cloud Storage for Firebase

  • google_firebase_storage_bucket : permet d'accéder à un bucket Cloud Storage existant pour les SDK Firebase, l'authentification et Firebase Security Rules.

  • google_storage_bucket_object : ajoutez un objet à un bucket Cloud Storage.

    Important:N'utilisez pas de données réelles d'utilisateur final ou de production dans ce fichier.


Firebase Security Rules (pour Cloud Firestore et Cloud Storage)

Notez que Firebase Realtime Database utilise un système de provisionnement différent pour ses Firebase Security Rules.

  • google_firebaserules_ruleset : définit les Firebase Security Rules qui s'appliquent à une instance Cloud Firestore ou à un bucket Cloud Storage.

  • google_firebaserules_release : déployez des ensembles de règles spécifiques sur une instance Cloud Firestore ou un bucket Cloud Storage.


Firebase App Check


Firebase Extensions



Exemples de fichiers de configuration Terraform pour des cas d'utilisation courants

Cette configuration crée un projet Google Cloud, l'associe à un compte Cloud Billing (le forfait Blaze est requis pour Firebase Authentication avec GCIP), active les services Firebase pour le projet, configure Firebase Authentication avec GCIP et enregistre trois types d'applications différents avec le projet.

Notez que l'activation de GCIP est nécessaire pour configurer Firebase Authentication via Terraform.

# Creates a new Google Cloud project.
resource "google_project" "auth" {
  provider  = google-beta.no_user_project_override
  folder_id = "folder-id-for-new-project"
  name            = "Project Display Name"
  project_id      = "project-id-for-new-project"

  # Associates the project with a Cloud Billing account
  # (required for Firebase Authentication with GCIP).
  billing_account = "000000-000000-000000"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "auth" {
  provider = google-beta.no_user_project_override
  project  = google_project.auth.project_id
  for_each = toset([
    "cloudbilling.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "serviceusage.googleapis.com",
    "identitytoolkit.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created above.
resource "google_firebase_project" "auth" {
  provider = google-beta
  project  = google_project.auth.project_id

  depends_on = [
    google_project_service.auth,
  ]
}

# Creates an Identity Platform config.
# Also enables Firebase Authentication with Identity Platform in the project if not.
resource "google_identity_platform_config" "auth" {
  provider = google-beta
  project  = google_project.auth.project_id

  # Auto-deletes anonymous users
  autodelete_anonymous_users = true

  # Configures local sign-in methods, like anonymous, email/password, and phone authentication.
  sign_in {
    allow_duplicate_emails = true

    anonymous {
      enabled = true
    }

    email {
      enabled = true
      password_required = false
    }

    phone_number {
      enabled = true
      test_phone_numbers = {
        "+11231231234" = "000000"
      }
    }
  }

  # Sets an SMS region policy.
  sms_region_config {
    allowlist_only {
      allowed_regions = [
        "US",
        "CA",
      ]
    }
  }

  # Configures blocking functions.
  blocking_functions {
    triggers {
      event_type = "beforeSignIn"
      function_uri = "https://us-east1-${google_project.auth.project_id}.cloudfunctions.net/before-sign-in"
    }
    forward_inbound_credentials {
      refresh_token = true
      access_token = true
      id_token = true
    }
  }

  # Configures a temporary quota for new signups for anonymous, email/password, and phone number.
  quota {
    sign_up_quota_config {
      quota = 1000
      start_time = ""
      quota_duration = "7200s"
    }
  }

  # Configures authorized domains.
  authorized_domains = [
    "localhost",
    "${google_project.auth.project_id}.firebaseapp.com",
    "${google_project.auth.project_id}.web.app",
  ]

  # Wait for identitytoolkit.googleapis.com to be enabled before initializing Authentication.
  depends_on = [
    google_project_service.auth,
  ]
}

# Creates a Firebase Android App in the new project created above.
resource "google_firebase_android_app" "auth" {
  provider     = google-beta
  project      = google_project.auth.project_id
  display_name = "My Android app"
  package_name = "android.package.name"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.auth,
  ]
}

# Creates a Firebase Apple-platforms App in the new project created above.
resource "google_firebase_apple_app" "auth" {
  provider     = google-beta
  project      = google_project.auth.project_id
  display_name = "My Apple app"
  bundle_id    = "apple.app.12345"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.auth,
  ]
}

# Creates a Firebase Web App in the new project created above.
resource "google_firebase_web_app" "auth" {
  provider     = google-beta
  project      = google_project.auth.project_id
  display_name = "My Web app"

  # The other App types (Android and Apple) use "DELETE" by default.
  # Web apps don't use "DELETE" by default due to backward-compatibility.
  deletion_policy = "DELETE"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.auth,
  ]
}

Cette configuration crée un projet Google Cloud, active les services Firebase pour le projet et provisionne un service Data Connect.

# Creates a new Google Cloud project.
resource "google_project" "dataconnect" {
  provider   = google-beta.no_user_project_override
  folder_id  = "folder-id-for-new-project"
  name       = "Project Display Name"
  project_id = "project-id-for-new-project"

  # Associates the project with a Cloud Billing account
  # (required to use Firebase Data Connect).
  billing_account = "000000-000000-000000"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "services" {
  provider = google-beta.no_user_project_override
  project  = google_project.dataconnect.project_id
  for_each = toset([
    "serviceusage.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "firebasedataconnect.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created earlier.
resource "google_firebase_project" "dataconnect" {
  provider = google-beta
  project  = google_project.dataconnect.project_id

  depends_on = [google_project_service.services]
}

# Create a Firebase Data Connect service
resource "google_firebase_data_connect_service" "dataconnect-default" {
  project         = google_firebase_project.dataconnect.project
  location        = "name-of-region-for-service"
  service_id      = "${google_firebase_project.dataconnect.project}-default-fdc"
  deletion_policy = "DEFAULT"
}

Cette configuration crée un projet Google Cloud, active les services Firebase pour le projet, provisionne l'instance Realtime Database par défaut du projet et enregistre trois types d'applications différents avec le projet.

# Creates a new Google Cloud project.
resource "google_project" "rtdb" {
  provider   = google-beta.no_user_project_override
  folder_id  = "folder-id-for-new-project"
  name       = "Project Display Name"
  project_id = "project-id-for-new-project"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "rtdb" {
  provider = google-beta.no_user_project_override
  project  = google_project.rtdb.project_id
  for_each = toset([
    "serviceusage.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "firebasedatabase.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created above.
resource "google_firebase_project" "rtdb" {
  provider = google-beta
  project  = google_project.rtdb.project_id
}

# Provisions the default Realtime Database default instance.
resource "google_firebase_database_instance" "database" {
  provider    = google-beta
  project     = google_project.rtdb.project_id
  # See available locations: https://firebase.google.com/docs/database/locations
  region      = "name-of-region"
  # This value will become the first segment of the database's URL.
  instance_id = "${google_project.rtdb.project_id}-default-rtdb"
  type        = "DEFAULT_DATABASE"

  # Wait for Firebase to be enabled in the Google Cloud project before initializing Realtime Database.
  depends_on = [
    google_firebase_project.rtdb,
  ]
}

# Creates a Firebase Android App in the new project created above.
resource "google_firebase_android_app" "rtdb" {
  provider     = google-beta
  project      = google_project.rtdb.project_id
  display_name = "My Android app"
  package_name = "android.package.name"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.rtdb,
  ]
}

# Creates a Firebase Apple-platforms App in the new project created above.
resource "google_firebase_apple_app" "rtdb" {
  provider     = google-beta
  project      = google_project.rtdb.project_id
  display_name = "My Apple app"
  bundle_id    = "apple.app.12345"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.rtdb,
  ]
}

# Creates a Firebase Web App in the new project created above.
resource "google_firebase_web_app" "rtdb" {
  provider     = google-beta
  project      = google_project.rtdb.project_id
  display_name = "My Web app"

  # The other App types (Android and Apple) use "DELETE" by default.
  # Web apps don't use "DELETE" by default due to backward-compatibility.
  deletion_policy = "DELETE"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.rtdb,
  ]
}

Cette configuration crée un projet Google Cloud, l'associe à un compte Cloud Billing (le forfait Blaze est requis pour plusieurs instances Realtime Database), active les services Firebase pour le projet, provisionne plusieurs instances Realtime Database (y compris l'instance Realtime Database par défaut du projet) et enregistre trois types d'applications différents avec le projet.

# Creates a new Google Cloud project.
resource "google_project" "rtdb-multi" {
  provider   = google-beta.no_user_project_override
  folder_id  = "folder-id-for-new-project"
  name       = "Project Display Name"
  project_id = "project-id-for-new-project"

  # Associate the project with a Cloud Billing account
  # (required for multiple Realtime Database instances).
  billing_account = "000000-000000-000000"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "rtdb-multi" {
  provider = google-beta.no_user_project_override
  project  = google_project.rtdb-multi.project_id
  for_each = toset([
    "cloudbilling.googleapis.com",
    "serviceusage.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "firebasedatabase.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created above.
resource "google_firebase_project" "rtdb-multi" {
  provider = google-beta
  project  = google_project.rtdb-multi.project_id
}

# Provisions the default Realtime Database default instance.
resource "google_firebase_database_instance" "database-default" {
  provider    = google-beta
  project     = google_project.rtdb-multi.project_id
  # See available locations: https://firebase.google.com/docs/database/locations
  region      = "name-of-region"
  # This value will become the first segment of the database's URL.
  instance_id = "${google_project.rtdb-multi.project_id}-default-rtdb"
  type        = "DEFAULT_DATABASE"

  # Wait for Firebase to be enabled in the Google Cloud project before initializing Realtime Database.
  depends_on = [
    google_firebase_project.rtdb-multi,
  ]
}

# Provisions an additional Realtime Database instance.
resource "google_firebase_database_instance" "database-additional" {
  provider    = google-beta
  project     = google_project.rtdb-multi.project_id
  # See available locations: https://firebase.google.com/docs/projects/locations#rtdb-locations
  # This location doesn't need to be the same as the default database instance.
  region      = "name-of-region"
  # This value will become the first segment of the database's URL.
  instance_id = "name-of-additional-database-instance"
  type        = "USER_DATABASE"

  # Wait for Firebase to be enabled in the Google Cloud project before initializing Realtime Database.
  depends_on = [
    google_firebase_project.rtdb-multi,
  ]
}

# Creates a Firebase Android App in the new project created above.
resource "google_firebase_android_app" "rtdb-multi" {
  provider     = google-beta
  project      = google_project.rtdb-multi.project_id
  display_name = "My Android app"
  package_name = "android.package.name"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.rtdb-multi,
  ]
}

# Creates a Firebase Apple-platforms App in the new project created above.
resource "google_firebase_apple_app" "rtdb-multi" {
  provider     = google-beta
  project      = google_project.rtdb-multi.project_id
  display_name = "My Apple app"
  bundle_id    = "apple.app.12345"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.rtdb-multi,
  ]
}

# Creates a Firebase Web App in the new project created above.
resource "google_firebase_web_app" "rtdb-multi" {
  provider     = google-beta
  project      = google_project.rtdb-multi.project_id
  display_name = "My Web app"

  # The other App types (Android and Apple) use "DELETE" by default.
  # Web apps don't use "DELETE" by default due to backward-compatibility.
  deletion_policy = "DELETE"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.rtdb-multi,
  ]
}

Cette configuration crée un projet Google Cloud, active les services Firebase pour le projet, provisionne l'instance Cloud Firestore par défaut du projet et enregistre trois types d'applications différents avec le projet.

Il provisionne également Firebase Security Rules pour l'instance Cloud Firestore par défaut, crée un index Cloud Firestore et ajoute un document Cloud Firestore avec des données de départ.

# Creates a new Google Cloud project.
resource "google_project" "firestore" {
  provider   = google-beta.no_user_project_override
  folder_id  = "folder-id-for-new-project"
  name       = "Project Display Name"
  project_id = "project-id-for-new-project"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "firestore" {
  provider = google-beta.no_user_project_override
  project  = google_project.firestore.project_id
  for_each = toset([
    "cloudresourcemanager.googleapis.com",
    "serviceusage.googleapis.com",
    "firestore.googleapis.com",
    "firebaserules.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created above.
resource "google_firebase_project" "firestore" {
  provider = google-beta
  project  = google_project.firestore.project_id
}

# Provisions the Firestore database instance.
resource "google_firestore_database" "firestore" {
  provider                    = google-beta
  project                     = google_project.firestore.project_id
  name                        = "(default)"
  # See available locations: https://firebase.google.com/docs/firestore/locations
  location_id                 = "name-of-region"
  # "FIRESTORE_NATIVE" is required to use Firestore with Firebase SDKs, authentication, and Firebase Security Rules.
  type                        = "FIRESTORE_NATIVE"
  concurrency_mode            = "OPTIMISTIC"

  # Wait for Firebase to be enabled in the Google Cloud project before initializing Firestore.
  depends_on = [
    google_firebase_project.firestore,
  ]
}

# Creates a ruleset of Firestore Security Rules from a local file.
resource "google_firebaserules_ruleset" "firestore" {
  provider = google-beta
  project  = google_project.firestore.project_id
  source {
    files {
      name = "firestore.rules"
      # Write security rules in a local file named "firestore.rules".
      # Learn more: https://firebase.google.com/docs/firestore/security/get-started
      content = file("firestore.rules")
    }
  }

  # Wait for Firestore to be provisioned before creating this ruleset.
  depends_on = [
    google_firestore_database.firestore,
  ]
}

# Releases the ruleset for the Firestore instance.
resource "google_firebaserules_release" "firestore" {
  provider     = google-beta
  name         = "cloud.firestore"  # must be cloud.firestore
  ruleset_name = google_firebaserules_ruleset.firestore.name
  project      = google_project.firestore.project_id

  # Wait for Firestore to be provisioned before releasing the ruleset.
  depends_on = [
    google_firestore_database.firestore,
  ]
}

# Adds a new Firestore index.
resource "google_firestore_index" "indexes" {
  provider = google-beta
  project  = google_project.firestore.project_id

  collection  = "quiz"
  query_scope = "COLLECTION"

  fields {
    field_path = "question"
    order      = "ASCENDING"
  }

  fields {
    field_path = "answer"
    order      = "ASCENDING"
  }

  # Wait for Firestore to be provisioned before adding this index.
  depends_on = [
    google_firestore_database.firestore,
  ]
}

# Adds a new Firestore document with seed data.
# Don't use real end-user or production data in this seed document.
resource "google_firestore_document" "doc" {
  provider    = google-beta
  project     = google_project.firestore.project_id
  collection  = "quiz"
  document_id = "question-1"
  fields      = "{\"question\":{\"stringValue\":\"Favorite Database\"},\"answer\":{\"stringValue\":\"Firestore\"}}"

  # Wait for Firestore to be provisioned before adding this document.
  depends_on = [
    google_firestore_database.firestore,
  ]
}

# Creates a Firebase Android App in the new project created above.
resource "google_firebase_android_app" "firestore" {
  provider     = google-beta
  project      = google_project.firestore.project_id
  display_name = "My Android app"
  package_name = "android.package.name"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.firestore,
  ]
}

# Creates a Firebase Apple-platforms App in the new project created above.
resource "google_firebase_apple_app" "firestore" {
  provider     = google-beta
  project      = google_project.firestore.project_id
  display_name = "My Apple app"
  bundle_id    = "apple.app.12345"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.firestore,
  ]
}

# Creates a Firebase Web App in the new project created above.
resource "google_firebase_web_app" "firestore" {
  provider     = google-beta
  project      = google_project.firestore.project_id
  display_name = "My Web app"

  # The other App types (Android and Apple) use "DELETE" by default.
  # Web apps don't use "DELETE" by default due to backward-compatibility.
  deletion_policy = "DELETE"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.firestore,
  ]
}

Il s'agit du jeu de règles de Cloud Firestore Security Rules qui doit se trouver dans un fichier local nommé firestore.rules.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /some_collection/{document} {
      allow read, create, update: if request.auth != null;
    }
  }
}

Cette configuration crée un projet Google Cloud, l'associe à un compte Cloud Billing (le forfait Blaze est requis pour les buckets supplémentaires), active les services Firebase pour le projet, provisionne des buckets Cloud Storage supplémentaires autres que par défaut et enregistre trois types d'applications différents avec le projet.

Il provisionne également Firebase Security Rules pour chaque bucket Cloud Storage et importe un fichier dans l'un des buckets Cloud Storage.

# Creates a new Google Cloud project.
resource "google_project" "storage-multi" {
  provider  = google-beta.no_user_project_override
  folder_id = "folder-id-for-new-project"
  name            = "Project Display Name"
  project_id      = "project-id-for-new-project"

  # Associates the project with a Cloud Billing account
  # (required for multiple Cloud Storage buckets).
  billing_account = "000000-000000-000000"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "storage-multi" {
  provider = google-beta.no_user_project_override
  project  = google_project.storage-multi.project_id
  for_each = toset([
    "cloudbilling.googleapis.com",
    "serviceusage.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "firebaserules.googleapis.com",
    "firebasestorage.googleapis.com",
    "storage.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created above.
resource "google_firebase_project" "storage-multi" {
  provider = google-beta
  project  = google_project.storage-multi.project_id
}

# Provisions a Cloud Storage bucket.
resource "google_storage_bucket" "bucket-1" {
  provider = google-beta
  project  = google_project.storage-multi.project_id
  name     = "name-of-storage-bucket"
  # See available locations: https://cloud.google.com/storage/docs/locations#available-locations
  location = "name-of-region-for-bucket"
}

# Provisions an additional Cloud Storage bucket.
resource "google_storage_bucket" "bucket-2" {
  provider = google-beta
  project  = google_project.storage-multi.project_id
  name     = "name-of-additional-storage-bucket"
  # See available locations: https://cloud.google.com/storage/docs/locations#available-locations
  # This location does not need to be the same as the existing Storage bucket.
  location = "name-of-region-for-additional-bucket"
}

# Makes the first Storage bucket accessible for Firebase SDKs, authentication, and Firebase Security Rules.
resource "google_firebase_storage_bucket" "bucket-1" {
  provider  = google-beta
  project   = google_project.storage-multi.project_id
  bucket_id = google_storage_bucket.bucket-1.name
}

# Makes the additional Storage bucket accessible for Firebase SDKs, authentication, and Firebase Security Rules.
resource "google_firebase_storage_bucket" "bucket-2" {
  provider  = google-beta
  project   = google_project.storage-multi.project_id
  bucket_id = google_storage_bucket.bucket-2.name
}

# Creates a ruleset of Firebase Security Rules from a local file.
resource "google_firebaserules_ruleset" "storage-multi" {
  provider = google-beta
  project  = google_project.storage-multi.project_id
  source {
    files {
      # Write security rules in a local file named "storage.rules"
      # Learn more: https://firebase.google.com/docs/storage/security/get-started
      name    = "storage.rules"
      content = file("storage.rules")
    }
  }

  # Wait for the Storage buckets to be provisioned before creating this ruleset.
  depends_on = [
    google_firebase_project.storage-multi,
  ]
}

# Releases the ruleset to the first Storage bucket.
resource "google_firebaserules_release" "bucket-1" {
  provider     = google-beta
  name         = "firebase.storage/${google_storage_bucket.bucket-1.name}"
  ruleset_name = "projects/${google_project.storage-multi.project_id}/rulesets/${google_firebaserules_ruleset.storage-multi.name}"
  project      = google_project.storage-multi.project_id
}

# Releases the ruleset to the additional Storage bucket.
resource "google_firebaserules_release" "bucket-2" {
  provider     = google-beta
  name         = "firebase.storage/${google_storage_bucket.bucket-2.name}"
  ruleset_name = "projects/${google_project.storage-multi.project_id}/rulesets/${google_firebaserules_ruleset.storage-multi.name}"
  project      = google_project.storage-multi.project_id
}

# Uploads a new file to the first Storage bucket.
# Do not use real end-user or production data in this file.
resource "google_storage_bucket_object" "cat-picture-multi" {
  provider = google-beta
  name     = "cat.png"
  source   = "path/to/cat.png"
  bucket   = google_storage_bucket.bucket-1.name
}

# Creates a Firebase Android App in the new project created above.
resource "google_firebase_android_app" "storage-multi" {
  provider     = google-beta
  project      = google_project.storage-multi.project_id
  display_name = "My Android app"
  package_name = "android.package.name"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.storage-multi,
  ]
}

# Creates a Firebase Apple-platforms App in the new project created above.
resource "google_firebase_apple_app" "storage-multi" {
  provider     = google-beta
  project      = google_project.storage-multi.project_id
  display_name = "My Apple app"
  bundle_id    = "apple.app.12345"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.storage-multi,
  ]
}

# Creates a Firebase Web App in the new project created above.
resource "google_firebase_web_app" "storage-multi" {
  provider     = google-beta
  project      = google_project.storage-multi.project_id
  display_name = "My Web app"

  # Wait for Firebase to be enabled in the Google Cloud project before creating this App.
  depends_on = [
    google_firebase_project.storage-multi,
  ]
}

Il s'agit du jeu de règles de Cloud Storage Security Rules qui doit se trouver dans un fichier local nommé storage.rules.

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /some_folder/{fileName} {
      allow read, write: if request.auth != null;
    }
  }
}

Cette configuration crée un projet Google Cloud, active les services Firebase pour le projet, et configure et active l'application de Firebase App Check pour Cloud Firestore afin qu'il ne soit accessible que depuis votre application Android.

# Creates a new Google Cloud project.
resource "google_project" "appcheck" {
  provider   = google-beta.no_user_project_override
  folder_id  = "folder-id-for-new-project"
  name       = "Project Display Name"
  project_id = "project-id-for-new-project"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "services" {
  provider = google-beta.no_user_project_override
  project  = google_project.appcheck.project_id
  for_each = toset([
    "cloudresourcemanager.googleapis.com",
    "firebase.googleapis.com",
    "firebaseappcheck.googleapis.com",
    "firestore.googleapis.com",
    "serviceusage.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created earlier.
resource "google_firebase_project" "appcheck" {
  provider = google-beta
  project  = google_project.appcheck.project_id

  depends_on = [google_project_service.services]
}

# Provisions the Firestore database instance.
resource "google_firestore_database" "database" {
  provider = google-beta
  project  = google_firebase_project.appcheck.project
  name     = "(default)"
  # See available locations: https://firebase.google.com/docs/projects/locations#default-cloud-location
  location_id = "name-of-region"
  # "FIRESTORE_NATIVE" is required to use Firestore with Firebase SDKs, authentication, and Firebase Security Rules.
  type             = "FIRESTORE_NATIVE"
  concurrency_mode = "OPTIMISTIC"

  # Wait for Firebase to be enabled in the Google Cloud project before initializing Firestore.
  depends_on = [
    google_firebase_project.appcheck,
  ]
}

# Creates a Firebase Android App in the new project created earlier.
resource "google_firebase_android_app" "appcheck" {
  provider     = google-beta
  project      = google_firebase_project.appcheck.project
  display_name = "Play Integrity app"
  package_name = "package.name.playintegrity"
  sha256_hashes = [
    # TODO: insert your Android app's SHA256 certificate
  ]
}

# It takes a while for App Check to recognize the new app
# If your app already exists, you don't have to wait 30 seconds.
resource "time_sleep" "wait_30s" {
  depends_on      = [google_firebase_android_app.appcheck]
  create_duration = "30s"
}

# Register the Android app with the Play Integrity provider
resource "google_firebase_app_check_play_integrity_config" "appcheck" {
  provider = google-beta
  project  = google_firebase_project.appcheck.project
  app_id   = google_firebase_android_app.appcheck.app_id

  depends_on = [time_sleep.wait_30s, google_firestore_database.database]

  lifecycle {
    precondition {
      condition     = length(google_firebase_android_app.appcheck.sha256_hashes) > 0
      error_message = "Provide a SHA-256 certificate on the Android App to use App Check"
    }
  }
}

# Enable enforcement of App Check for Firestore
resource "google_firebase_app_check_service_config" "firestore" {
  provider = google-beta

  project    = google_firebase_project.appcheck.project
  service_id = "firestore.googleapis.com"

  depends_on = [google_project_service.services]
}

Cette configuration crée un projet Google Cloud, active les services Firebase pour le projet et installe une nouvelle instance d'un Firebase Extension dans le projet. Si l'instance existe déjà, ses paramètres sont mis à jour en fonction des valeurs fournies dans la configuration.

# Creates a new Google Cloud project.
resource "google_project" "extensions" {
  provider   = google-beta.no_user_project_override
  folder_id  = "folder-id-for-new-project"
  name       = "Project Display Name"
  project_id = "project-id-for-new-project"

  # Associates the project with a Cloud Billing account
  # (required to use Firebase Extensions).
  billing_account = "000000-000000-000000"

  # Required for the project to display in a list of Firebase projects.
  labels = {
    "firebase" = "enabled"
  }
}

# Enables required APIs.
resource "google_project_service" "extensions" {
  provider = google-beta.no_user_project_override
  project  = google_project.extensions.project_id
  for_each = toset([
    "cloudbilling.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "serviceusage.googleapis.com",
    "firebase.googleapis.com",
    "firebaseextensions.googleapis.com",
  ])
  service = each.key

  # Don't disable the service if the resource block is removed by accident.
  disable_on_destroy = false
}

# Enables Firebase services for the new project created above.
resource "google_firebase_project" "extensions" {
  provider = google-beta
  project  = google_project.extensions.project_id

  depends_on = [
    google_project_service.extensions,
  ]
}

# Installs an instance of the "Translate Text in Firestore" extension.
# Or updates the extension if the specified instance already exists.
resource "google_firebase_extensions_instance" "translation" {
  provider = google-beta
  project = google_project.extensions.project_id

  instance_id = "translate-text-in-firestore"
  config {
    extension_ref = "firebase/firestore-translate-text"

    params = {
      COLLECTION_PATH      = "posts/comments/translations"
      DO_BACKFILL          = true
      LANGUAGES            = "ar,en,es,de,fr"
      INPUT_FIELD_NAME     = "input"
      LANGUAGES_FIELD_NAME = "languages"
      OUTPUT_FIELD_NAME    = "translated"
    }

    system_params = {
      "firebaseextensions.v1beta.function/location"                   = "us-central1"
      "firebaseextensions.v1beta.function/memory"                     = "256"
      "firebaseextensions.v1beta.function/minInstances"               = "0"
      "firebaseextensions.v1beta.function/vpcConnectorEgressSettings" = "VPC_CONNECTOR_EGRESS_SETTINGS_UNSPECIFIED"
    }
  }
}



Dépannage et questions fréquentes

Ce guide utilise les attributs Terraform suivants lorsque vous travaillez avec "projects".

project dans un bloc resource

Recommandation: dans la mesure du possible, incluez l'attribut project dans chaque bloc resource.

En incluant un attribut de projet, Terraform crée l'infrastructure spécifiée dans le bloc de ressources dans le projet spécifié. Ce guide et nos exemples de fichiers de configuration utilisent tous cette pratique.

Consultez la documentation officielle de Terraform sur project.

user_project_override dans le bloc provider

Pour provisionner la plupart des ressources, vous devez utiliser user_project_override = true, ce qui signifie vérifier les quotas par rapport à votre propre projet Firebase. Toutefois, pour configurer votre nouveau projet afin qu'il puisse accepter les vérifications de quota, vous devez d'abord utiliser user_project_override = false.

Consultez la documentation officielle de Terraform sur user_project_override.

Assurez-vous que le compte utilisateur que vous utilisez pour exécuter des commandes gcloud CLI a accepté les conditions d'utilisation de Firebase.

  • Pour effectuer cette vérification, utilisez un navigateur connecté au compte utilisateur et essayez d'afficher un projet Firebase existant dans la console Firebase. Si vous pouvez afficher un projet Firebase existant, cela signifie que le compte utilisateur a accepté les conditions d'utilisation de Firebase.

  • Si vous ne pouvez afficher aucun projet Firebase existant, le compte utilisateur n'a probablement pas accepté les conditions d'utilisation de Firebase. Pour résoudre ce problème, créez un projet Firebase via la console Firebase et acceptez les conditions d'utilisation de Firebase lors de la création du projet. Vous pouvez supprimer immédiatement ce projet via les paramètres du projet dans la console.

Patientez quelques minutes, puis réessayez d'exécuter terraform apply.

Cela peut être dû à un délai de propagation dans différents systèmes. Essayez de résoudre ce problème en important la ressource dans l'état Terraform en exécutant terraform import. Essayez ensuite d'exécuter terraform apply à nouveau.

Pour savoir comment importer chaque ressource, consultez la section "Import" (Importer) de la documentation Terraform (par exemple, la documentation "Import" (Importer) pour Cloud Firestore).

Comme l'erreur le suggère, Terraform tente peut-être de provisionner plusieurs indices et/ou de créer un document en même temps, et a rencontré une erreur de simultanéité. Essayez d'exécuter terraform apply à nouveau.

Cette erreur signifie que Terraform ne sait pas quel projet vérifier. Pour résoudre le problème, vérifiez les points suivants dans le bloc resource:

  • Assurez-vous d'avoir spécifié une valeur pour l'attribut project.
  • Assurez-vous d'utiliser le fournisseur avec user_project_override = true (sans alias), qui est google-beta dans les exemples Firebase.

Voici les raisons possibles pour lesquelles l'ID de projet existe déjà:

  • Le projet associé à cet ID appartient à un autre utilisateur.

    • Pour résoudre le problème:sélectionnez un autre ID de projet.
  • Le projet associé à cet ID a été supprimé récemment (en état de suppression temporaire).

    • Pour résoudre le problème:si vous pensez que le projet associé à l'ID vous appartient, vérifiez son état à l'aide de l'API REST projects.get.
  • Le projet associé à cet ID existe correctement sous l'utilisateur actuel. Une cause possible de l'erreur est qu'une terraform apply précédente a été interrompue.

    • Pour résoudre le problème:exécutez les commandes suivantes:
      terraform import google_project.default PROJECT_ID puis
      terraform import google_firebase_project.default PROJECT_ID

Si vous avez provisionné votre bucket Cloud Storage par défaut (via google_app_engine_application) avant d'essayer de provisionner votre instance Cloud Firestore par défaut, vous constaterez que votre instance Cloud Firestore par défaut a déjà été provisionnée. Notez que l'instance de base de données provisionnée est en mode Datastore, ce qui signifie qu'elle n'est pas accessible aux SDK Firebase, à l'authentification ni à Firebase Security Rules. Si vous souhaitez utiliser Cloud Firestore avec ces services Firebase, vous devez vider la base de données, puis modifier son type de base de données dans la console Google Cloud.

Lorsque vous provisionnez le bucket Cloud Storage par défaut d'un projet (via google_app_engine_application) et que le projet n'a pas encore d'instance Cloud Firestore par défaut, google_app_engine_application provisionne automatiquement l'instance Cloud Firestore par défaut du projet.

Étant donné que l'instance Cloud Firestore par défaut de votre projet est déjà provisionnée, google_firestore_database renvoie une erreur si vous essayez de provisionner à nouveau cette instance par défaut.

Une fois l'instance Cloud Firestore par défaut du projet provisionnée, vous ne pouvez plus la "reprovisionner" ni modifier son emplacement. Notez que l'instance de base de données provisionnée est en mode Datastore, ce qui signifie qu'elle n'est pas accessible aux SDK Firebase, à l'authentification ni à Firebase Security Rules. Si vous souhaitez utiliser Cloud Firestore avec ces services Firebase, vous devez vider la base de données, puis modifier son type de base de données dans la console Google Cloud.