firebasegoogle-cloud-platformfirebase-authenticationterraformfirebase-admin

How to generate AdminSDK (ADC) credentials for firebase auth using terraform?


i lastly tried to setup a google project using terraform with a backend that should consume a firebase auth instance for verification. Herefor i need a credentials file that is usually generated in the firebase web console Project Settings > Service Accounts > Firebase Admin SDK > Generate new private key.

As i want to automatise retrieving that file I was looking on how to generate that file on my own by using terraform, but i did not find any documentation for that. The file structure looks like

{
  "auth_provider_x509_cert_url":
  "auth_uri":
  "client_email":
  "client_id":
  "client_x509_cert_url":
  "private_key":
  "private_key_id":
  "project_id":
  "token_uri":
  "type":
  "universe_domain":
}

In the project I would set an env variable with GOOGLE_APPLICATION_CREDENTIALS="/firebase-service-account.json" to tell where to find my credential file.

In my terraform file i do something like

resource "google_service_account" "sa_backend_firebase_adminsdk" {
 account_id     = "sa-backend-firebase-adminsdk"
 display_name   = "Backend Firebase SDK SA"
 project        = var.GCLOUD_PROJECT_ID
}

resource "google_service_account_key" "sa_backend_firebase_adminsdk_key" {
  service_account_id  = google_service_account.sa_backend_firebase_adminsdk.name
  private_key_type    =   "TYPE_GOOGLE_CREDENTIALS_FILE"
}


locals {
  private_key_id = split("/", google_service_account_key.sa_backend_firebase_adminsdk_key.id)[5]
  service_key_account_json = jsonencode({
    type                        = "service_account",
    project_id                  = "${var.GCLOUD_PROJECT_ID}",
    private_key_id              = "${local.private_key_id}",
    private_key                 = "-----BEGIN PRIVATE KEY-----\n${google_service_account_key.sa_backend_firebase_adminsdk_key.private_key}\n-----END PRIVATE KEY-----\n",
    client_email                = "${google_service_account.sa_backend_firebase_adminsdk.email}",
    client_id                   = "${google_service_account.sa_backend_firebase_adminsdk.unique_id}",
    auth_uri                    = "https://accounts.google.com/o/oauth2/auth",
    token_uri                   = "https://oauth2.googleapis.com/token",
    auth_provider_x509_cert_url = "https://www.googleapis.com/oauth2/v1/certs",
    client_x509_cert_url        = "https://www.googleapis.com/robot/v1/metadata/x509/${google_service_account.sa_backend_firebase_adminsdk.email}",
    universe_domain             = "googleapis.com"
  })
}



resource "local_sensitive_file" "sa_backend_firebase_adminsdk_private_key_file" {
  content  = local.service_key_account_json
  filename = "${path.module}/${var.GCLOUD_PROJECT_NAME}-private-key.json"
}

Finally I have two granular additional question to that, because they might cause the process not to work:

  1. the OG firebase admin SDK file includes for client_x509_cert_url https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-`39pwf%40m` whereas my generated file includes https://www.googleapis.com/robot/v1/metadata/x509/sa-backend-firebase-adminsdk`@`
  2. the OG private key is separated by \n and has a completely different length than the one i generate.
  3. Is the AdminSDK file of the service account equal to the ADC (=Application Default Credentials) referenced by google, and is the provided json format the correct format to fulfill the ADC-file requirements ? (As i did not find any docs on that)

Solution

  • You don't need to invent this yourself, terraform already has this data in the resource you used to create a key file: https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_service_account_key#private_key-1

    You probably need something like this:

    resource "google_service_account" "sa" {
      account_id = var.sa_name
    }
    
    resource "google_service_account_key" "sa_key" {
      service_account_id = google_service_account.sa.email
    }
    
    output "trigger_screening_key" {
      value = base64decode(google_service_account_key.sa_key.private_key)
      sensitive = true
    }
    

    Note the warning on top about the private key being stored in plaintext in your statefile though.

    As for question 3: yes, that json file you'll get as an output can be used as input for ADC, for most client libs this is done by setting the env GOOGLE_APPLICATION_CREDENTIALS to the absolute path of the file. I'm not sure if the firebase admin SDK also supports that, if not you'll probably need to pass the path somewhere at initialization.