LAB04_GCP_Identity and Access Management: Service Accounts & Bindings

Identity and Access Management: Service Accounts & Bindings

☁ GCP 🟢 Beginner IAM Service Account IAM Binding

Scenario

In Google Cloud, applications and resources authenticate using Service Accounts rather than human user credentials. You need to create a service account designated for an application that needs to read from Google Cloud Storage, and assign it the appropriate storage object viewer role at the project level.

Your Objectives
  • Create a google_service_account for your data-reader application.
  • Assign the roles/storage.objectViewer role to the service account using a google_project_iam_member resource.
  • Output the email address of the generated service account.

Additional Context

IAM Member vs Binding vs Policy:

  • google_project_iam_member adds a single role to a single user non-destructively. (Best for automation).
  • google_project_iam_binding manages all members for a specific role. Anyone not in your Terraform code will be removed from that role.
  • google_project_iam_policy assumes complete authority over all IAM roles at the project. It removes anything you didn't define.
You should almost always prefer iam_member to prevent accidentally revoking someone else's access.

variables.tf

variable "project_id" { type = string }

main.tf

provider "google" {
  project = var.project_id
}

# Create the Service Account
resource "google_service_account" "app_sa" {
  account_id   = "app-data-reader"
  display_name = "Application Data Reader SA"
  description  = "Service account for the app to read GCS datasets"
}

# Grant the Service Account read access to Cloud Storage across the project
# Use _member, NOT _binding or _policy to avoid overwriting existing permissions
resource "google_project_iam_member" "sa_storage_viewer" {
  project = var.project_id
  role    = "roles/storage.objectViewer"

  # GCP expects the member to be prefixed with the account type
  member  = "serviceAccount:${google_service_account.app_sa.email}"
}

outputs.tf

output "service_account_email" {
  value = google_service_account.app_sa.email
}

Workflow Commands

terraform init
terraform apply -var="project_id=my-gcp-project-123"

# Verify the IAM policy binding on the project
gcloud projects get-iam-policy my-gcp-project-123 \
  --flatten="bindings[].members" \
  --format='table(bindings.role)' \
  --filter="bindings.members:$(terraform output -raw service_account_email)"

terraform destroy -var="project_id=my-gcp-project-123"
✓ Expected Output After Apply
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

Outputs:

service_account_email = "[email protected]"