Imaging when I needed to grant access to a Google storage bucket for a list of Google service accounts, I put the list in YAML like this:
# data/gcs.yaml google-service-accounts: - gaia@horizon.iam.gserviceaccount.com - nova@horizon.iam.gserviceaccount.com - cyan@horizon.iam.gserviceaccount.com - edi@mass-effect.iam.gserviceaccount.com ...
Assuming horizon is the default GCP project and mass-effect is a partner project and most GSAs are of course from the default project. So can this list be DRYed up a bit like this?
# data/gcs.yaml google-service-accounts: - gaia - nova - cyan - edi@mass-effect ... default: project: horizon
The terraform code to read this YAML and grant IAM members could look like:
locals {
  manifest = yamldecode(file("./data/gcs.yaml"))
}
resource "google_storage_bucket" "default" {
  ...
}
resource "google_storage_bucket_iam_binding" "default_readers" {
  bucket  = google_storage_bucket.default.name
  role    = "roles/storage.objectViewer"
  members = formatlist(
    "serviceAccount:%s",
    [for member in local.manifest['google-service-accounts'] : format("%s@%s.iam.gserviceaccount.com", split("@", member)[0], try(split("@", member)[1], local.manifest.default.project))]
  )
}A quick explanation on how this works:
# for item `gaia`
split("@", "gaia") -> ["gaia"]
split("@", "gaia")[0] -> "gaia"
split("@", "gaia")[1] -> error # doesn't exist
try(split("@", "gaia")[1], "horizon") -> "horizon"
format("%s@%s.iam.gserviceaccount.com", ...) -> "gaia@horizon.iam.gserviceaccount.com"
# for item edi@mass-effect
split("@", "edi@mass-effect") -> ["edi", "mass-effect"]
split("@", "edi@mass-effect")[0] -> "edi"
split("@", "edi@mass-effect")[1] -> "mass-effect"
try(split("@", "edi@mass-effect")[1], "horizon") -> "mass-effect"
format("%s@%s.iam.gserviceaccount.com", ...) -> "edi@mass-effect.iam.gserviceaccount.com"PS. yes I like the Horizon and Mass Effect games. 🙂
