logo

GCP - Project-Level IAM Binding vs Resource-Level IAM Binding

Project-Level IAM Bindings

A project-level IAM binding grants a role to a principal (like a service account) for all resources within that Google Cloud project. This is a broad, inherited permission. If you grant a service account the roles/run.jobsExecutor role at the project level, it can execute any Cloud Run job in that project.

The command for this is:

gcloud projects add-iam-policy-binding ${PROJECT_ID} --member="serviceAccount:${SERVICE_ACCOUNT_EMAIL}" --role="${ROLE}"

Resource-Level IAM Bindings

A resource-level binding, on the other hand, grants a role to a principal for a specific, single resource. For Cloud Run jobs, this is a particular job instance. Granting a service account a role at this level gives it permissions only for that specific job, not for any others in the project.

The command for this is:

gcloud run jobs add-iam-policy-binding ${JOB_NAME} --member="serviceAccount:${SERVICE_ACCOUNT_EMAIL}" --role="${ROLE}"

Get All Resource-Level IAM Bindings

It is easy to get all Project-Level IAM Bindings with

gcloud projects get-iam-policy ${PROJECT_ID}

To get all Resource-Level IAM Bindings, use Cloud Asset Inventory API:

gcloud asset search-all-iam-policies \
    --scope=projects/${PROJECT_ID} \
    --query="policy:${SERVICE_ACCOUNT_EMAIL}" \
    --format="table(asset_type,policy.bindings.role,resource)"

If your Cloud Asset Inventory API is not enabled, it will first ask you to enable it:

API [cloudasset.googleapis.com] not enabled on project [PROJECT_ID]. Would you like to enable and retry (this will take a few minutes)? (y/N)?