Skip to main content

Service identity & authentication

Exam guide§2.1

A Cloud Run service has two IAM-related sides. Access & networking covered the inbound side - who may invoke the service. This page is the outbound side: the identity your code runs as when it calls other Google Cloud services (Pub/Sub, Cloud SQL, Cloud Storage, ...).

Google client libraries running in your container automatically use this service identity to authenticate their API calls, and IAM authorizes each call against it.

The default service account is a risk

If you deploy a service (or job) without specifying a service account, Cloud Run runs it as the Compute Engine default service account, which carries the broad Editor basic role on the project.

Cloud Run serviceYour codeDefault service accountRole: EditorGoogle Cloud projectGoogle Cloud resourcesCloud SQL instanceCloud Run serviceCloud Storage bucketCreate, change, and delete resources
A Cloud Run service with no service account set runs as the default (Compute Engine) service account, whose broad Editor role lets your code create, change, and delete most resources in the project.

Because of policy-binding inheritance, that identity has read/write access to most resources in the project - it can create, modify, or delete them.

GotchaDefault service account = broad Editor

Convenient, but an inherent security risk: any code (or dependency) running in your container inherits Editor across the whole project. Newer orgs disable the automatic Editor grant via the iam.automaticIamGrantsForDefaultServiceAccounts org policy. See Service accounts.

Use the principle of least privilege

In production, replace the default identity with a dedicated, user-managed service account granted only the roles it needs:

NumbersLock down the service identity
  1. Create a new user-managed service account for the service (console or gcloud).
  2. Configure it as the Cloud Run service's identity - set at create, update, or new-revision deploy time (console, gcloud CLI, YAML, or Terraform).
  3. Grant it predefined or custom roles, bound on the specific resources the service must reach. A brand-new SA appears in no policy binding, so every API call it makes is rejected by IAM until you add one.
CommandsAssign a per-service identity and grant it access
# 1. Create the service account
gcloud iam service-accounts create my-service-account
 
# 2. Set it as the service's identity at deploy time
gcloud run deploy my-service --image my-image \
--service-account my-service-account@PROJECT_ID.iam.gserviceaccount.com
 
# 3. Grant a predefined role on the target resource (not the whole project)
# e.g. let the service publish to one Pub/Sub topic
gcloud pubsub topics add-iam-policy-binding my-topic \
--member="serviceAccount:my-service-account@PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/pubsub.publisher"

That command is the third step drawn out: the service account is the member, roles/pubsub.publisher is the role, and the binding lives in the IAM policy attached to the topic - so the service is authorized to publish.

Cloud Run Servicemy-service-accountPolicy BindingPub/Sub PublisherIAM PolicyPub/Sub topic my-topicAuthorized to publish messagesIdentityMemberRolePart of
Granting the service account the Pub/Sub Publisher role via a policy binding on the topic authorizes the Cloud Run service to publish messages - a worked instance of the member + role + resource model.

The role kinds (basic vs predefined vs custom) and the policy-binding model (member + role + permissions, attached to a resource) are the generic IAM machinery - see Roles and Members & Policies.

Calling Google Cloud APIs

When your application code uses a client library to call a Google API (say, publishing to a Pub/Sub topic), the library automatically acquires a token using the runtime service account - no keys in your code. For most Google APIs this is an OAuth 2.0 access token.

Cloud Run serviceContainerApplication codeClient libraryService accountAccess tokenIAMIAM policyattached tohttps://pubsub.googleapis.comGoogle CloudPub/Sub APIPub/Sub TopicCallAuthenticate withAPI callPublish messageCheck IAM policy
A Cloud Run service authenticates outbound API calls with its runtime service account: the client library acquires an OAuth 2.0 access token, IAM verifies it against the policy on the target Pub/Sub topic.

The access token travels with the API call. IAM verifies the token, reads the identity it carries, and checks whether the IAM policy on the target resource grants that identity the required role - the same authorization model as any other caller.

Service-to-service communication

When an architecture uses multiple Cloud Run services, they often call one another, and private services need credentials.

CompareAsync vs sync
AsynchronousDecouple services through a messaging or eventing product: Cloud Tasks, Pub/Sub, Cloud Scheduler, or Eventarc.
SynchronousThe calling service calls the receiving service's endpoint URL directly over HTTP.

Give the calling service its own service account with the minimal roles required.

For a synchronous call, make the calling service's service account a principal on the receiving service and grant it the Cloud Run Invoker (roles/run.invoker) role:

CommandsAuthorize a calling service to invoke a receiving service
gcloud run services add-iam-policy-binding RECEIVING_SERVICE \
--member='serviceAccount:CALLING_SERVICE_IDENTITY' \
--role='roles/run.invoker'

The request must prove that identity with a Google-signed OpenID Connect (OIDC) ID token. OIDC is an identity protocol built on OAuth 2.0 that lets one service verify another's identity. The calling service's code acquires the ID token via Google's auth client libraries; the receiving service uses the same libraries to parse the request and verify the token.

Calling serviceContainerApplication codeClient libraryService accountID tokenID tokenIAMIAM policyattached tohttps://svc.urlReceiving serviceApplication codeClient libraryCallAuthenticate withAPI callCheck IAM policy
Synchronous service-to-service calls authenticate with a Google-signed OpenID Connect ID token: the calling service presents it, IAM verifies the policy, and the receiving service can parse and verify the token.
GotchaID token vs access token

Calling a Google API (Pub/Sub, Storage, ...) uses an OAuth 2.0 access token. Invoking another Cloud Run service over HTTP uses a Google-signed OIDC ID token - and the caller still needs roles/run.invoker on the receiving service. Don't mix them up.

Recap

NumbersRemember
  • A Cloud Run service always has access to a default service account.
  • Google client libraries use that identity to call Google Cloud APIs.
  • The default (Compute Engine) SA has the Editor basic role - broad permissions across all services.
  • In production, replace it with a user-managed, per-service account holding only predefined/custom roles on the resources it needs.
  • Outbound calls to a Google API use an OAuth 2.0 access token; a synchronous service-to-service call uses a Google-signed OIDC ID token plus roles/run.invoker on the receiver.
  • For async service-to-service, use Cloud Tasks, Pub/Sub, Cloud Scheduler, or Eventarc.