IAM Best Practices¶
Enterprise-grade best practices for Identity and Access Management in Google Cloud Platform.
📚 Overview¶
This guide consolidates IAM best practices for building secure, scalable, and compliant cloud environments. Following these practices reduces security risks, improves operational efficiency, and ensures regulatory compliance.
🎯 Core Principles¶
1. Principle of Least Privilege¶
✓ Grant minimum permissions needed
✓ Start restrictive, expand as needed
✓ Use predefined roles over basic roles
✓ Regular permission reviews
✓ Remove unused access immediately
✓ Document permission rationale
✓ Use time-bound access when possible
✓ Implement just-in-time access
❌ Never grant roles/owner unless absolutely necessary
❌ Avoid roles/editor and roles/viewer in production
❌ Don't grant permanent access for temporary needs
❌ Never use "allUsers" or "allAuthenticatedUsers"
2. Defense in Depth¶
Layer 1: Organization Policies
• Enforce security boundaries
• Restrict resource locations
• Require OS Login
• Disable service account keys
Layer 2: IAM Roles and Policies
• Least privilege access
• Role-based access control
• Conditional access
• Regular audits
Layer 3: VPC Service Controls
• Data exfiltration prevention
• Service perimeters
• Access levels
• Ingress/egress rules
Layer 4: Identity-Aware Proxy
• Application-level access
• Context-aware decisions
• Zero trust model
• No VPN required
Layer 5: Monitoring and Logging
• Audit all access
• Alert on anomalies
• Regular reviews
• Incident response
3. Zero Trust Security¶
Never Trust, Always Verify:
✓ Verify every access request
✓ Assume breach mentality
✓ No implicit trust
✓ Continuous verification
✓ Context-aware access
✓ Micro-segmentation
Implementation:
✓ Identity-Aware Proxy (IAP)
✓ VPC Service Controls
✓ Binary Authorization
✓ Workload Identity
✓ Private Google Access
✓ Access Context Manager
👥 User Management¶
1. Use Groups, Not Individual Users¶
# ❌ BAD: Grant to individual users
gcloud projects add-iam-policy-binding PROJECT_ID \
--member='user:alice@company.com' \
--role='roles/compute.instanceAdmin.v1'
gcloud projects add-iam-policy-binding PROJECT_ID \
--member='user:bob@company.com' \
--role='roles/compute.instanceAdmin.v1'
# ✓ GOOD: Grant to group
gcloud projects add-iam-policy-binding PROJECT_ID \
--member='group:compute-admins@company.com' \
--role='roles/compute.instanceAdmin.v1'
# Benefits:
# • Easier to manage
# • Consistent permissions
# • Simpler auditing
# • Faster onboarding/offboarding
2. Group Naming Convention¶
Format: [FUNCTION]-[ROLE]-[ENVIRONMENT]@company.com
Examples:
compute-admins-prod@company.com
storage-viewers-dev@company.com
bigquery-editors-staging@company.com
network-admins-all@company.com
Benefits:
✓ Clear purpose
✓ Easy to search
✓ Consistent structure
✓ Self-documenting
3. User Lifecycle Management¶
Onboarding:
1. Add user to appropriate groups
2. Assign required roles
3. Set up MFA
4. Provide training
5. Document access
Offboarding:
1. Remove from all groups immediately
2. Revoke all direct role assignments
3. Disable service account keys
4. Audit access logs
5. Document removal
Regular Reviews:
• Weekly: New access grants
• Monthly: Group memberships
• Quarterly: All access
• Annually: Full audit
🤖 Service Account Management¶
1. Service Account Best Practices¶
✓ One service account per application
✓ Descriptive names (app-backend, data-processor)
✓ Use Workload Identity (GKE)
✓ Use metadata server (Compute Engine)
✓ Avoid creating keys when possible
✓ Rotate keys every 90 days (if needed)
✓ Store keys in Secret Manager
✓ Never commit keys to source control
✓ Monitor service account usage
✓ Disable unused service accounts
❌ Don't use default service accounts
❌ Don't grant Editor/Owner to service accounts
❌ Don't share service accounts across apps
❌ Don't use user-managed keys unless necessary
2. Service Account Naming¶
Format: [APPLICATION]-[FUNCTION]-sa
Examples:
web-backend-sa@project.iam.gserviceaccount.com
data-processor-sa@project.iam.gserviceaccount.com
cicd-deployer-sa@project.iam.gserviceaccount.com
monitoring-agent-sa@project.iam.gserviceaccount.com
Benefits:
✓ Clear purpose
✓ Easy to identify
✓ Searchable
✓ Audit-friendly
3. Service Account Security¶
# Disable default service accounts
gcloud iam service-accounts disable \
PROJECT_NUMBER-compute@developer.gserviceaccount.com
# Use Workload Identity instead of keys
# For GKE:
gcloud iam service-accounts add-iam-policy-binding \
app-sa@PROJECT_ID.iam.gserviceaccount.com \
--role=roles/iam.workloadIdentityUser \
--member="serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME]"
# Monitor service account key creation
gcloud logging read \
'protoPayload.methodName="google.iam.admin.v1.CreateServiceAccountKey"' \
--limit=50
# Alert on key creation
gcloud logging sinks create sa-key-alert \
--log-filter='protoPayload.methodName="google.iam.admin.v1.CreateServiceAccountKey"' \
--destination=pubsub.googleapis.com/projects/PROJECT_ID/topics/security-alerts
🔐 Role Management¶
1. Role Selection Hierarchy¶
Priority 1: Predefined Roles (BEST)
✓ Curated by Google
✓ Regularly updated
✓ Service-specific
✓ Well-documented
Examples:
• roles/compute.instanceAdmin.v1
• roles/storage.objectViewer
• roles/bigquery.dataEditor
Priority 2: Custom Roles (GOOD)
✓ Tailored to exact needs
✓ Least privilege
✓ Requires maintenance
When to use:
• Predefined roles too broad
• Specific permission combination needed
• Compliance requirements
Priority 3: Basic Roles (AVOID)
❌ Too permissive
❌ Legacy
❌ Not recommended
Never use in production:
• roles/owner
• roles/editor
• roles/viewer
2. Custom Role Best Practices¶
# custom-role.yaml
title: "Backend Developer"
description: "Permissions for backend developers"
stage: "GA"
includedPermissions:
# Only include what's needed
- compute.instances.get
- compute.instances.list
- compute.instances.start
- compute.instances.stop
- storage.objects.get
- storage.objects.list
- cloudsql.instances.connect
- logging.logEntries.list
# Document the role
# Version control this file
# Regular reviews and updates
# Test before deploying
# Create with documentation
gcloud iam roles create backendDeveloper \
--project=PROJECT_ID \
--file=custom-role.yaml
# Document in README
echo "# Custom Role: backendDeveloper
Purpose: Backend developers need to manage compute instances and access storage
Permissions: See custom-role.yaml
Review Schedule: Quarterly
Last Updated: 2026-03-04
" > roles/backend-developer-README.md
3. Role Assignment Patterns¶
# Pattern 1: Environment-based
# Production: Read-only
gcloud projects add-iam-policy-binding prod-project \
--member='group:developers@company.com' \
--role='roles/viewer'
# Development: Full access
gcloud projects add-iam-policy-binding dev-project \
--member='group:developers@company.com' \
--role='roles/editor'
# Pattern 2: Resource-based with conditions
gcloud projects add-iam-policy-binding PROJECT_ID \
--member='group:developers@company.com' \
--role='roles/compute.instanceAdmin.v1' \
--condition='expression=resource.labels.environment == "dev",title=Dev Only'
# Pattern 3: Time-bound access
gcloud projects add-iam-policy-binding PROJECT_ID \
--member='user:contractor@company.com' \
--role='roles/viewer' \
--condition='expression=request.time < timestamp("2026-12-31T23:59:59Z"),title=Contract Period'
📊 Monitoring and Auditing¶
1. Enable Comprehensive Logging¶
# Enable all audit logs
# Go to: IAM & Admin → Audit Logs
# Enable: Admin Read, Data Read, Data Write for all services
# Or via gcloud for specific service
gcloud projects set-iam-policy PROJECT_ID policy.json
# policy.json includes:
{
"auditConfigs": [
{
"service": "allServices",
"auditLogConfigs": [
{"logType": "ADMIN_READ"},
{"logType": "DATA_READ"},
{"logType": "DATA_WRITE"}
]
}
]
}
2. Set Up Critical Alerts¶
# Alert on Owner role grants
gcloud logging sinks create owner-role-alert \
--log-filter='protoPayload.methodName="SetIamPolicy" AND protoPayload.request.policy.bindings.role="roles/owner"' \
--destination=pubsub.googleapis.com/projects/PROJECT_ID/topics/critical-alerts
# Alert on service account key creation
gcloud logging sinks create sa-key-alert \
--log-filter='protoPayload.methodName="google.iam.admin.v1.CreateServiceAccountKey"' \
--destination=pubsub.googleapis.com/projects/PROJECT_ID/topics/security-alerts
# Alert on policy changes
gcloud logging sinks create policy-change-alert \
--log-filter='protoPayload.methodName="SetIamPolicy"' \
--destination=pubsub.googleapis.com/projects/PROJECT_ID/topics/iam-changes
# Alert on failed access attempts
gcloud logging sinks create access-denied-alert \
--log-filter='protoPayload.status.code=7' \
--destination=pubsub.googleapis.com/projects/PROJECT_ID/topics/access-denied
3. Regular Access Reviews¶
#!/usr/bin/env python3
"""
Automated monthly access review
"""
from google.cloud import resourcemanager_v3
from google.cloud import asset_v1
from datetime import datetime
import csv
def monthly_access_review(organization_id):
"""Generate monthly access review report"""
client = asset_v1.AssetServiceClient()
# Get all IAM policies
request = asset_v1.SearchAllIamPoliciesRequest(
scope=f"organizations/{organization_id}",
)
policies = client.search_all_iam_policies(request=request)
# Analyze policies
report = []
issues = []
for policy in policies:
for binding in policy.policy.bindings:
# Flag basic roles
if binding.role in ['roles/owner', 'roles/editor', 'roles/viewer']:
issues.append({
'severity': 'HIGH',
'resource': policy.resource,
'issue': f'Basic role {binding.role} in use',
'members': list(binding.members)
})
# Flag service accounts with broad permissions
if binding.role in ['roles/owner', 'roles/editor']:
for member in binding.members:
if member.startswith('serviceAccount:'):
issues.append({
'severity': 'CRITICAL',
'resource': policy.resource,
'issue': f'Service account with {binding.role}',
'member': member
})
# Add to report
for member in binding.members:
report.append({
'resource': policy.resource,
'member': member,
'role': binding.role,
'has_condition': bool(binding.condition)
})
# Generate CSV reports
timestamp = datetime.now().strftime('%Y%m%d')
with open(f'access-review-{timestamp}.csv', 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['resource', 'member', 'role', 'has_condition'])
writer.writeheader()
writer.writerows(report)
with open(f'access-issues-{timestamp}.csv', 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['severity', 'resource', 'issue', 'member'])
writer.writeheader()
writer.writerows(issues)
print(f"Review complete: {len(report)} bindings, {len(issues)} issues")
return report, issues
# Run monthly
monthly_access_review("123456789")
🏢 Organization-Level Best Practices¶
1. Organization Structure¶
Organization
├── Production Folder
│ ├── Strict policies
│ ├── Limited access
│ ├── Full audit logging
│ └── VPC Service Controls
│
├── Staging Folder
│ ├── Moderate policies
│ ├── Developer access
│ └── Standard logging
│
├── Development Folder
│ ├── Relaxed policies
│ ├── Full developer access
│ └── Basic logging
│
└── Sandbox Folder
├── Minimal policies
├── Experimental access
└── Optional logging
Benefits:
✓ Clear separation
✓ Appropriate controls per environment
✓ Easy to manage
✓ Scalable
2. Organization Policies¶
# Essential organization policies
# 1. Require OS Login
gcloud resource-manager org-policies enable-enforce \
compute.requireOsLogin \
--organization=ORG_ID
# 2. Disable service account key creation
gcloud resource-manager org-policies enable-enforce \
iam.disableServiceAccountKeyCreation \
--organization=ORG_ID
# 3. Restrict resource locations
cat > restrict-locations.yaml << EOF
constraint: gcp.resourceLocations
listPolicy:
allowedValues:
- in:us-locations
- in:eu-locations
EOF
gcloud resource-manager org-policies set-policy \
--organization=ORG_ID \
restrict-locations.yaml
# 4. Domain restricted sharing
cat > domain-restriction.yaml << EOF
constraint: iam.allowedPolicyMemberDomains
listPolicy:
allowedValues:
- "C0123456" # Your org ID
- "company.com"
EOF
gcloud resource-manager org-policies set-policy \
--organization=ORG_ID \
domain-restriction.yaml
# 5. Restrict VM external IPs (production only)
cat > restrict-external-ips.yaml << EOF
constraint: compute.vmExternalIpAccess
listPolicy:
deniedValues:
- "*"
EOF
gcloud resource-manager org-policies set-policy \
--folder=PRODUCTION_FOLDER_ID \
restrict-external-ips.yaml
📋 Compliance and Governance¶
1. Compliance Checklist¶
SOC 2 / ISO 27001:
✓ Least privilege access
✓ Regular access reviews
✓ Audit logging enabled
✓ MFA enforced
✓ Separation of duties
✓ Incident response plan
✓ Access revocation process
✓ Documentation maintained
HIPAA:
✓ VPC Service Controls
✓ Encryption at rest and in transit
✓ Access logging and monitoring
✓ BAA with Google
✓ PHI access controls
✓ Audit trails
✓ Breach notification process
PCI DSS:
✓ Network segmentation
✓ Access control measures
✓ Logging and monitoring
✓ Regular security testing
✓ Encryption requirements
✓ Vendor management
✓ Incident response
2. Documentation Requirements¶
Required Documentation:
1. IAM Policy Document
• Who has what access
• Why access is granted
• Review schedule
• Approval process
2. Role Definitions
• Custom role purposes
• Permission justifications
• Usage guidelines
• Review schedule
3. Service Account Inventory
• Purpose of each SA
• Permissions granted
• Key management (if any)
• Owner/contact
4. Access Review Procedures
• Review frequency
• Review process
• Escalation procedures
• Documentation requirements
5. Incident Response Plan
• Detection procedures
• Response procedures
• Communication plan
• Post-incident review
✅ Implementation Checklist¶
Initial Setup¶
- [ ] Set up Cloud Identity or Google Workspace
- [ ] Create organization structure
- [ ] Define IAM governance policy
- [ ] Create groups for teams
- [ ] Implement organization policies
- [ ] Enable audit logging
- [ ] Set up monitoring and alerting
User Management¶
- [ ] Use groups instead of individual users
- [ ] Implement consistent naming conventions
- [ ] Define onboarding/offboarding procedures
- [ ] Enforce MFA for all users
- [ ] Regular access reviews scheduled
- [ ] Document all access grants
Service Accounts¶
- [ ] One SA per application
- [ ] Use Workload Identity (GKE)
- [ ] Avoid service account keys
- [ ] Descriptive SA names
- [ ] Minimal permissions
- [ ] Monitor SA usage
- [ ] Disable unused SAs
Roles and Permissions¶
- [ ] Use predefined roles when possible
- [ ] Create custom roles for specific needs
- [ ] Implement least privilege
- [ ] Use time-bound access
- [ ] Document role assignments
- [ ] Regular permission reviews
Security¶
- [ ] Enable all audit logs
- [ ] Set up critical alerts
- [ ] Implement VPC Service Controls
- [ ] Use Identity-Aware Proxy
- [ ] Regular security audits
- [ ] Incident response plan
- [ ] Break-glass procedures
Compliance¶
- [ ] Document IAM policies
- [ ] Regular compliance audits
- [ ] Meet regulatory requirements
- [ ] Maintain audit trails
- [ ] Access review procedures
- [ ] Incident response documented
🎓 Summary¶
Key Takeaways: 1. Always follow least privilege principle 2. Use groups, not individual users 3. Avoid basic roles (Owner, Editor, Viewer) 4. Use predefined roles when possible 5. Enable comprehensive audit logging 6. Regular access reviews are critical 7. Automate where possible 8. Document everything 9. Monitor and alert on critical changes 10. Continuous improvement
Last Updated: March 2026 Version: 2.0