Last active
June 17, 2024 09:59
-
-
Save zebreus/906b8870e49586adfe8bd7bbff43f0a8 to your computer and use it in GitHub Desktop.
Terraform configuration for creating a firebase project with firestore, functions and storage
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# firebase.tf https://gist.githubusercontent.com/Zebreus/906b8870e49586adfe8bd7bbff43f0a8/raw/firebase.tf | |
# Terraform configuration for creating a firebase project with firestore, functions and storage | |
# Unfinished | |
terraform { | |
required_providers { | |
google-beta = { | |
source = "hashicorp/google-beta" | |
version = "4.11.0" | |
} | |
null = { | |
version = "~> 3.1.0" | |
} | |
time = { | |
source = "hashicorp/time" | |
version = "0.7.2" | |
} | |
} | |
} | |
variable "billing_account_id" { | |
type = string | |
description = "The id of the associated billing account" | |
nullable = false | |
} | |
variable "project_id" { | |
type = string | |
description = "The id of the created project" | |
nullable = false | |
} | |
variable "project_name" { | |
type = string | |
description = "The name of the created project" | |
nullable = false | |
} | |
variable "region" { | |
type = string | |
description = "The region to create the project in" | |
default = "europe-west1" | |
nullable = false | |
} | |
variable "zone" { | |
type = string | |
description = "The zone to create the project in" | |
default = "europe-west1-b" | |
nullable = false | |
} | |
variable "location" { | |
type = string | |
description = "The location to create the project in" | |
default = "europe-west" | |
nullable = false | |
} | |
locals { | |
bucket_location = "EUROPE-WEST1" | |
} | |
# Basic provider | |
provider "google-beta" { | |
alias = "gcloud-user" | |
region = var.region | |
zone = var.zone | |
} | |
data "google_billing_account" "account" { | |
provider = google-beta.gcloud-user | |
billing_account = var.billing_account_id | |
} | |
data "google_client_config" "gcloud-user" { | |
provider = google-beta.gcloud-user | |
# depends_on = [ | |
# google_service_account.service_account | |
# ] | |
} | |
data "google_client_openid_userinfo" "gcloud-user" { | |
provider = google-beta.gcloud-user | |
} | |
// Create new google cloud project with service account | |
resource "google_project" "default" { | |
provider = google-beta.gcloud-user | |
project_id = var.project_id | |
name = var.project_name | |
billing_account = data.google_billing_account.account.id | |
} | |
resource "google_service_account" "service_account" { | |
provider = google-beta.gcloud-user | |
project = google_project.default.project_id | |
account_id = "terraform" | |
display_name = "Terraform" | |
} | |
# Allow your user to create a access token | |
resource "google_service_account_iam_member" "grant-token-iam" { | |
provider = google-beta.gcloud-user | |
service_account_id = google_service_account.service_account.id | |
role = "roles/iam.serviceAccountTokenCreator" | |
member = "user:${data.google_client_openid_userinfo.gcloud-user.email}" | |
} | |
resource "time_sleep" "delay_token_creation" { | |
depends_on = [ | |
google_service_account_iam_member.grant-token-iam, | |
google_service_account.service_account, | |
google_project_iam_member.firebase-admin-iam, | |
google_project_iam_member.service-usage-admin-iam, | |
google_project_iam_member.appengine-admin-iam, | |
google_project_iam_member.appengine-creator-iam, | |
google_project_iam_member.editor-iam | |
] | |
create_duration = "30s" | |
} | |
# Create access token | |
data "google_service_account_access_token" "default" { | |
provider = google-beta.gcloud-user | |
# project = google_project.default.project_id | |
target_service_account = google_service_account.service_account.email | |
scopes = ["userinfo-email", "cloud-platform"] | |
lifetime = "300s" | |
depends_on = [ | |
google_service_account_iam_member.grant-token-iam, | |
google_service_account.service_account, | |
google_project_iam_member.firebase-admin-iam, | |
google_project_iam_member.service-usage-admin-iam, | |
google_project_iam_member.appengine-admin-iam, | |
google_project_iam_member.appengine-creator-iam, | |
google_project_iam_member.editor-iam, | |
time_sleep.delay_token_creation | |
] | |
} | |
# Give some roles to the service account | |
resource "google_project_iam_member" "firebase-admin-iam" { | |
provider = google-beta.gcloud-user | |
project = google_project.default.project_id | |
role = "roles/firebase.admin" | |
member = "serviceAccount:${google_service_account.service_account.email}" | |
} | |
resource "google_project_iam_member" "service-usage-admin-iam" { | |
provider = google-beta.gcloud-user | |
project = google_project.default.project_id | |
role = "roles/serviceusage.serviceUsageAdmin" | |
member = "serviceAccount:${google_service_account.service_account.email}" | |
} | |
resource "google_project_iam_member" "appengine-admin-iam" { | |
provider = google-beta.gcloud-user | |
project = google_project.default.project_id | |
role = "roles/appengine.appAdmin" | |
member = "serviceAccount:${google_service_account.service_account.email}" | |
} | |
resource "google_project_iam_member" "appengine-creator-iam" { | |
provider = google-beta.gcloud-user | |
project = google_project.default.project_id | |
role = "roles/appengine.appCreator" | |
member = "serviceAccount:${google_service_account.service_account.email}" | |
} | |
resource "google_project_iam_member" "editor-iam" { | |
provider = google-beta.gcloud-user | |
project = google_project.default.project_id | |
role = "roles/editor" | |
member = "serviceAccount:${google_service_account.service_account.email}" | |
} | |
# Create provider with service account | |
resource "google_service_account_key" "mykey" { | |
provider = google-beta.gcloud-user | |
service_account_id = google_service_account.service_account.id | |
# Wait for the account being added to roles | |
depends_on = [ | |
google_project_iam_member.firebase-admin-iam, | |
google_project_iam_member.service-usage-admin-iam, | |
] | |
} | |
provider "google-beta" { | |
alias = "service-account" | |
project = google_project.default.project_id | |
region = var.region | |
zone = var.zone | |
# impersonate_service_account = google_service_account.service_account.email | |
# credentials = base64decode(google_service_account_key.mykey.private_key) | |
access_token = data.google_service_account_access_token.default.access_token | |
} | |
# Activate all required apis | |
resource "google_project_service" "serviceusage" { | |
provider = google-beta.gcloud-user | |
project = google_project.default.project_id | |
service = "serviceusage.googleapis.com" | |
disable_dependent_services = true | |
depends_on = [ | |
] | |
} | |
resource "google_project_service" "firebase" { | |
provider = google-beta.service-account | |
project = google_project.default.project_id | |
service = "firebase.googleapis.com" | |
disable_dependent_services = true | |
depends_on = [ | |
google_project_service.serviceusage | |
] | |
} | |
resource "google_project_service" "firestore" { | |
provider = google-beta.service-account | |
project = google_project.default.project_id | |
service = "firestore.googleapis.com" | |
depends_on = [ | |
google_project_service.serviceusage | |
] | |
} | |
resource "google_project_service" "firebasestorage" { | |
provider = google-beta.service-account | |
project = google_project.default.project_id | |
service = "firebasestorage.googleapis.com" | |
depends_on = [ | |
google_project_service.serviceusage | |
] | |
} | |
resource "google_project_service" "cloudresourcemanager" { | |
provider = google-beta.service-account | |
project = google_project.default.project_id | |
service = "cloudresourcemanager.googleapis.com" | |
depends_on = [ | |
google_project_service.serviceusage | |
] | |
} | |
resource "google_project_service" "identitytoolkit" { | |
provider = google-beta.service-account | |
project = google_project.default.project_id | |
service = "identitytoolkit.googleapis.com" | |
depends_on = [ | |
google_project_service.serviceusage | |
] | |
} | |
resource "google_project_service" "compute" { | |
provider = google-beta.service-account | |
project = google_project.default.project_id | |
service = "compute.googleapis.com" | |
depends_on = [ | |
google_project_service.serviceusage | |
] | |
} | |
resource "google_project_service" "container_registry" { | |
provider = google-beta.service-account | |
project = google_project.default.project_id | |
service = "containerregistry.googleapis.com" | |
disable_dependent_services = true | |
depends_on = [ | |
google_project_service.serviceusage | |
] | |
} | |
resource "google_project_service" "cloud_run" { | |
provider = google-beta.service-account | |
project = google_project.default.project_id | |
service = "run.googleapis.com" | |
depends_on = [ | |
google_project_service.serviceusage | |
] | |
} | |
resource "google_project_service" "cloud_build" { | |
provider = google-beta.service-account | |
project = google_project.default.project_id | |
service = "cloudbuild.googleapis.com" | |
depends_on = [ | |
google_project_service.serviceusage | |
] | |
} | |
# Create firebase project | |
resource "google_firebase_project" "default" { | |
provider = google-beta.service-account | |
project = google_project.default.project_id | |
depends_on = [ | |
google_project_service.firebase | |
] | |
} | |
# Create firebase web app | |
resource "google_firebase_web_app" "basic" { | |
provider = google-beta.service-account | |
project = google_project.default.project_id | |
display_name = "${var.project_name} App" | |
depends_on = [ | |
google_firebase_project.default | |
] | |
} | |
data "google_firebase_web_app_config" "basic" { | |
provider = google-beta.service-account | |
web_app_id = google_firebase_web_app.basic.app_id | |
} | |
# Create firestore database | |
resource "google_app_engine_application" "app" { | |
provider = google-beta.service-account | |
# provider = google-beta.gcloud-user | |
project = google_project.default.project_id | |
location_id = var.location | |
database_type = "CLOUD_FIRESTORE" | |
depends_on = [ | |
google_project_iam_member.appengine-admin-iam, | |
google_project_iam_member.appengine-creator-iam, | |
google_project_service.firestore | |
] | |
} | |
# Create a bucket for backups | |
resource "google_storage_bucket" "backup" { | |
provider = google-beta.service-account | |
project = google_project.default.project_id | |
name = "${google_project.default.project_id}-backup" | |
location = local.bucket_location | |
} | |
# Create admin-sdk service account | |
resource "google_service_account" "admin_sdk" { | |
provider = google-beta.gcloud-user | |
project = google_project.default.project_id | |
account_id = "firebase-adminsdk-ouwu6" | |
display_name = "firebase-adminsdk" | |
} | |
resource "google_project_iam_member" "admin-sdk-token-creator" { | |
provider = google-beta.gcloud-user | |
project = google_project.default.project_id | |
role = "roles/iam.serviceAccountTokenCreator" | |
member = "serviceAccount:${google_service_account.admin_sdk.email}" | |
} | |
resource "google_project_iam_member" "admin-sdk-agent" { | |
provider = google-beta.gcloud-user | |
project = google_project.default.project_id | |
role = "roles/firebase.sdkAdminServiceAgent" | |
member = "serviceAccount:${google_service_account.admin_sdk.email}" | |
} | |
resource "google_service_account_key" "admin_sdk" { | |
provider = google-beta.gcloud-user | |
service_account_id = google_service_account.service_account.id | |
# Wait for the account being added to roles | |
depends_on = [ | |
google_project_iam_member.admin-sdk-token-creator, | |
google_project_iam_member.admin-sdk-agent, | |
] | |
} | |
# Create firebase storage | |
resource "null_resource" "activate_storage" { | |
triggers = { | |
bucket = data.google_firebase_web_app_config.basic.storage_bucket | |
} | |
provisioner "local-exec" { | |
command = "curl -X POST -H 'Authorization: Bearer ${nonsensitive(data.google_service_account_access_token.default.access_token)}' -H 'Content-Type: application/json' 'https://firebasestorage.googleapis.com/v1beta/projects/${google_project.default.project_id}/buckets/${data.google_firebase_web_app_config.basic.storage_bucket}:addFirebase'" | |
interpreter = ["sh", "-c"] | |
} | |
depends_on = [ | |
google_firebase_web_app.basic, | |
google_project_service.firebasestorage | |
] | |
} | |
# Enable authentication service | |
resource "google_identity_platform_config" "identity_platform_config" { | |
provider = google-beta.service-account | |
project = google_project.default.project_id | |
autodelete_anonymous_users = true | |
depends_on = [ | |
google_firebase_web_app.basic, | |
google_project_service.identitytoolkit | |
] | |
} | |
resource "google_identity_platform_project_default_config" "identity_project_config" { | |
provider = google-beta.service-account | |
project = google_project.default.project_id | |
sign_in { | |
allow_duplicate_emails = false | |
email { | |
enabled = true | |
password_required = true | |
} | |
} | |
depends_on =[google_identity_platform_config.identity_platform_config] | |
} | |
# Write secrets to local file | |
resource "local_file" "firebase_config" { | |
content = jsonencode({ | |
firebase = { | |
appId = google_firebase_web_app.basic.app_id | |
apiKey = data.google_firebase_web_app_config.basic.api_key | |
authDomain = data.google_firebase_web_app_config.basic.auth_domain | |
databaseURL = lookup(data.google_firebase_web_app_config.basic, "database_url", "") | |
storageBucket = lookup(data.google_firebase_web_app_config.basic, "storage_bucket", "") | |
messagingSenderId = lookup(data.google_firebase_web_app_config.basic, "messaging_sender_id", "") | |
measurementId = lookup(data.google_firebase_web_app_config.basic, "measurement_id", "") | |
} | |
}) | |
filename = "${path.module}/firebase-config.json" | |
depends_on = [ | |
google_firebase_web_app.basic | |
] | |
} | |
resource "local_file" "secrets_file" { | |
content = jsonencode({ | |
private = { | |
serviceAccount = jsondecode(base64decode(google_service_account_key.admin_sdk.private_key)) | |
firebase = { | |
backupBucket = google_storage_bucket.backup.name | |
} | |
} | |
public = { | |
firebase = { | |
projectId = google_project.default.project_id | |
appId = google_firebase_web_app.basic.app_id | |
apiKey = data.google_firebase_web_app_config.basic.api_key | |
authDomain = data.google_firebase_web_app_config.basic.auth_domain | |
databaseURL = lookup(data.google_firebase_web_app_config.basic, "database_url", "") | |
storageBucket = lookup(data.google_firebase_web_app_config.basic, "storage_bucket", "") | |
messagingSenderId = lookup(data.google_firebase_web_app_config.basic, "messaging_sender_id", "") | |
measurementId = lookup(data.google_firebase_web_app_config.basic, "measurement_id", "") | |
} | |
} | |
}) | |
filename = "${path.module}/secrets.json" | |
depends_on = [ | |
google_firebase_web_app.basic | |
] | |
} | |
resource "local_file" "firebaserc" { | |
content = jsonencode({ | |
projects = { | |
development = google_project.default.project_id | |
production = google_project.default.project_id | |
} | |
}) | |
filename = "${path.module}/.firebaserc" | |
depends_on = [ | |
google_project.default | |
] | |
} | |
resource "local_file" "admin_config" { | |
content = base64decode(google_service_account_key.mykey.private_key) | |
filename = "${path.module}/admin-config.json" | |
depends_on = [ | |
google_service_account_key.mykey, | |
google_firebase_web_app.basic | |
] | |
} |
Just wondering if anyone has run into this issue with the latest version of this gist:
╷
│ Error: Invalid resource type
│
│ on main.tf line 363, in resource "google_identity_platform_config" "identity_platform_config":
│ 363: resource "google_identity_platform_config" "identity_platform_config" {
│
│ The provider hashicorp/google-beta does not support resource type "google_identity_platform_config".
I pulled the google_identity_platform_config.identity_platform_config
resource into my own script, dropped the provider = google-beta
instruction (as of v4.66.0, you don't need the beta provider), and it worked fine for me.
This gist is super helpful, thank you! FYI, setting authorized domains is now supported: https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/identity_platform_config#authorized_domains
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@zebreus I figured Identity Platform was one of the APIs independent from firebase, so you can open it in the GCP console and see what is missing. And you can find what can be configured in the terraform doc.