Happy Dussehra! May good always win. Happy Diwali! Wishing you a bright year ahead. Merry Christmas! Warm wishes from Vizag. Happy New Year! Here’s to a great year ahead.

Archive · GCP

GCP Basics: Projects, IAM and the gcloud CLI

How Google Cloud organises resources and access: the resource hierarchy, IAM roles and inheritance, service accounts, workload identity federation and a sensible first setup.

3 min read

  • Google Cloud
  • gcloud CLI
  • Cloud IAM
  • Workload Identity Federation
  • Organization Policy

Before launching anything on Google Cloud, learn how resources and access are organised. Most early mistakes (a shared project with everyone as Owner, a downloaded service account key in a repository) come from skipping this step.

The resource hierarchy

flowchart TB
  ORG[Organization<br/>example.com] --> FP[Folder production]
  ORG --> FN[Folder non-production]
  ORG --> FS[Folder shared services]
  FP --> P1[Project shop-prod]
  FN --> P2[Project shop-dev]
  FN --> P3[Project shop-test]
  FS --> P4[Project logging and monitoring]
  P1 --> R1[Resources<br/>VMs buckets databases]
  BA[Billing account] -.->|linked to| P1
  BA -.-> P2
  POL[IAM policies and<br/>organization policies] -.->|inherited downwards| FP

The project is the main unit of billing, API enablement and permissions, similar to an AWS account. Project IDs are globally unique, between 6 and 30 characters, and cannot be reused. A deleted project stays recoverable for 30 days.

GCP AWS idea Note
Organization, folders AWS Organizations, OUs Policies set here are inherited by everything below
Project Account Boundary for billing, quotas and APIs
IAM role bound to a principal on a resource Policy attached to a principal GCP attaches the binding to the resource
Service account IAM role / machine identity An identity for workloads, with its own email
Region asia-south1 (Mumbai), asia-south2 (Delhi) ap-south-1 Pick regions near users and data rules

IAM policies are additive and inherited: a role granted on a folder applies to every project below it, and permissions granted lower cannot be removed by a lower policy. Deny policies and Organization Policy constraints (for example, restricting regions or blocking service account key creation) are the tools for hard limits.

First setup with the gcloud CLI

curl https://sdk.cloud.google.com | bash && exec -l $SHELL
gcloud init
gcloud auth login
gcloud auth application-default login      # credentials for local code and Terraform
gcloud projects create demo-ci-2025 --name="Demo CI" --folder=123456789012
gcloud config set project demo-ci-2025
gcloud config set compute/region asia-south1
gcloud services enable compute.googleapis.com storage.googleapis.com iam.googleapis.com

APIs are enabled per project, so a command that fails with “API not enabled” needs gcloud services enable. Use named configurations (gcloud config configurations create work) to switch between projects safely.

Granting access

  • Grant roles to groups, not individuals, and at the lowest scope that works (a project or a single bucket rather than the organization).
  • Prefer predefined roles (roles/storage.objectViewer, roles/compute.viewer) over the broad basic roles Owner, Editor and Viewer.
gcloud projects add-iam-policy-binding demo-ci-2025 \
  --member="group:devops@example.com" --role="roles/compute.viewer"
gcloud projects get-iam-policy demo-ci-2025 --format=json | jq '.bindings[] | {role, members}'

Use IAM Recommender and the policy troubleshooter to find roles that are never used or permissions that block a request.

Service accounts without downloaded keys

Give each workload its own service account with only the roles it needs. Avoid downloaded JSON keys: they never expire by themselves and tend to leak. Organizations created since May 2024 get a secure-by-default Organization Policy that blocks creating them; for older organizations, enforce iam.disableServiceAccountKeyCreation yourself.

For CI systems outside Google Cloud, use workload identity federation. A GitHub Actions example:

gcloud iam workload-identity-pools create github --location=global --display-name="GitHub"
gcloud iam workload-identity-pools providers create-oidc github-actions \
  --location=global --workload-identity-pool=github \
  --issuer-uri="https://token.actions.githubusercontent.com" \
  --attribute-mapping="google.subject=assertion.sub,attribute.repository=assertion.repository" \
  --attribute-condition="assertion.repository=='acme/shop-api'"
gcloud iam service-accounts add-iam-policy-binding deployer@demo-ci-2025.iam.gserviceaccount.com \
  --role=roles/iam.workloadIdentityUser \
  --member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/github/attribute.repository/acme/shop-api"

The attribute condition restricts which repository may use the pool; without it, any repository could exchange a token.

Before you deploy anything: billing

Link a billing account and create a budget alert first:

gcloud billing budgets create --billing-account=0123AB-4567CD-89EFGH \
  --display-name="demo-ci monthly" --budget-amount=50USD \
  --threshold-rule=percent=0.5 --threshold-rule=percent=0.9 --threshold-rule=percent=1.0

A budget alert sends notifications; it does not stop spending, so pair it with quotas and reviews. Also set up a log sink to a central project, and put the organization-level groups and policies in Terraform so changes are reviewed.