O Firebase está começando a oferecer suporte ao Terraform. Se a sua equipe quer automatizar e padronizar a criação de projetos do Firebase com provisionamento de recursos e ativação de serviços específicos, usar o Terraform e o Firebase pode ser uma boa opção.
O fluxo de trabalho básico para usar o Terraform com o Firebase inclui o seguinte:
Criação e personalização de um arquivo de configuração do Terraform (um arquivo
.tf
) que especifica a infraestrutura que você quer provisionar, ou seja, os recursos que você quer provisionar e os serviços que você quer ativar.Uso de comandos gcloud CLI que interagem com o Terraform para provisionar a infraestrutura especificada no arquivo
.tf
.
O que você pode fazer com o Terraform e o Firebase?
Neste guia, o exemplo de fluxo de trabalho genérico é criar um novo projeto do Firebase com um app Android. Mas você pode fazer muito mais com o Terraform, como:
Excluir e modificar infraestruturas atuais usando o Terraform.
Gerenciar configurações e tarefas específicas do produto usando o Terraform, como:
- Ativar os provedores de login do Firebase Authentication.
- Criar buckets de Cloud Storage ou instâncias de banco de dados e implantar Firebase Security Rules para eles.
Você pode usar arquivos de configuração e comandos padrão do Terraform para realizar todas essas tarefas. Para ajudar nisso, mostramos exemplos de arquivos de configuração do Terraform para vários casos de uso comuns.
Fluxo de trabalho genérico para uso do Terraform com o Firebase
Pré-requisitos
Este guia é uma introdução ao uso do Terraform com o Firebase, portanto, é necessário conhecer os princípios básicos do Terraform. Verifique se você concluiu os seguintes pré-requisitos antes de iniciar esse fluxo de trabalho:
Instale o Terraform e leia os tutoriais oficiais dele.
Instale o Google Cloud CLI (gcloud CLI). Faça login usando uma conta de usuário ou uma conta de serviço.
Confira os requisitos para contas de usuário e contas de serviço
- Ao usar uma conta de usuário, você precisa aceitar os Termos de Serviço do Firebase (TOS do Firebase). Se você visualizou um projeto no Console do Firebase, então aceitou os TOS do Firebase.
- Para que o Terraform realize algumas ações, como criar projetos,
o seguinte precisa ser verdadeiro:
- O usuário ou a conta de serviço precisa ter o acesso de IAM aplicável para essas ações.
- Se o usuário ou a conta de serviço fizer parte de uma organização do Google Cloud, as políticas da organização precisam permitir que a conta realize essas ações.
Etapa 1: criar e personalizar um arquivo de configuração do Terraform
Um arquivo de configuração do Terraform precisa de duas seções principais, explicadas em detalhes abaixo:
- Uma seção de configuração de
provider
que determina quais recursos do Terraform podem ser acessados - Uma seção de blocos de
resource
individuais que especificam qual infraestrutura criar
Configure seu provider
Uma configuração de provider
é necessária, seja quais forem os produtos ou serviços do Firebase envolvidos.
Crie um arquivo de configuração do Terraform (como o
main.tf
) no diretório local.Neste guia, você vai usar esse arquivo de configuração para especificar as características de
provider
e toda a infraestrutura a ser criada pelo Terraform. No entanto, você tem opções para incluir a configuração do provedor.Conheça as maneiras de incluir a configuração de
provider
.Você tem as seguintes opções para incluir uma definição de
provider
no restante da sua configuração do Terraform:Opção 1: incluir na parte superior de um único arquivo de configuração
.tf
do Terraform, como mostrado neste guia.- Use essa opção se você estiver começando a usar o Terraform ou apenas testando essa ferramenta com o Firebase.
Opção 2: incluir em um arquivo
.tf
separado (como umprovider.tf
), diferente do.tf
, em que você especifica a infraestrutura a ser criada (como um arquivomain.tf
).- Use essa opção se você fizer parte de uma equipe maior que precisa padronizar a configuração.
- Ao executar os comandos do Terraform, os arquivos
provider.tf
emain.tf
precisam estar no mesmo diretório.
Inclua a seguinte configuração de
provider
na parte superior do arquivomain.tf
.Use o provedor
google-beta
porque esta é uma versão Beta da integração do Firebase e Terraform. Tenha cuidado ao utilizar esse recurso na produção.# 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 }
Saiba mais sobre os diferentes tipos de atributos relacionados ao projeto, incluindo o que este guia chama de "projeto de verificação de cota", ao usar o Terraform com o Firebase.
Acesse a próxima seção para concluir o arquivo de configuração e especificar qual infraestrutura será criada.
Especificar qual infraestrutura criar usando blocos de resource
No arquivo de configuração do Terraform (para este guia, o arquivo main.tf
), é necessário especificar toda a infraestrutura que você quer que o Terraform crie, ou seja, todos os recursos a serem provisionados e todos os serviços a serem ativados. Neste guia você encontra uma lista completa de todos os
recursos do Firebase que oferecem suporte ao Terraform.
Abra seu arquivo
main.tf
.Na configuração de
provider
, inclua a seguinte definição dos blocos deresource
.Este exemplo básico cria um novo projeto do Firebase e, em seguida, um app Android do Firebase nesse projeto.
# 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, ] }
Confira uma versão com várias anotações deste arquivo de exemplo de configuração
Se você não conhece a infraestrutura de projetos e apps como recursos, consulte a seguinte documentação:
- Noções básicas sobre os projetos do Firebase
- Documentação de referência para gerenciamento de projetos do 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, ] }
Etapa 2: executar comandos do Terraform para criar a infraestrutura especificada
Para provisionar os recursos e ativar os serviços especificados no arquivo main.tf
, execute os seguintes comandos no mesmo diretório de main.tf
.
Se você quiser informações detalhadas sobre esses comandos, consulte a
documentação do Terraform.
Se esta for a primeira vez que você está executando comandos do Terraform no diretório, inicialize o diretório de configuração e instale o provedor do Google Terraform. Para isso, execute o seguinte comando:
terraform init
Crie a infraestrutura especificada no arquivo
main.tf
executando o seguinte comando:terraform apply
Confirme se tudo foi provisionado ou ativado conforme o esperado:
Opção 1: revise a configuração mostrada no terminal executando o seguinte comando:
terraform show
Opção 2: visualize seu projeto do Firebase no Console do Firebase.
Recursos do Firebase com suporte ao Terraform
Os seguintes recursos do Firebase e do Google oferecem suporte ao Terraform. Novos recursos são adicionados constantemente. Portanto, se você não encontrar o que procura, volte em breve para conferir se ele está disponível ou solicite ao informar um problema no repositório do GitHub.
Gerenciamento de projetos e apps do Firebase
google_firebase_project
: ative os serviços do Firebase em um projeto Google Cloud.Apps do Firebase
google_firebase_apple_app
: crie ou gerencie um app do Firebase para plataformas da Apple.google_firebase_android_app
: crie ou gerencie um app Android do Firebase.google_firebase_web_app
: crie ou gerencie um app da Web do Firebase.
Firebase Authentication
google_identity_platform_config
: ative o Google Cloud Identity Platform (GCIP), que é o back-end do Firebase Authentication, e envie as configurações de autenticação no nível do projeto.A configuração do Firebase Authentication pelo Terraform requer a ativação do GCIP. Consulte o arquivo de amostra
.tf
para saber como configurar Firebase Authentication.O projeto em que o Terraform vai ativar o GCIP e/ou o Firebase Authentication precisa estar no plano de preços Blaze, ou seja, o projeto precisa ter uma conta do Cloud Billing associada. Isso pode ser feito de maneira programática configurando o atributo
billing_account
no recursogoogle_project
.Esse recurso também permite mais configurações, como métodos de login locais, como anônimo, e-mail/senha e autenticação por telefone, bem como funções de bloqueio e domínios autorizados.
google_identity_platform_default_supported_idp_config
: configure provedores de identidade federados comuns, como Google, Facebook ou Apple.identity_platform_oauth_idp_config
: configure origens de provedor de identidade OAuth (IdP) arbitrárias.google_identity_platform_inbound_saml_config
: configure integrações SAML.
Sem suporte no momento:
- Configurar a autenticação multifator (MFA) no Terraform
Firebase Realtime Database
google_firebase_database_instance
: criar uma instância Realtime Database
Sem suporte no momento:
- Implantar Firebase Realtime Database Security Rules pelo Terraform (aprenda a implantar esses Rules usando outras ferramentas, incluindo opções programáticas)
Cloud Firestore
google_firestore_database
: criar uma instância Cloud Firestoregoogle_firestore_index
: ative consultas eficientes no Cloud Firestore.google_firestore_document
: propague uma instância de Cloud Firestore com um documento específico em uma coleção.Importante: não use dados reais de usuário final ou de produção neste documento semente.
Cloud Storage for Firebase
google_firebase_storage_bucket
: torne um bucket Cloud Storage acessível para SDKs do Firebase, autenticação e Firebase Security Rules.google_storage_bucket_object
: adicione um objeto a um bucket Cloud Storage.Importante: não use dados reais de usuários finais ou de produção neste arquivo.
Firebase Security Rules para Cloud Firestore e Cloud Storage
O Firebase Realtime Database usa um sistema de provisionamento diferente para o Firebase Security Rules.
google_firebaserules_ruleset
: defina Firebase Security Rules que se aplicam a uma instância Cloud Firestore ou a um bucket do Cloud Storage.google_firebaserules_release
: implante conjuntos de regras específicos para uma instância do Cloud Firestore ou um bucket do Cloud Storage.
Firebase App Check
google_firebase_app_check_service_config
: ative a aplicação de App Check para um serviço.google_firebase_app_check_app_attest_config
: registre um app de plataformas da Apple com o provedor do App Attest.google_firebase_app_check_device_check_config
: registre um app de plataformas da Apple com o provedor DeviceCheck.google_firebase_app_check_play_integrity_config
: registre um app Android com o provedor da Play Integrity.google_firebase_app_check_recaptcha_enterprise_config
: registre um app da Web com o provedor do reCAPTCHA Enterprise.google_firebase_app_check_recaptcha_v3_config
: registre um app da Web com o provedor do reCAPTCHA v3.google_firebase_app_check_debug_token
: use tokens de depuração para testes.
Firebase Extensions
google_firebase_extensions_instance
: instale ou atualize uma instância de um Firebase Extension.
Exemplos de arquivos de configuração do Terraform para casos de uso comuns
Configurar Firebase Authentication com o GCIP
Essa configuração cria um novo projeto Google Cloud, associa o projeto a uma conta do Cloud Billing (o plano de preços Blaze é necessário para Firebase Authentication com GCIP), ativa os serviços do Firebase para o projeto, configura Firebase Authentication com GCIP e registra três tipos diferentes de app com o projeto.
A ativação do GCIP é necessária para configurar o Firebase Authentication pelo 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, ] }
Provisionar a instância padrão Firebase Realtime Database
Essa configuração cria um novo projeto Google Cloud, ativa os serviços do Firebase para o projeto, provisiona a instância Realtime Database padrão do projeto e registra três tipos diferentes de app.
# 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, ] }
Provisionar várias instâncias do Firebase Realtime Database
Essa configuração cria um novo projeto Google Cloud, associa o projeto a uma conta do Cloud Billing (o plano de preços Blaze é necessário para várias instâncias de Realtime Database), ativa os serviços do Firebase para o projeto, provisiona várias instâncias de Realtime Database (incluindo a instância de Realtime Database padrão do projeto) e registra três tipos diferentes de app com o projeto.
# 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, ] }
Provisionar a instância padrão do Cloud Firestore
Essa configuração cria um novo projeto Google Cloud, ativa os serviços do Firebase para o projeto, provisiona a instância Cloud Firestore padrão do projeto e registra três tipos diferentes de app.
Também provisiona Firebase Security Rules para a instância padrão do Cloud Firestore, cria um índice do Cloud Firestore e adiciona um documento do Cloud Firestore com dados de origem.
# 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, ] }
Esse é o conjunto de regras de Cloud Firestore Security Rules que precisa estar em um arquivo local
chamado firestore.rules
.
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /some_collection/{document} { allow read, create, update: if request.auth != null; } } }
Provisionar o bucket Cloud Storage padrão
Provisionar outros buckets do Cloud Storage
Essa configuração cria um novo projeto do Google Cloud, associa-o a uma conta Cloud Billing (o plano de preços Blaze é necessário para outros buckets), ativa serviços do Firebase para o projeto, provisiona outros buckets não padrão do Cloud Storage e registra três tipos diferentes de app com o projeto.
Também provisiona Firebase Security Rules para cada bucket do Cloud Storage e faz upload de um arquivo para um dos buckets do 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, ] }
Esse é o conjunto de regras de Cloud Storage Security Rules que precisa estar em um arquivo local
chamado storage.rules
.
rules_version = '2'; service firebase.storage { match /b/{bucket}/o { match /some_folder/{fileName} { allow read, write: if request.auth != null; } } }
Proteger um recurso de API com Firebase App Check
Essa configuração cria um novo projeto Google Cloud, ativa os serviços do Firebase para o projeto e configura e ativa a aplicação de Firebase App Check para Cloud Firestore, de modo que ele só possa ser acessado pelo seu app 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] }
Instalar uma instância de um Firebase Extension
Essa configuração cria um novo projeto Google Cloud, ativa os serviços do Firebase para o projeto e instala uma nova instância de um Firebase Extension no projeto. Se a instância já existir, os parâmetros dela serão atualizados com base nos valores fornecidos na configuração.
# 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" } } }
Solução de problemas e perguntas frequentes
Conheça
todos os atributos relacionados ao projeto, como
project
e user_project_override
Este guia usa os seguintes atributos do Terraform ao trabalhar com projetos.
project
em um blocoresource
Recomendado: sempre que possível, inclua o atributo
project
em cada blocoresource
.Ao incluir um atributo de projeto, o Terraform vai criar a infraestrutura especificada no bloco de recursos dentro do projeto especificado. Usamos essa prática neste guia e nos nossos arquivos de exemplo de configuração.
Consulte a documentação oficial do Terraform sobre
project
.user_project_override
no blocoprovider
Para provisionar a maioria dos recursos, use
user_project_override = true
, o que significa verificar a cota do seu próprio projeto do Firebase. No entanto, para configurar o novo projeto para que ele possa aceitar verificações de cota, primeiro você precisa usaruser_project_override = false
.Consulte a documentação oficial do Terraform sobre
user_project_override
.
Você recebe este erro:
generic::permission_denied: Firebase Tos Not Accepted
.
Verifique se a conta de usuário que você está usando para executar os comandos da gcloud CLI aceitou os Termos de Serviço do Firebase (TOS do Firebase).
Para fazer isso, conecte-se à conta de usuário em um navegador e tente visualizar um projeto existente do Firebase no Console do Firebase. Se você conseguir visualizar um projeto existente do Firebase, então a conta de usuário aceitou os TOS do Firebase.
Se não, provavelmente a conta de usuário não aceitou os TOS do Firebase. Para corrigir isso, crie um novo projeto do Firebase usando o Console do Firebase e aceite os TOS como parte da criação de projetos. Você pode excluir esse projeto imediatamente nas Configurações do projeto no console.
Depois de executar
terraform apply
, você recebe este erro:
generic::permission_denied: IAM authority does not have the
permission
.
Aguarde alguns minutos e tente executar terraform apply
novamente.
Ocorreu um falha ao criar um recurso, mas, ao executar terraform apply
novamente, ALREADY_EXISTS
aparece.
Isso pode ocorrer devido a um atraso na propagação em vários sistemas. Para tentar resolver o problema, importe o recurso para o estado do Terraform e execute terraform import
. Em seguida, tente executar terraform apply
novamente.
Saiba como importar cada recurso na seção "Importar" da documentação do Terraform (por exemplo, a documentação "Importar" do Cloud Firestore).
Ao trabalhar com
Cloud Firestore, você recebe este erro: Error creating Index: googleapi:
Error 409;...Concurrent access -- try again
Como o erro sugere, o Terraform pode estar tentando provisionar vários índices e/ou criar um documento ao mesmo tempo, e encontrou um erro de simultaneidade.
Tente executar terraform apply
novamente.
Você recebe este erro:
"you may need to specify 'X-Goog-User-Project' HTTP header for quota and
billing purposes"
.
Esse erro significa que o Terraform não sabe em qual projeto deve verificar a cota. Para resolver problemas, verifique o seguinte no bloco resource
:
- Verifique se você especificou um valor para o atributo
project
. - Verifique se você está usando o provedor com
user_project_override = true
(sem alias), em que as amostras do Firebase sãogoogle-beta
.
Ao criar um projeto do Google Cloud, você recebe o erro de que o ID do projeto especificado para o novo projeto já existe.
Confira os possíveis motivos disso:
O projeto associado a esse ID pertence a outra pessoa.
- Para resolver o problema, escolha outro ID.
O projeto associado a esse ID foi excluído recentemente (no estado de exclusão reversível).
- Solução: se você achar que o projeto associado ao ID pertence a você, verifique o estado do projeto usando a API REST
projects.get
.
- Solução: se você achar que o projeto associado ao ID pertence a você, verifique o estado do projeto usando a API REST
O projeto associado a esse ID existe corretamente no usuário atual. Uma causa possível para o erro é a interrupção anterior na execução de
terraform apply
.- Solução: execute os seguintes comandos:
terraform import google_project.default PROJECT_ID
e depois
terraform import google_firebase_project.default PROJECT_ID
- Solução: execute os seguintes comandos:
Por que você precisa provisionar a instância padrão do Cloud Firestore antes do bucket padrão do Cloud Storage?
Se você provisionou o bucket padrão do Cloud Storage (via google_app_engine_application
) antes de tentar provisionar a instância padrão do Cloud Firestore, a instância padrão do Cloud Firestore já estará provisionada. Observação: a instância provisionada do banco de dados está no modo Datastore. Ou seja, ela não pode ser acessada por SDKs do Firebase, autenticação ou Firebase Security Rules. Se você quiser usar o Cloud Firestore com esses serviços do Firebase, esvazie o banco de dados e mude o tipo dele no console do Google Cloud.
Ao tentar provisionar o Cloud Storage (via google_app_engine_application
) e depois a instância padrão do Cloud Firestore, você recebe este erro: Error: Error creating Database: googleapi: Error 409: Database already
exists. Please use another database_id
.
Quando você provisiona o bucket padrão do Cloud Storage de um projeto (via google_app_engine_application
) e o projeto ainda não tem a respectiva instância padrão do Cloud Firestore, google_app_engine_application
provisiona automaticamente a instância padrão do Cloud Firestore do projeto.
Como a instância padrão do Cloud Firestore do seu projeto já está provisionada, google_firestore_database
apresentará um erro se você tentar provisionar explicitamente essa instância padrão novamente.
Depois que a instância padrão do Cloud Firestore do projeto for provisionada, não será possível provisioná-la novamente ou mudar o local dela. Observação: a instância provisionada do banco de dados está no modo Datastore. Ou seja, ela não pode ser acessada por SDKs do Firebase, autenticação ou Firebase Security Rules. Se você quiser usar o Cloud Firestore com esses serviços do Firebase, esvazie o banco de dados e mude o tipo dele no console do Google Cloud.