Skip to content
Intermediate CloudLesson 8 of 13 4 min read

Google Cloud IAM & Service Accounts

Principals, roles, and policy bindings - and why workloads should run as narrowly scoped service accounts, not with keys.

On this page6 sections

Every request to Google Cloud is checked by IAM (Identity and Access Management): who is asking, and does a policy grant them a role that includes the permission they need?

Principals

A principal is whoever receives access. In commands and policies, the type is written as a prefix:

PrefixMeaning
user:alice@example.comA single Google account
group:sre@example.comA Google group, the easiest way to manage teams
serviceAccount:app@PROJECT_ID.iam.gserviceaccount.comA workload's identity
domain:example.comEveryone in a Google Workspace or Cloud Identity domain

Roles

You never grant individual permissions directly. You grant roles, which are bundles of permissions. There are three kinds:

  • Basic roles - Owner, Editor, and Viewer. They span every service and are far too broad. Google's guidance is blunt: in production, do not grant basic roles unless there is no alternative.
  • Predefined roles - maintained by Google for one service and one job, for example roles/storage.objectViewer (read objects in Cloud Storage) or roles/run.invoker (call a Cloud Run service).
  • Custom roles - your own bundle of permissions, for when no predefined role is narrow enough.

Predefined role names look like roles/SERVICE.IDENTIFIER.

Policies and bindings

An allow policy is attached to a resource (an organization, folder, project, or individual resource) and contains bindings. Each binding is a role plus a list of principals. Remember from the fundamentals lesson that policies are inherited down the hierarchy.

bash
gcloud projects add-iam-policy-binding learninx-demo \
  --member='user:alice@example.com' \
  --role='roles/storage.objectViewer'

gcloud projects get-iam-policy learninx-demo

Service accounts

A service account is an identity for software rather than a person: a VM, a Cloud Run service, a CI job. Its email follows the pattern NAME@PROJECT_ID.iam.gserviceaccount.com.

bash
gcloud iam service-accounts create app-runner --display-name="App runner"
gcloud projects add-iam-policy-binding learninx-demo \
  --member='serviceAccount:app-runner@learninx-demo.iam.gserviceaccount.com' \
  --role='roles/storage.objectViewer'

Give each workload its own service account with only the roles it needs. That way a compromised app cannot reach anything beyond its own job.

Avoid service account keys

You can download a JSON key for a service account, but Google warns that keys are a security risk if not managed carefully. A leaked key keeps working until someone revokes it. Prefer the safer options:

  • Attach the service account to the resource (a VM, a Cloud Run service). The workload then receives short-lived credentials automatically, and there is nothing to leak.
  • Use Workload Identity Federation for workloads outside Google Cloud, such as GitHub Actions or another cloud.

Watch the default service accounts

Compute Engine and App Engine create default service accounts that are granted the broad Editor role on the project by default. Google recommends turning off that automatic grant and using dedicated, narrowly scoped service accounts instead.

Try it

Run these in the practice terminal (opens in a new tab). It opens in a new tab, so you keep your place here.
bash
gcloud iam service-accounts create app-runner
gcloud iam service-accounts list
gcloud iam roles describe roles/storage.objectViewer

When you're ready, hit Mark complete and move to the next lesson.

Further reading

Challenge

Create a service account with the ID app-runner for an application to run as.

Want to experiment first? Try things in the practice terminal (opens in a new tab), then enter the command that solves the task here.

Quiz

Lock in the concepts. Score at least 80% to mark the lesson complete.

0 of 3 answered

Done with this one?

Skipped the challenge? You can mark the lesson complete by hand.

Your notes

Kept on this browser only.