Identity-Aware Proxy puts an identity check in front of resources instead of trusting the network. It is Google’s zero-trust (BeyondCorp) building block.
flowchart LR ADM["Admin laptop"] -- "gcloud compute ssh --tunnel-through-iap" --> IAP["Identity-Aware Proxy"] IAP -- "35.235.240.0/20 → tcp:22" --> VM["VM db-1<br/>no external IP"] EMP["Employee browser"] --> LB["External Application LB"] LB --> IAP2["IAP for HTTPS"] IAP2 --> APP["Internal web app"] %% step ADM: The admin runs gcloud with --tunnel-through-iap; no VPN and no bastion host. %% step IAP: IAP checks the admin’s Google identity, the IAP-secured Tunnel User role and optional context such as device or IP. %% step VM: Traffic reaches the VM from 35.235.240.0/20, which the firewall allows on port 22 only. %% step EMP: For web apps, employees open the normal URL in a browser. %% step IAP2: IAP on the backend service asks them to sign in and checks the IAP-secured Web App User role. %% step APP: Only authorised users reach the app; IAP adds signed headers so the app can verify who they are.
IAP for HTTPS apps
- Works with external and internal Application Load Balancers, Cloud Run and App Engine.
- Enable IAP on the backend service, then grant IAP-secured Web App User (
roles/iap.httpsResourceAccessor) to groups. - Add access levels (Access Context Manager) to require a company device, a region or an IP range.
- The app should verify the signed
x-goog-iap-jwt-assertionheader, so requests that bypass IAP are rejected.
IAP TCP forwarding (SSH and RDP)
- Firewall rule allowing
35.235.240.0/20to tcp:22 (or 3389). - Grant IAP-secured Tunnel User (
roles/iap.tunnelResourceAccessor) on the project or specific VMs. - Connect:
gcloud compute ssh db-1 --zone=asia-southeast1-a --tunnel-through-iap
gcloud compute start-iap-tunnel win-1 3389 --local-host-port=localhost:3389 --zone=asia-southeast1-a
Combine with OS Login, so Linux accounts and SSH keys come from IAM instead of keys copied into metadata (roles/compute.osLogin or roles/compute.osAdminLogin).
Why it beats a bastion host
| Bastion VM | IAP |
|---|---|
| A public IP to patch and protect | No public IP anywhere |
| SSH keys shared between admins | Per-user IAM roles, MFA from your identity provider |
| Logs only on the bastion | Every connection in Cloud Audit Logs |
| Command | Meaning |
|---|---|
gcloud compute ssh VM --tunnel-through-iap |
SSH through IAP |
gcloud iap web enable --resource-type=backend-services --service=web-backend |
IAP on a backend service |
gcloud projects add-iam-policy-binding … --role=roles/iap.tunnelResourceAccessor |
Allow tunnels |
Traps: forgetting the firewall rule for 35.235.240.0/20; IAP Tunnel User alone does not log you into the OS (you also need OS Login or SSH keys); an app that does not check the IAP header can be reached by anyone who finds a path around the load balancer.