Firebase で Terraform のサポートを開始しました。特定のリソースがプロビジョニングされ、サービスが有効になっている Firebase プロジェクトの作成を自動化し、標準化したいチームの場合は、Firebase で Terraform を使用することをおすすめします。
Firebase で Terraform を使用するための基本的なワークフローは次のとおりです。
Terraform 構成ファイル(
.tf
ファイル)を作成してカスタマイズする。このファイルに、プロビジョニングしたいインフラストラクチャ(プロビジョニングするリソースと有効にするサービス)を指定します。Terraform とやり取りする gcloud CLI コマンドを使用して、
.tf
ファイルに指定したインフラストラクチャをプロビジョニングします。
Terraform と Firebase でできること
このガイドで説明する一般的なワークフローの例は、Android アプリを含む新しい Firebase プロジェクトを作成するものですが、Terraform を使用すると次のようなこともできます。
Terraform を使用して、既存のインフラストラクチャの削除と変更を行う。
Terraform を使用して、次のようなプロダクト固有の構成とタスクを管理する。
- Firebase Authentication ログイン プロバイダを有効にする。
- Cloud Storage バケットまたはデータベース インスタンスを作成して、Firebase Security Rules をデプロイする。
これらのタスクはすべて、標準の Terraform 構成ファイルとコマンドで行うことができます。このような作業に役立つように、一般的なユースケースに対応したサンプルの Terraform 構成ファイルが用意されています。
Firebase で Terraform を使用するための一般的なワークフロー
前提条件
このガイドでは、Firebase で Terraform を使用する方法について説明します。そのため、Terraform に関する基本的なスキルがあることを前提としています。このワークフローを始める前に、次の前提条件を満たしていることを確認してください。
Terraform をインストールし、公式のチュートリアルで Terraform について学習している。
Google Cloud CLIをインストール(gcloud CLI)します。ユーザー アカウントまたはサービス アカウントを使用してログインします。
ユーザー アカウントとサービス アカウントの要件を確認する
- ユーザー アカウントを使用する場合は、Firebase の利用規約(Firebase ToS)に同意する必要があります。Firebase コンソールに Firebase プロジェクトが表示されている場合は、Firebase ToS にすでに同意しています。
- Terraform が特定のアクション(プロジェクトの作成など)を実行するには、次の条件を満たしている必要があります。
- ユーザー アカウントまたはサービス アカウントには、これらのアクションに対応する IAM アクセス権が必要です。
- ユーザー アカウントまたはサービス アカウントが Google Cloud 組織に属している場合、組織のポリシーで、これらのアクションの実行をアカウントに許可する必要があります。
ステップ 1: Terraform 構成ファイルを作成してカスタマイズする
Terraform 構成ファイルには次の 2 つのメイン セクションが必要です(このガイドの後半で詳しく説明します)。
provider
を設定する
provider
は、使用する Firebase プロダクトまたはサービスに関係なく設定する必要があります。
ローカル ディレクトリに Terraform 構成ファイル(
main.tf
ファイルなど)を作成します。このガイドでは、この構成ファイルを使用して、
provider
の設定と、Terraform で作成するすべてのインフラストラクチャを指定します。ただし、別の方法でプロバイダの設定を追加することもできます。provider
の設定を追加する別の方法を確認する残りの Terraform 構成に
provider
の設定を追加するには、次の方法があります。オプション 1: 1 つの Terraform
.tf
構成ファイル(このガイドを参照)の先頭に追加します。- Terraform を初めて使用する場合や Firebase で Terraform を試す場合は、このオプションを使用します。
オプション 2: 作成するインフラストラクチャを指定する
.tf
ファイル(main.tf
ファイルなど)とは別の.tf
ファイル(provider.tf
ファイルなど)に追加します。- 大規模なチームの一員として設定を標準化する必要がある場合は、このオプションを使用します。
- Terraform コマンドを実行するときに、
provider.tf
とmain.tf
の両方のファイルが同じディレクトリに配置されている必要があります。
main.tf
ファイルの先頭に、次のprovider
設定を記述します。これは Terraform で Firebase を使用する機能のベータ版であるため、
google-beta
プロバイダを使用する必要があります。本番環境で使用する場合は注意してください。# 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 }
Firebase で Terraform を使用する場合は、さまざまな種類のプロジェクト関連の属性(このガイドの「割り当てチェック用プロジェクト」も含む)をご覧ください。
次のセクションに進んで構成ファイルを作成し、作成するインフラストラクチャを指定します。
resource
ブロックを使用して、作成するインフラストラクチャを指定する
Terraform で作成するすべてのインフラストラクチャ(プロビジョニングするすべてのリソースと有効にするすべてのサービス)を Terraform 構成ファイル(このガイドでは main.tf
ファイル)に指定する必要があります。このガイドの Terraform をサポートする Firebase リソースを確認してください。
main.tf
ファイルを開きます。provider
の設定で、次のresource
ブロックの構成を追加します。この基本的な例では、新しい Firebase プロジェクトを作成し、そのプロジェクトに Firebase Android アプリを作成します。
# 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, ] }
このサンプル構成ファイルの注釈付きバージョンを表示する
プロジェクトのインフラストラクチャとリソースとしてのアプリに慣れていない場合は、次のドキュメントをご覧ください。
- Firebase プロジェクトについて理解する
- リファレンス ドキュメント(Firebase プロジェクト管理)
# 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, ] }
ステップ 2: Terraform コマンドを実行して、指定したインフラストラクチャを作成する
main.tf
ファイルで指定されたリソースをプロビジョニングしてサービスを有効にするには、main.tf
ファイルと同じディレクトリから次のコマンドを実行します。これらのコマンドの詳細については、Terraform のドキュメントをご覧ください。
このディレクトリで Terraform コマンドを初めて実行する場合は、構成ディレクトリを初期化し、Google Terraform プロバイダをインストールする必要があります。この作業を行うには、次のコマンドを実行します。
terraform init
次のコマンドを実行して、
main.tf
ファイルに指定されているインフラストラクチャを作成します。terraform apply
すべてが想定どおりプロビジョニングまたは有効化されていることを確認します。
オプション 1: 次のコマンドを実行して、ターミナルに出力された構成を確認します。
terraform show
オプション 2: Firebase コンソールで Firebase プロジェクトを表示します。
Terraform をサポートする Firebase リソース
次の Firebase と Google のリソースは Terraform に対応しています。Google では随時リソースを追加しています。Terraform で管理したいリソースが表示されない場合は、しばらくしてからもう一度ご確認いただくか、GitHub リポジトリで問題を報告してください。
Firebase プロジェクトとアプリの管理
google_firebase_project
- 既存の Google Cloud プロジェクトで Firebase サービスを有効にするFirebase アプリ
google_firebase_apple_app
- Firebase Apple プラットフォーム アプリを作成または管理するgoogle_firebase_android_app
- Firebase Android アプリを作成または管理するgoogle_firebase_web_app
- Firebase ウェブアプリを作成または管理する
Firebase Authentication
google_identity_platform_config
- Google Cloud Identity Platform(GCIP)(Firebase Authentication のバックエンド)を有効にして、プロジェクト レベルの認証設定を行うTerraform を使用して Firebase Authentication を構成する場合は GCIP を有効にする必要があります。Firebase Authentication の設定方法については、サンプル
.tf
ファイルを確認してください。Terraform で GCIP や Firebase Authentication を有効にするプロジェクトには、Blaze お支払いプランが必要です(つまり、プロジェクトに関連付けられた Cloud Billing アカウントが必要です)。
google_project
リソースにbilling_account
属性を設定すると、この作業をプログラムで行うことができます。このリソースを使用すると、匿名、メールアドレスとパスワード、電話認証などのローカル ログイン方法、ブロッキング関数、承認済みドメインなど、より多くの構成も可能になります。
google_identity_platform_default_supported_idp_config
- Google、Facebook、Apple などの一般的なフェデレーション ID プロバイダを構成するidentity_platform_oauth_idp_config
- 任意の OAuth ID プロバイダ(IdP)ソースを構成するgoogle_identity_platform_inbound_saml_config
- SAML 統合を構成する
現時点でサポートされていない機能:
- Terraform を使用した多要素認証(MFA)の構成
Firebase Realtime Database
google_firebase_database_instance
Realtime Database インスタンスを作成します。
現時点でサポートされていない機能:
- Terraform を介して Firebase Realtime Database Security Rules をデプロイする(プログラムで行う方法など、別の手段でこれらの Rules をデプロイする方法をご覧ください)
Cloud Firestore
google_firestore_database
Cloud Firestore インスタンスを作成します。google_firestore_index
- Cloud Firestore の効率的なクエリを有効にするgoogle_firestore_document
- コレクション内の特定のドキュメントを含む Cloud Firestore インスタンスをシードする重要: このシード ドキュメントでは、実際のエンドユーザーのデータや本番環境のデータを使用しないでください。
Cloud Storage for Firebase
google_firebase_storage_bucket
- Firebase SDK、認証、Firebase Security Rules で既存の Cloud Storage バケットにアクセスできるようにするgoogle_storage_bucket_object
- Cloud Storage バケットにオブジェクトを追加する重要: このファイルでは、エンドユーザーや本番環境の実際のデータを使用しないでください。
Firebase Security Rules(Cloud Firestore、Cloud Storage)
Firebase Realtime Database では、Firebase Security Rules に別のプロビジョニング システムが使用されています。
google_firebaserules_ruleset
- Cloud Firestore インスタンスまたは Cloud Storage バケットに適用される Firebase Security Rules を定義するgoogle_firebaserules_release
- 特定のルールセットを Cloud Firestore インスタンスまたは Cloud Storage バケットにデプロイする
Firebase App Check
google_firebase_app_check_service_config
- サービスの App Check 適用を有効にするgoogle_firebase_app_check_app_attest_config
- App Attest プロバイダに Apple プラットフォームのアプリを登録するgoogle_firebase_app_check_device_check_config
- Apple プラットフォームのアプリを DeviceCheck プロバイダに登録するgoogle_firebase_app_check_play_integrity_config
- Android アプリを Play Integrity プロバイダに登録するgoogle_firebase_app_check_recaptcha_enterprise_config
- reCAPTCHA Enterprise プロバイダにウェブアプリを登録するgoogle_firebase_app_check_recaptcha_v3_config
- reCAPTCHA v3 プロバイダにウェブアプリを登録するgoogle_firebase_app_check_debug_token
- テストにデバッグ トークンを使用する
Firebase Extensions
google_firebase_extensions_instance
- Firebase Extension のインスタンスをインストールまたは更新します。
一般的なユースケースの Terraform 構成ファイルの例
GCIP を使用して Firebase Authentication を設定する
この構成ファイルでは、新しい Google Cloud プロジェクトを作成し、プロジェクトを Cloud Billing アカウントに関連付けます(GCIP を使用した Firebase Authentication には Blaze お支払いプランが必要です)。プロジェクトで Firebase サービスを有効にし、GCIP を使用して Firebase Authentication を設定し、プロジェクトに 3 つの異なるアプリの種類を登録します。
Terraform で Firebase Authentication を設定するには、GCIP を有効にする必要があります。
# 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, ] }
デフォルトの Firebase Realtime Database インスタンスをプロビジョニングする
この構成ファイルでは、新しい Google Cloud プロジェクトを作成し、プロジェクトで Firebase サービスを有効にします。プロジェクトのデフォルトの Realtime Database インスタンスをプロビジョニングして、プロジェクトに 3 つの異なるアプリの種類を登録します。
# 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, ] }
複数の Firebase Realtime Database インスタンスをプロビジョニングする
この構成ファイルでは、新しい Google Cloud プロジェクトを作成し、プロジェクトを Cloud Billing アカウントに関連付けます(複数の Realtime Database インスタンスには Blaze お支払いプランが必要です)。プロジェクトで Firebase サービスを有効にして、複数の Realtime Database インスタンス(プロジェクトのデフォルトの Realtime Database インスタンスを含む)をプロビジョニングし、プロジェクトに 3 つの異なるアプリの種類を登録します。
# 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, ] }
デフォルトの Cloud Firestore インスタンスをプロビジョニングする
この構成ファイルでは、新しい Google Cloud プロジェクトを作成し、プロジェクトで Firebase サービスを有効にします。プロジェクトのデフォルトの Cloud Firestore インスタンスをプロビジョニングして、プロジェクトに 3 つの異なるアプリの種類を登録します。
また、デフォルトの Cloud Firestore インスタンスで Firebase Security Rules をプロビジョニングし、Cloud Firestore インデックスを作成して、シードデータを含む Cloud Firestore ドキュメントを追加します。
# 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, ] }
これは Cloud Firestore Security Rules のルールセットで、firestore.rules
という名前のローカル ファイルに存在する必要があります。
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /some_collection/{document} { allow read, create, update: if request.auth != null; } } }
デフォルトの Cloud Storage バケットをプロビジョニングする
追加の Cloud Storage バケットをプロビジョニングする
この構成ファイルでは、新しい Google Cloud プロジェクトを作成し、プロジェクトを Cloud Billing アカウントに関連付けます(追加のバケットには Blaze お支払いプランが必要です)。プロジェクトで Firebase サービスを有効にし、デフォルト以外の追加の Cloud Storage バケットをプロビジョニングして、プロジェクトに 3 つの異なるアプリの種類を登録します。
また、Cloud Storage バケットごとに Firebase Security Rules をプロビジョニングし、いずれかの 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, ] }
これは Cloud Storage Security Rules のルールセットで、storage.rules
という名前のローカル ファイルに存在する必要があります。
rules_version = '2'; service firebase.storage { match /b/{bucket}/o { match /some_folder/{fileName} { allow read, write: if request.auth != null; } } }
Firebase App Check を使用して API リソースを保護する
この構成ファイルでは、新しい Google Cloud プロジェクトを作成し、プロジェクトで Firebase サービスを有効にし、Cloud Firestore に Firebase App Check の適用を設定して有効にし、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] }
Firebase Extension のインスタンスをインストールする
この構成ファイルでは、新しい Google Cloud プロジェクトを作成し、プロジェクトで Firebase サービスを有効にし、プロジェクトに Firebase Extension の新しいインスタンスをインストールします。インスタンスがすでに存在する場合、そのパラメータは構成で指定された値に基づいて更新されます。
# 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" } } }
トラブルシューティングとよくある質問
プロジェクト関連の属性(project
、user_project_override
など)についてより詳しく教えてほしい
このガイドでは、プロジェクトを操作する際に次の Terraform 属性を使用します。
resource
ブロック内のproject
推奨: 可能な限り、各
resource
ブロック内にproject
属性を含めます。プロジェクト属性を含めると、Terraform は、リソース ブロック内で指定されたインフラストラクチャを、指定されたプロジェクトに作成します。このガイドとすべてのサンプル構成ファイルでは、この手法を使用しています。
project
については、Terraform の公式ドキュメントをご覧ください。provider
ブロック内のuser_project_override
ほとんどのリソースのプロビジョニングで
user_project_override = true
の使用を推奨します。これを使用すると、Firebase プロジェクトの割り当てがチェックされます。ただし、新しいプロジェクトをセットアップする際に割り当てチェックが行われるようにするには、最初にuser_project_override = false
を使用する必要があります。user_project_override
については、Terraform の公式ドキュメントをご覧ください。
「generic::permission_denied: Firebase Tos Not Accepted
」というエラーが表示される
gcloud CLI コマンドの実行に使用するユーザー アカウントが Firebase の利用規約(Firebase ToS)に同意していることを確認します。
この確認を行うには、ユーザー アカウントにログインしているブラウザで Firebase コンソールを開き、既存の Firebase プロジェクトを表示してみます。既存の Firebase プロジェクトが表示された場合、ユーザー アカウントは Firebase ToS に同意しています。
既存の Firebase プロジェクトが表示されない場合、ユーザー アカウントは Firebase ToS に同意していない可能性があります。この問題を解決するには、Firebase コンソールで新しい Firebase プロジェクトを作成し、プロジェクトの作成時に Firebase ToS に同意します。このプロジェクトは、コンソールの [プロジェクト設定] ですぐに削除できます。
terraform apply
を実行すると generic::permission_denied: IAM authority does not have the
permission
というエラーが表示される
数分待ってから、terraform apply
を再度実行してみてください。
リソースの作成に失敗したが、terraform apply
を再度実行すると「ALREADY_EXISTS
」と表示される
この問題は、システム間の伝播の遅延が原因で発生している可能性があります。この問題を解決するには、terraform import
を実行して、Terraform の状態にリソースをインポートします。その後、terraform apply
を再度実行してみてください。
各リソースをインポートする方法については、Terraform のドキュメントでインポートに関するセクションをご覧ください(Cloud Firestore の「インポート」ドキュメントなど)。
Cloud Firestore を操作すると Error creating Index: googleapi:
Error 409;...Concurrent access -- try again
というエラーが発生する
エラーが示しているように、Terraform が複数のインデックスのプロビジョニングとドキュメントの作成を同時に実行し、同時実行エラーが発生している可能性があります。もう一度 terraform apply
を実行してみてください。
"you may need to specify 'X-Goog-User-Project' HTTP header for quota and
billing purposes"
というエラーが表示される
このエラーは、Terraform が割り当てを確認するプロジェクトを把握していないことを意味します。トラブルシューティングを行うには、resource
ブロック内の次の点を確認してください。
project
属性の値が指定されていることを確認してください。- プロバイダで
user_project_override = true
が使用されていること(エイリアスが使用されていないこと)を確認してください。Firebase サンプルではgoogle-beta
です。
新しい Google Cloud プロジェクトを作成すると、新しいプロジェクトに指定されたプロジェクト ID がすでに存在するというエラーが表示されます。
プロジェクト ID がすでに存在している理由としては、次のようなものが考えられます。
この ID に関連付けられているプロジェクトを別のユーザーが所有している。
- 解決策: 別のプロジェクト ID を選択します。
その ID に関連付けられたプロジェクトが最近削除された(復元可能な削除状態になっている)。
- 解決策: ID に関連付けられたプロジェクトが自身の所有するプロジェクトであると思われる場合は、
projects.get
REST API を使用して、プロジェクトの状態を確認します。
- 解決策: ID に関連付けられたプロジェクトが自身の所有するプロジェクトであると思われる場合は、
ID に関連付けられたプロジェクトが現在のユーザーの下に存在している。エラーの原因としては、以前の
terraform apply
が中断されたことが考えられます。- 解決策: 次のコマンドを順番に実行します。
terraform import google_project.default PROJECT_ID
terraform import google_firebase_project.default PROJECT_ID
- 解決策: 次のコマンドを順番に実行します。
デフォルトの Cloud Storage バケットの前に、デフォルトの Cloud Firestore インスタンスをプロビジョニングする必要があるのはなぜですか。
デフォルトの Cloud Firestore インスタンスのプロビジョニングを試みる前に、デフォルトの Cloud Storage バケットを(google_app_engine_application
を介して)プロビジョニングした場合、デフォルトの Cloud Firestore インスタンスはすでにプロビジョニングされています。プロビジョニングされたデータベース インスタンスは Datastore モードです。つまり、Firebase SDK、認証、Firebase Security Rules にはアクセスできません。これらの Firebase サービスで Cloud Firestore を使用するには、データベースを空にしてから、Google Cloud コンソールでデータベースのタイプを変更する必要があります。
Cloud Storage を(google_app_engine_application
を介して)プロビジョニングしてからデフォルトの Cloud Firestore インスタンスをプロビジョニングしようとすると、Error: Error creating Database: googleapi: Error 409: Database already
exists. Please use another database_id
というエラーが発生します。
プロジェクトのデフォルトの Cloud Storage バケットを(google_app_engine_application
を介して)プロビジョニングするときに、プロジェクトにデフォルトの Cloud Firestore インスタンスが存在しないと、google_app_engine_application
はプロジェクトのデフォルトの Cloud Firestore インスタンスを自動的にプロビジョニングします。
そのため、プロジェクトのデフォルトの Cloud Firestore インスタンスはすでにプロビジョニングされているため、そのデフォルト インスタンスを明示的に再度プロビジョニングしようとすると、google_firestore_database
でエラーが発生します。
プロジェクトのデフォルトの Cloud Firestore インスタンスをプロビジョニングした後に、そのインスタンスを「再プロビジョニング」したり、ロケーションの変更を行うことはできません。プロビジョニングされたデータベース インスタンスは Datastore モードです。つまり、Firebase SDK、認証、Firebase Security Rules にはアクセスできません。これらの Firebase サービスで Cloud Firestore を使用するには、データベースを空にしてから、Google Cloud コンソールでデータベースのタイプを変更する必要があります。