Skip to content

Instantly share code, notes, and snippets.

@phlummox
Forked from zebreus/firebase.tf
Created January 12, 2023 11:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save phlummox/514de91dafc2ac7f20b97cbbf2748804 to your computer and use it in GitHub Desktop.
Save phlummox/514de91dafc2ac7f20b97cbbf2748804 to your computer and use it in GitHub Desktop.
Terraform configuration for creating a firebase project with firestore, functions and storage
# 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
]
}
# 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
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment