Configuring Google Cloud Identity-Aware Proxy (IAP) to enforce per-request identity verification for Compute Engine, App Engine, Cloud Run, and GKE services using access levels, context-aware policies, and programmatic access with service accounts.
Do not use for non-HTTP applications that cannot be placed behind an HTTPS load balancer, for public-facing applications that need unauthenticated access, or when applications handle their own authentication and IAP would conflict with existing auth flows.
gcloud services enable iap.googleapis.com)Configure IAP for different GCP compute platforms.
# Enable required APIs
gcloud services enable iap.googleapis.com
gcloud services enable accesscontextmanager.googleapis.com
# Create OAuth consent screen
gcloud iap oauth-brands create \
--application_title="Internal Applications" \
[email protected]
# Create OAuth client
gcloud iap oauth-clients create \
projects/PROJECT_ID/brands/BRAND_ID \
--display_name="IAP Web Client"
# === Enable IAP on Compute Engine Backend Service ===
gcloud compute backend-services update my-backend-service \
--iap=enabled,oauth2-client-id=CLIENT_ID,oauth2-client-secret=CLIENT_SECRET \
--global
# === Enable IAP on App Engine ===
gcloud iap web enable \
--resource-type=app-engine \
--oauth2-client-id=CLIENT_ID \
--oauth2-client-secret=CLIENT_SECRET
# === Enable IAP on Cloud Run ===
# First grant IAP service account the Cloud Run Invoker role
gcloud run services add-iam-policy-binding my-service \
--member="serviceAccount:[email protected]" \
--role="roles/run.invoker" \
--region=us-central1
# Enable IAP on the Cloud Run backend service
gcloud compute backend-services update my-cloud-run-backend \
--iap=enabled,oauth2-client-id=CLIENT_ID,oauth2-client-secret=CLIENT_SECRET \
--global
# === Enable IAP TCP Forwarding for SSH/RDP ===
# No load balancer needed - uses IAP tunnel
gcloud compute instances add-iam-policy-binding my-vm \
--member="group:[email protected]" \
--role="roles/iap.tunnelResourceAccessor" \
--zone=us-central1-a
# SSH through IAP tunnel
gcloud compute ssh my-vm --zone=us-central1-a --tunnel-through-iap
# RDP through IAP tunnel
gcloud compute start-iap-tunnel my-windows-vm 3389 \
--local-host-port=localhost:3390 \
--zone=us-central1-a
Grant access to specific users and groups with optional access level conditions.
# Grant basic access to a group
gcloud iap web add-iam-policy-binding \
--resource-type=backend-services \
--service=my-backend-service \
--member="group:[email protected]" \
--role="roles/iap.httpsResourceAccessor"
# Grant access with access level condition
gcloud iap web add-iam-policy-binding \
--resource-type=backend-services \
--service=finance-app \
--member="group:[email protected]" \
--role="roles/iap.httpsResourceAccessor" \
--condition='expression=request.auth.access_levels.exists(x, x == "accessPolicies/POLICY_ID/accessLevels/corporate-device"),title=RequireCorporateDevice,description=Requires managed corporate device'
# Grant access only during business hours
gcloud iap web add-iam-policy-binding \
--resource-type=backend-services \
--service=admin-console \
--member="group:[email protected]" \
--role="roles/iap.httpsResourceAccessor" \
--condition='expression=request.time.getHours("America/New_York") >= 8 && request.time.getHours("America/New_York") <= 18 && request.time.getDayOfWeek("America/New_York") >= 1 && request.time.getDayOfWeek("America/New_York") <= 5,title=BusinessHoursOnly'
# Grant access to a specific URL path
gcloud iap web add-iam-policy-binding \
--resource-type=backend-services \
--service=internal-api \
--member="group:[email protected]" \
--role="roles/iap.httpsResourceAccessor" \
--condition='expression=request.path.startsWith("/api/v2/"),title=APIv2Access'
Define context-based access requirements using device attributes and network conditions.
# Create access level requiring encrypted corporate device
cat > managed-device.yaml << 'EOF'
- devicePolicy:
allowedEncryptionStatuses:
- ENCRYPTED
osConstraints:
- osType: DESKTOP_WINDOWS
minimumVersion: "10.0.19045"
- osType: DESKTOP_MAC
minimumVersion: "14.0"
- osType: DESKTOP_CHROME_OS
requireScreenlock: true
requireAdminApproval: true
allowedDeviceManagementLevels:
- ADVANCED
EOF
gcloud access-context-manager levels create managed-device \
--policy=POLICY_ID \
--title="Managed Device" \
--basic-level-spec=managed-device.yaml
# Create access level for corporate network
cat > corp-network.yaml << 'EOF'
- ipSubnetworks:
- "203.0.113.0/24"
- "198.51.100.0/24"
regions:
- US
- GB
EOF
gcloud access-context-manager levels create corp-network \
--policy=POLICY_ID \
--title="Corporate Network" \
--basic-level-spec=corp-network.yaml
# Create custom access level using CEL for complex logic
cat > high-trust.yaml << 'EOF'