How do you Inject a File from Google Secret Manager into a Google Cloud Run App via Terraform

175 views Asked by At

I am using Terraform to standup my backend and Google Secret Manager to hold my secrets and my Google Service Account file for my app. I am able to inject all my secret values to my app but am unable to inject the secret file to the app.

Question: How should I configure my Terraform so that I can pull a file from Secret Manager in my app? My app looks for a file path and then reads in the file.

This is the block in secret manager main configuration (main.tf) where I am uploading my Google Service Account. I know this works because I see the file contents in my Google Console:

################### GCP Service Account ######################
resource "google_secret_manager_secret" "gcp_service_account" {
  secret_id = "GCP_SERVICE_ACCOUNT"
  replication {
    auto {}
  }
}

resource "google_secret_manager_secret_version" "gcp_service_account_version" {
  secret = google_secret_manager_secret.gcp_service_account.name
  secret_data = file(var.gcp_service_account)
}

Then I output the value like this in my outputs.tf file:

output "gcp_service_account_id" {
  value       = google_secret_manager_secret.gcp_service_account.name
  description = "The ID of the GCP service account"
  sensitive   = true
}

Now I have my output in my root main configuration (main.tf) file I inject the value into my backend module:

module "secret_manager" {
  source      = "./modules/secret_manager"
  db_password = var.db_password
  stripe_key_pub = var.stripe_secret_key
  stripe_key_secret = var.stripe_pub_key
  gcp_service_account = var.gcp_service_account
}

module "backend_app" {
  source = "./modules/backend"
  gke_cluster_name = module.gke_cluster.cluster_name
  project_id = var.project_id
  region = var.region
  app_image = var.app_image

  db_host = module.patshala_db.db_public_ip
  db_name    = var.db_name
  db_user = var.db_user
  db_password = module.secret_manager.db_password_id

  gcp_service_account = module.secret_manager.gcp_service_account_id
  stripe_pub_key      = module.secret_manager.stripe_key_pub_id
  stripe_secret_key   = module.secret_manager.stripe_key_secret_id

  db_port    = var.db_port
  server_port = var.server_port

  depends_on = [module.patshala_db]
}

Later I pass that value in my backend module main configuration (main.tf) like this:

resource "google_cloud_run_service" "backend_service" {
  name     = "backend"
  location = var.region

  template {
    spec {
      containers {
        image = var.app_image

        dynamic "env" {
          for_each = tomap({
            "DB_NAME"             = var.db_name
            "DB_USER"             = var.db_user
            "DB_PASSWORD"         = var.db_password
            "DB_HOST"             = var.db_host
            "DB_PORT"             = var.db_port
            "SERVER_PORT"         = var.server_port
            "STRIPE_PUB_KEY"      = var.stripe_pub_key
            "STRIPE_KEY_SECRET"   = var.stripe_secret_key
            "GCP_SERVICE_ACCOUNT" = var.gcp_service_account
          })
          content {
            name  = env.key
            value = env.value
          }
        }

        liveness_probe {
          http_get {
            path = "/health"
            port = 8000  # Changed to integer
          }
          initial_delay_seconds = 30
          period_seconds        = 30
        }

      }
    }
  }

  autogenerate_revision_name = true  # This is optional but useful if you want Terraform to
}
1

There are 1 answers

0
JacobW On

I would configure the file location as an env variable, and then as the first action in the app, I would fetch the file you need