GCP IAM Guide
IAM Roles
| Role Type | Description | Examples |
|---|---|---|
| Basic roles | Coarse-grained legacy roles | roles/viewer, roles/editor, roles/owner |
| Predefined roles | Curated by Google for specific services | roles/storage.objectAdmin, roles/container.developer |
| Custom roles | User-defined with specific permissions | projects/my-proj/roles/myCustomRole |
# List predefined roles for a service
gcloud iam roles list --filter="name:roles/storage"
# Create custom role
gcloud iam roles create myCustomRole \
--project=my-project \
--title="My Custom Role" \
--permissions=storage.objects.get,storage.objects.list \
--stage=GA
# Update custom role
gcloud iam roles update myCustomRole \
--project=my-project \
--add-permissions=storage.buckets.get
Policy Bindings
# Add single binding (non-destructive)
gcloud projects add-iam-policy-binding my-project \
--member="user:alice@example.com" \
--role="roles/storage.objectViewer"
# Add with condition
gcloud projects add-iam-policy-binding my-project \
--member="serviceAccount:sa@my-project.iam.gserviceaccount.com" \
--role="roles/compute.instanceAdmin" \
--condition='expression=resource.name.startsWith("projects/my-project/zones/us-central1"),title=ZoneRestriction'
# Get full IAM policy
gcloud projects get-iam-policy my-project --format=json
# Set full policy (replace entire policy)
gcloud projects set-iam-policy my-project policy.json
# Remove binding
gcloud projects remove-iam-policy-binding my-project \
--member="user:alice@example.com" \
--role="roles/storage.objectViewer"
Service Accounts
# Create service account
gcloud iam service-accounts create deploy-sa \
--display-name="Deployment SA"
# Grant SA access to project
gcloud projects add-iam-policy-binding my-project \
--member="serviceAccount:deploy-sa@my-project.iam.gserviceaccount.com" \
--role="roles/run.developer"
# Allow user to impersonate SA (Service Account Token Creator)
gcloud iam service-accounts add-iam-policy-binding \
deploy-sa@my-project.iam.gserviceaccount.com \
--member="user:alice@example.com" \
--role="roles/iam.serviceAccountTokenCreator"
# Create key (avoid if possible, use Workload Identity instead)
gcloud iam service-accounts keys create key.json \
--iam-account=deploy-sa@my-project.iam.gserviceaccount.com
# List keys
gcloud iam service-accounts keys list \
--iam-account=deploy-sa@my-project.iam.gserviceaccount.com
Workload Identity Federation
# Create workload identity pool
gcloud iam workload-identity-pools create github-pool \
--project=my-project \
--location=global \
--display-name="GitHub Actions Pool"
# Create OIDC provider (GitHub Actions)
gcloud iam workload-identity-pools providers create-oidc github-provider \
--project=my-project \
--location=global \
--workload-identity-pool=github-pool \
--display-name="GitHub" \
--attribute-mapping="google.subject=assertion.sub,attribute.repository=assertion.repository" \
--issuer-uri="https://token.actions.githubusercontent.com"
# Bind SA to WIF pool
gcloud iam service-accounts add-iam-policy-binding \
deploy-sa@my-project.iam.gserviceaccount.com \
--role="roles/iam.workloadIdentityUser" \
--member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/github-pool/attribute.repository/my-org/my-repo"
Audit Logs
# Query audit logs via gcloud
gcloud logging read \
'logName="projects/my-project/logs/cloudaudit.googleapis.com%2Factivity" AND protoPayload.methodName="storage.objects.delete"' \
--limit=50 \
--format=json
# Enable data access audit logs (via IAM policy JSON)
{
"auditConfigs": [{
"service": "storage.googleapis.com",
"auditLogConfigs": [
{"logType": "DATA_READ"},
{"logType": "DATA_WRITE"}
]
}]
}
# Export logs to BigQuery
gcloud logging sinks create my-bq-sink \
bigquery.googleapis.com/projects/my-project/datasets/audit_logs \
--log-filter='logName:"cloudaudit.googleapis.com"'