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:
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
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).
Navigation
- 01 — Introduction: What We're Building
- 02 — Terraform Overview
- 03 — Cloud Services Explained
- 04 — PlanetScale Database Explained
- 05 — Project Setup & Terraform State
- 06 — GCP Project & APIs
- 07 — Artifact Registry
- 08 — Secrets Management
- 09 — Cloud Storage
- 10 — Service Accounts & IAM (Current chapter)
- 11 — Cloud Run
- 12 — Cloud Tasks & Scheduler
- 13 — Dockerfile
- 14 — First Deploy
- 15 — Custom Domain & SSL
- 16 — Workload Identity Federation
- 17 — GitHub Actions CI/CD
- 18 — Quick Reference