Skip to content

11 — Service Accounts & IAM

Previous: 10 — Cloud Storage

Service accounts are identities that Cloud Run and other services use to access other GCP resources. This chapter creates the service account and grants it only the permissions it needs.


Principle of least privilege

We follow the principle of least privilege: give each identity only the permissions it needs, nothing more.

Our Cloud Run web service needs: - Secret Manager — read secrets (DATABASE_URL, SECRET_KEY, etc.) - Cloud Storage — read/write static and media buckets

It does NOT need: - Cloud SQL Admin (we're not using Cloud SQL) - Compute Admin (not running VMs) - Full IAM (too broad)


Create service account with Terraform

Add to infrastructure/main.tf:

# Service account for Cloud Run
resource "google_service_account" "run" {
  account_id   = "mycoolproject-run"
  display_name = "MyCoolProject Cloud Run Service Account"
}

# Grant permissions to read secrets
resource "google_project_iam_member" "run_secret_accessor" {
  project = var.project_id
  role    = "roles/secretmanager.secretAccessor"
  member  = "serviceAccount:${google_service_account.run.email}"
}

# Grant permissions to manage storage buckets
resource "google_project_iam_member" "run_storage_admin" {
  project = var.project_id
  role    = "roles/storage.objectAdmin"
  member  = "serviceAccount:${google_service_account.run.email}"
}

# Grant permissions to manage Cloud Tasks
resource "google_project_iam_member" "run_cloudtasks_admin" {
  project = var.project_id
  role    = "roles/cloudtasks.admin"
  member  = "serviceAccount:${google_service_account.run.email}"
}

Run terraform apply to create the service account and permissions.


Service account email format

The service account email will be:

mycoolproject-run@mycoolproject-prod.iam.gserviceaccount.com

This format is used throughout Terraform and gcloud commands to reference the identity.


Service account for Cloud Tasks worker

The Cloud Tasks worker (Cloud Run Job) needs its own permissions to run Django management commands and access secrets:

# Service account for Cloud Tasks worker (background jobs)
resource "google_service_account" "worker" {
  account_id   = "mycoolproject-worker"
  display_name = "MyCoolProject Worker Service Account"
}

# Grant same permissions as web service account
resource "google_project_iam_member" "worker_secret_accessor" {
  project = var.project_id
  role    = "roles/secretmanager.secretAccessor"
  member  = "serviceAccount:${google_service_account.worker.email}"
}

resource "google_project_iam_member" "worker_storage_admin" {
  project = var.project_id
  role    = "roles/storage.objectAdmin"
  member  = "serviceAccount:${google_service_account.worker.email}"
}

resource "google_project_iam_member" "worker_cloudtasks_admin" {
  project = var.project_id
  role    = "roles/cloudtasks.admin"
  member  = "serviceAccount:${google_service_account.worker.email}"
}

IAM roles summary

Service Account Role Why
mycoolproject-run secretmanager.secretAccessor Read secrets (DB, secret key, etc.)
mycoolproject-run storage.objectAdmin Read/write static and media files
mycoolproject-run cloudtasks.admin Enqueue tasks from web service
mycoolproject-worker secretmanager.secretAccessor Read secrets for background jobs
mycoolproject-worker storage.objectAdmin Write processed files if needed
mycoolproject-worker cloudtasks.admin Process tasks from queue

Outputs for service account emails

Add to main.tf:

output "run_service_account_email" {
  value = google_service_account.run.email
}

output "worker_service_account_email" {
  value = google_service_account.worker.email
}

Verify the service accounts

gcloud iam service-accounts list --project=mycoolproject-prod

You should see both mycoolproject-run and mycoolproject-worker.


What we've built so far

After chapters 05-11, Terraform has created: - GCP project with APIs enabled - Artifact Registry repository - Secret Manager secrets (structure, not values) - Cloud Storage buckets (static + media) - Service accounts with IAM permissions

Next: Cloud Run service (the actual web server).