LAB34_GCP_Multi-Project Security: Cross-Project IAM and Storage

Multi-Project Security: Cross-Project IAM and Storage

☁ GCP 🔥 Intermediate IAM Cloud Storage Cross-Project

Scenario

An application running in your "App Project" needs to securely read analytics data stored in a Cloud Storage bucket located in your completely separate "Data Project". You will provision a Service Account in Project A, create a Bucket in Project B, and use Terraform's ability to manage resources across multiple projects via provider aliases to grant the precise IAM role needed.

Your Objectives
  • Define two distinct Google providers using the alias meta-argument.
  • Create a google_service_account in the "App" project.
  • Create a google_storage_bucket in the "Data" project.
  • Create a google_storage_bucket_iam_member binding that lives in the "Data" project, granting `roles/storage.objectViewer` to the Service Account that lives in the "App" project.

Additional Context

Provider Aliases: When executing Terraform, you usually declare one `provider "google"` block pointing to your primary project. To manage resources in a secondary project simultaneously, you define a second `provider "google"` block mapped to a new alias (`alias = "data_project"`). When creating resources for the second project, you must explicitly inject `provider = google.data_project`.

IAM Federation: In GCP, IAM Principals (like Service Accounts) are globally routable via their exact email address string. A bucket in Project B can seamlessly grant permissions to `[email protected]`.

variables.tf

variable "app_project_id"  { type = string }
variable "data_project_id" { type = string }

main.tf

# The Default Provider (Project A)
provider "google" {
  project = var.app_project_id
  region  = "us-central1"
}

# The Alias Provider (Project B)
provider "google" {
  alias   = "data"
  project = var.data_project_id
  region  = "us-central1"
}

# 1. Identity lives in the App Project (Uses Default Provider)
resource "google_service_account" "app_sa" {
  account_id   = "app-workload-runner"
  display_name = "Application Service Account"
}

# 2. Storage Bucket lives in the Data Project (Uses Alias Provider)
resource "random_id" "bkt" { byte_length = 4 }

resource "google_storage_bucket" "analytics_bucket" {
  # Explicitly tell Terraform to use the data project provider credentials
  provider = google.data
  
  name     = "corporate-analytics-${random_id.bkt.hex}"
  location = "US"
}

# 3. Apply the IAM rule IN the Data Project, granting access TO the App Project SA
resource "google_storage_bucket_iam_member" "cross_project_read" {
  # The IAM resource MUST exist in the same provider as the bucket
  provider = google.data

  bucket   = google_storage_bucket.analytics_bucket.name
  role     = "roles/storage.objectViewer"
  
  # Interpolate the email string dynamically
  member   = "serviceAccount:${google_service_account.app_sa.email}"
}

Workflow Commands

terraform init

# Make sure the user executing Terraform has sufficient IAM privileges in BOTH projects
terraform apply \
  -var="app_project_id=app-dev-111" \
  -var="data_project_id=data-bureau-222"

terraform destroy \
  -var="app_project_id=app-dev-111" \
  -var="data_project_id=data-bureau-222"