Harden Google Cloud Access with IAM Conditions
Quick answer
Harden Google Cloud IAM with conditions: restrict admin roles to specific permissions, lock down MCP servers, and enforce time-based access. PoLP made easy.
Google Cloud’s IAM is like a swamp’s water channels—powerful but tricky to navigate. The Principle of Least Privilege (PoLP) is your compass: grant only the permissions needed. But when resources are shared across teams, standard roles can feel like a blunt machete. Enter IAM conditions—your surgical tool for fine-grained access control.
Use Case 1: Taming Admin Powers
Imagine a builder service account that needs to create resources but only access BigQuery and Vertex AI. Granting roles/resourcemanager.projectIamAdmin is too broad. With a condition, you can restrict which roles it can grant:
gcloud projects add-iam-policy-binding "${PROJECT_ID}"
--member="serviceAccount:${SA_MAIL}"
--role="roles/resourcemanager.projectIamAdmin"
--condition="^:^
title=LimitedIAMAdmin:
expression=api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', [])
.hasOnly([
'roles/aiplatform.user',
'roles/bigquery.jobUser',
'roles/bigquery.dataViewer',
'roles/cloudtrace.agent',
'roles/logging.logWriter'
])"
This uses Common Expression Language (CEL) to limit the admin to granting only those five roles. In Terraform, it’s just as clean.
Use Case 2: Locking Down MCP Servers
Google’s MCP servers expose cloud services via the Model Context Protocol. The roles/mcp.toolUser role grants access to all MCP servers—like giving a capybara the keys to the entire swamp. Use conditions to scope it to a specific service:
gcloud projects add-iam-policy-binding $PROJECT_ID
--member="serviceAccount:$SA_EMAIL"
--role="roles/mcp.toolUser"
--condition="^:^
title=bigquery_mcp_server_only:
expression=resource.service == 'bigquery.googleapis.com'"
You can even restrict to specific MCP tools using api.getAttribute('mcp.googleapis.com/tool.name', '').
Time-Based and Identity Conditions
Conditions aren’t just for resources—they can also control when access is allowed. For example, only during business hours in Berlin:
expression=request.time.getHours('Europe/Berlin') >= 9 &&
request.time.getHours('Europe/Berlin') <= 17 &&
request.time.getDayOfWeek('Europe/Berlin') >= 1 &&
request.time.getDayOfWeek('Europe/Berlin') <= 5
But beware: using conditions to filter by identity is an anti-pattern. Stick to binding policies to specific principals instead.
Go Deeper with Deny Policies
For defense-in-depth, pair IAM conditions with IAM Deny policies. They let you grant broad roles via Allow policies, then surgically remove excess permissions. Check out these resources:
- Permissions supported in deny policies
- Principal identifiers in deny policies
- Troubleshoot access issues with deny policies
- Build defense in depth
For more on Google Cloud, check out our Google Cloud Review.
Original announcement published on Google Cloud.