11.1 Identity and Access Management (IAM)

Note

Google Cloud IAM (Identity and Access Management) provides unified access control across all GCP services. It allows you to manage who (identity) has what access (role) to which resources. IAM follows the principle of least privilege and uses a role-based access control (RBAC) model.

IAM Core Concepts

Members (Who)

Members are the identities that can access your Google Cloud resources. There are five types of members:

  1. Google Account: Represents a developer, administrator, or any other person who interacts with GCP - Example: alice@example.com

  2. Service Account: Special account for applications and VMs - Example: my-service@project-id.iam.gserviceaccount.com

  3. Google Group: Named collection of Google Accounts and service accounts - Example: admins@example.com

  4. Google Workspace Domain: Represents all Google Accounts in an organization - Example: example.com

  5. Cloud Identity Domain: Like Google Workspace but without access to Workspace applications - Example: example.com

Roles (What)

Roles are collections of permissions. You grant roles to members to allow them to perform actions on resources.

Three types of roles:

  1. Basic Roles (Legacy - use sparingly):

    • Owner: Full control including managing access

    • Editor: Modify and delete access

    • Viewer: Read-only access

  2. Predefined Roles: Fine-grained access control managed by Google - Example: roles/compute.instanceAdmin.v1 - Full control of Compute Engine instances

  3. Custom Roles: User-defined roles with specific permissions - Created for specific organizational needs

Resources (Where)

Resources are GCP entities that you can grant access to:

  • Projects

  • Compute Engine instances

  • Cloud Storage buckets

  • BigQuery datasets

  • And more…

Permissions

Permissions determine what operations are allowed on a resource. They follow this format:

<service>.<resource>.<verb>

Examples:
- compute.instances.create
- storage.buckets.get
- bigquery.datasets.update

IAM Policy Structure

An IAM policy is a collection of role bindings that bind one or more members to roles.

Policy JSON Format:

{
    "bindings": [
        {
            "role": "roles/storage.objectViewer",
            "members": [
                "user:alice@example.com",
                "serviceAccount:my-service@project.iam.gserviceaccount.com",
                "group:admins@example.com"
            ]
        },
        {
            "role": "roles/storage.objectAdmin",
            "members": [
                "user:bob@example.com"
            ],
            "condition": {
                "title": "Expires in 2024",
                "expression": "request.time < timestamp('2024-12-31T23:59:59Z')"
            }
        }
    ],
    "etag": "BwXhFxF7dqE=",
    "version": 3
}

Setting Up IAM Access

Prerequisites:

# Install Google Cloud CLI if not already installed
curl https://sdk.cloud.google.com | bash
exec -l $SHELL

# Authenticate
gcloud auth login

# Set your project
gcloud config set project PROJECT_ID

View Current IAM Policy:

# View project IAM policy
gcloud projects get-iam-policy PROJECT_ID

# View IAM policy in readable format
gcloud projects get-iam-policy PROJECT_ID --format=json | jq

# View IAM policy for a specific resource (e.g., storage bucket)
gsutil iam get gs://BUCKET_NAME

Grant IAM Roles:

# Grant a role to a user at project level
gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="user:alice@example.com" \
    --role="roles/compute.viewer"

# Grant a role to a service account
gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="serviceAccount:my-service@PROJECT_ID.iam.gserviceaccount.com" \
    --role="roles/storage.objectAdmin"

# Grant a role to a Google Group
gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="group:developers@example.com" \
    --role="roles/editor"

# Grant a role to all authenticated users
gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="allAuthenticatedUsers" \
    --role="roles/viewer"

Remove IAM Roles:

# Remove a role from a user
gcloud projects remove-iam-policy-binding PROJECT_ID \
    --member="user:alice@example.com" \
    --role="roles/compute.viewer"

Grant Roles with Conditions:

# Grant time-bound access
gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="user:temp-contractor@example.com" \
    --role="roles/viewer" \
    --condition='expression=request.time < timestamp("2024-12-31T23:59:59Z"),title=Temporary Access,description=Access expires at end of 2024'

Service Accounts

Service accounts are special Google accounts that represent applications or VMs, not individual users.

Create a Service Account:

# Create service account
gcloud iam service-accounts create my-service-account \
    --display-name="My Service Account" \
    --description="Service account for application authentication"

# List service accounts
gcloud iam service-accounts list

# Get service account email
SA_EMAIL=$(gcloud iam service-accounts list \
    --filter="displayName:My Service Account" \
    --format="value(email)")

echo $SA_EMAIL

Grant Roles to Service Account:

# Grant roles at project level
gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="serviceAccount:$SA_EMAIL" \
    --role="roles/storage.objectViewer"

# Grant multiple roles
for role in "roles/compute.viewer" "roles/storage.objectAdmin" "roles/logging.logWriter"; do
    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member="serviceAccount:$SA_EMAIL" \
        --role="$role"
done

Create and Manage Service Account Keys:

# Create a JSON key file
gcloud iam service-accounts keys create ~/key.json \
    --iam-account=$SA_EMAIL

# List keys for service account
gcloud iam service-accounts keys list \
    --iam-account=$SA_EMAIL

# Delete a key
gcloud iam service-accounts keys delete KEY_ID \
    --iam-account=$SA_EMAIL

Warning

Service account keys are powerful credentials. Store them securely and rotate them regularly. Consider using Workload Identity or service account impersonation instead of downloading keys when possible.

Use Service Account Authentication:

# Authenticate using service account key
gcloud auth activate-service-account --key-file=~/key.json

# Set as environment variable for application authentication
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/key.json"

Service Account Impersonation:

# Grant user permission to impersonate service account
gcloud iam service-accounts add-iam-policy-binding $SA_EMAIL \
    --member="user:alice@example.com" \
    --role="roles/iam.serviceAccountUser"

# Use impersonation in gcloud commands
gcloud compute instances list \
    --impersonate-service-account=$SA_EMAIL

Custom Roles

Create custom roles when predefined roles don’t meet your needs.

Create a Custom Role:

# Create role definition file
cat > custom-role.yaml <<EOF
title: "Custom Instance Operator"
description: "Can start and stop instances but not delete"
stage: "GA"
includedPermissions:
- compute.instances.start
- compute.instances.stop
- compute.instances.get
- compute.instances.list
- compute.zones.get
- compute.zones.list
EOF

# Create custom role at project level
gcloud iam roles create customInstanceOperator \
    --project=PROJECT_ID \
    --file=custom-role.yaml

# Create custom role at organization level
gcloud iam roles create customInstanceOperator \
    --organization=ORGANIZATION_ID \
    --file=custom-role.yaml

Update a Custom Role:

# Add permissions to existing role
gcloud iam roles update customInstanceOperator \
    --project=PROJECT_ID \
    --add-permissions=compute.instances.reset

# Remove permissions
gcloud iam roles update customInstanceOperator \
    --project=PROJECT_ID \
    --remove-permissions=compute.instances.reset

List and Describe Roles:

# List all roles
gcloud iam roles list

# List project custom roles
gcloud iam roles list --project=PROJECT_ID

# Describe a specific role
gcloud iam roles describe roles/compute.instanceAdmin.v1

# Describe custom role
gcloud iam roles describe customInstanceOperator --project=PROJECT_ID

IAM Policy Management

Export and Import Policies:

# Export current policy to file
gcloud projects get-iam-policy PROJECT_ID > policy.json

# Edit policy.json as needed, then import
gcloud projects set-iam-policy PROJECT_ID policy.json

Using Policy Analyzer:

# Analyze who has access to a resource
gcloud asset analyze-iam-policy \
    --organization=ORGANIZATION_ID \
    --full-resource-name="//compute.googleapis.com/projects/PROJECT_ID/zones/us-central1-a/instances/INSTANCE_NAME"

# Find all resources a user has access to
gcloud asset analyze-iam-policy \
    --organization=ORGANIZATION_ID \
    --identity="user:alice@example.com"

IAM Conditions

IAM Conditions allow you to define and enforce conditional, attribute-based access control for GCP resources.

Common Condition Examples:

# Time-based access
gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="user:contractor@example.com" \
    --role="roles/viewer" \
    --condition='expression=request.time < timestamp("2024-06-30T00:00:00Z"),title=Access until June 2024'

# Resource-based access (only specific instances)
gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="user:developer@example.com" \
    --role="roles/compute.instanceAdmin.v1" \
    --condition='expression=resource.name.startsWith("projects/PROJECT_ID/zones/us-central1-a/instances/dev-"),title=Dev instances only'

# IP-based access
gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="user:admin@example.com" \
    --role="roles/owner" \
    --condition='expression=origin.ip in ["203.0.113.0/24"],title=Office IP only'

Best Practices

1. Use Principle of Least Privilege:

# Bad: Granting Editor role when only read access is needed
gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="user:alice@example.com" \
    --role="roles/editor"

# Good: Grant specific role for the task
gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="user:alice@example.com" \
    --role="roles/storage.objectViewer"

2. Use Groups Instead of Individual Users:

# Create a group in Google Workspace or Cloud Identity
# Then grant access to the group
gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="group:developers@example.com" \
    --role="roles/editor"

3. Separate Environments:

# Use separate projects for dev, staging, production
# Grant different access levels to each

# Development project - broader access
gcloud projects add-iam-policy-binding dev-project \
    --member="group:developers@example.com" \
    --role="roles/editor"

# Production project - restricted access
gcloud projects add-iam-policy-binding prod-project \
    --member="group:developers@example.com" \
    --role="roles/viewer"

4. Regular Access Reviews:

# Export IAM policy for review
gcloud projects get-iam-policy PROJECT_ID \
    --format=json > iam-audit-$(date +%Y%m%d).json

# List all service accounts and their keys
gcloud iam service-accounts list
gcloud iam service-accounts keys list --iam-account=SA_EMAIL

5. Enable Audit Logging:

# View admin activity logs
gcloud logging read "resource.type=project AND protoPayload.methodName=SetIamPolicy" \
    --limit 50 \
    --format json

# Monitor for privilege escalation
gcloud logging read "protoPayload.methodName=google.iam.admin.v1.CreateRole" \
    --limit 10

6. Use Workload Identity for GKE:

Instead of downloading service account keys for applications running in GKE, use Workload Identity:

# Enable Workload Identity on GKE cluster
gcloud container clusters update CLUSTER_NAME \
    --workload-pool=PROJECT_ID.svc.id.goog

# Bind Kubernetes service account to GCP service account
gcloud iam service-accounts add-iam-policy-binding $SA_EMAIL \
    --role roles/iam.workloadIdentityUser \
    --member "serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME]"

Practical IAM Scenarios

Scenario 1: Onboarding a New Developer

# Add to developers group
# (Done via Google Workspace or Cloud Identity admin console)

# Grant group access to development project
gcloud projects add-iam-policy-binding dev-project-id \
    --member="group:developers@example.com" \
    --role="roles/editor"

# Grant read-only access to production
gcloud projects add-iam-policy-binding prod-project-id \
    --member="group:developers@example.com" \
    --role="roles/viewer"

Scenario 2: Application Service Account

# Create service account for application
gcloud iam service-accounts create webapp-backend \
    --display-name="Web Application Backend"

# Grant necessary permissions
gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="serviceAccount:webapp-backend@PROJECT_ID.iam.gserviceaccount.com" \
    --role="roles/datastore.user"

gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="serviceAccount:webapp-backend@PROJECT_ID.iam.gserviceaccount.com" \
    --role="roles/storage.objectViewer"

# For Cloud Run, assign service account
gcloud run deploy webapp \
    --image gcr.io/PROJECT_ID/webapp \
    --service-account webapp-backend@PROJECT_ID.iam.gserviceaccount.com

Scenario 3: External Auditor Access

# Grant time-limited read-only access
gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="user:auditor@external-company.com" \
    --role="roles/viewer" \
    --condition='expression=request.time < timestamp("2024-01-31T23:59:59Z"),title=Audit Access Q1 2024'

Scenario 4: Cross-Project Access

# Service account in Project A needs access to storage in Project B

# In Project B, grant access to Project A's service account
gcloud projects add-iam-policy-binding project-b-id \
    --member="serviceAccount:service-a@project-a-id.iam.gserviceaccount.com" \
    --role="roles/storage.objectViewer"

Troubleshooting IAM Issues

Check Permissions:

# Test if you have a specific permission
gcloud projects get-iam-policy PROJECT_ID \
    --flatten="bindings[].members" \
    --filter="bindings.members:user:YOUR_EMAIL"

# Check what you can do on a resource
gcloud compute instances test-iam-permissions INSTANCE_NAME \
    --zone=ZONE \
    --permissions=compute.instances.start,compute.instances.stop

Common IAM Errors:

  1. Error 403: Permission Denied

# Check if user has necessary role
gcloud projects get-iam-policy PROJECT_ID \
    --flatten="bindings[].members" \
    --filter="bindings.members:user:alice@example.com"
  1. Error: Service Account Key Rotation

# List all keys
gcloud iam service-accounts keys list \
    --iam-account=SA_EMAIL

# Create new key
gcloud iam service-accounts keys create new-key.json \
    --iam-account=SA_EMAIL

# Delete old key after updating applications
gcloud iam service-accounts keys delete OLD_KEY_ID \
    --iam-account=SA_EMAIL
  1. IAM Policy Sync Issues

# Force policy refresh
gcloud projects get-iam-policy PROJECT_ID > /dev/null

# Wait a few seconds for propagation
sleep 5

# Try operation again

IAM Security Scanner

# Install Security Command Center (requires organization)
gcloud scc findings list ORGANIZATION_ID \
    --filter="category='PUBLIC_IP_ADDRESS'"

# Check for overly permissive IAM bindings
gcloud asset search-all-iam-policies \
    --scope=organizations/ORGANIZATION_ID \
    --query="policy:roles/owner OR policy:roles/editor"

Additional Resources