Google Cloud’s Identity-Aware Proxy (IAP) is a managed service that controls access to cloud applications and virtual machines without requiring a traditional VPN. Instead of exposing services through open firewall rules or relying on SSH keys distributed across teams, IAP verifies user identity and context before granting access. In a production infrastructure codebase, IAP serves as the primary mechanism for securing admin interfaces, internal dashboards, and direct machine access across a cloud-native platform.
The fundamental shift IAP introduces is moving from network-perimeter security to per-request identity verification — a core tenet of Google’s BeyondCorp security model. Every request to an IAP-protected resource must carry a valid OAuth 2.0 token, and IAP evaluates that token against configured IAM policies before forwarding traffic to the backend. This eliminates the need to manage SSH keys, bastion hosts, or VPN concentrators, reducing both operational overhead and attack surface.
In the infrastructure project, IAP is provisioned declaratively using Pulumi’s Go SDK. The infrastructure code defines IAP settings alongside backend services, IAM bindings for Google Groups, and firewall rules that restrict ingress to Google’s IAP forwarding ranges only. This approach ensures that every environment — from development to production — enforces consistent access policies through code review rather than manual configuration.
IAP tunnels provide encrypted TCP connections to VM instances and GKE nodes without requiring public IP addresses. The gcloud compute start-iap-tunnel command establishes a WebSocket-based tunnel through Google’s front-end infrastructure, forwarding local ports to the target instance. This completely replaces traditional SSH bastion host patterns and eliminates the need to distribute or rotate SSH keys across teams.
Any HTTP(S) backend service behind a Google Cloud Load Balancer can be IAP-protected. When IAP is enabled on a backend service, Google’s infrastructure intercepts every request, redirects unauthenticated users to a Google sign-in flow, and only forwards authenticated & authorized requests to the backend. The backend receives a signed JWT header (x-goog-iap-jwt-assertion) that it can independently verify for defense in depth.
Beyond simple identity checks, IAP supports access levels that evaluate device posture, IP address ranges, and other contextual signals. Access levels are defined in Access Context Manager and can be attached to IAP policies to enforce conditions like “corporate-managed device with encrypted disk” or “originating from a known office IP range.” This enables fine-grained zero-trust policies without modifying application code.
TCP forwarding extends IAP beyond HTTP traffic, enabling secure tunnels for arbitrary TCP protocols such as SSH, RDP, and database connections. The roles/iap.tunnelResourceAccessor IAM role grants permission to create tunnels, and firewall rules must allow ingress from the 35.235.240.0/20 CIDR range (Google’s IAP forwarding IP pool). In a production infrastructure setup, this is the standard mechanism for operator access to cluster nodes.
IAP acts as an OAuth 2.0 authorization server, managing the consent flow and token lifecycle transparently. When a user accesses an IAP-protected resource, IAP issues a short-lived credential scoped to that specific backend service. The backend can extract the user’s verified email and subject identifier from the JWT without needing its own authentication system, enabling clean separation between identity verification and application logic.
In the infrastructure project, IAP is enabled declaratively on backend services that front GKE-hosted admin interfaces. The Pulumi code configures the backend service with an IAP block containing an OAuth2 client ID and secret, which are stored in Google Secret Manager and referenced at deploy time.
package infra
import (
"github.com/pulumi/pulumi-gcp/sdk/v7/go/gcp/compute"
"github.com/pulumi/pulumi-gcp/sdk/v7/go/gcp/iap"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func createIAPBackendService(ctx *pulumi.Context) error {
// Create the backend service with IAP enabled
backendSvc, err := compute.NewBackendService(ctx, "admin-backend", &compute.BackendServiceArgs{
Protocol: pulumi.String("HTTP"),
PortName: pulumi.String("http"),
TimeoutSec: pulumi.Int(30),
HealthChecks: pulumi.String(healthCheck.ID()),
LoadBalancingScheme: pulumi.String("EXTERNAL_MANAGED"),
Iap: &compute.BackendServiceIapArgs{
Oauth2ClientId: pulumi.String(oauthClientId),
Oauth2ClientSecret: pulumi.String(oauthClientSecret),
},
Backends: compute.BackendServiceBackendArray{
&compute.BackendServiceBackendArgs{
Group: neg.SelfLink,
BalancingMode: pulumi.String("RATE"),
MaxRatePerEndpoint: pulumi.Float64(100),
},
},
})
if err != nil {
return err
}
ctx.Export("adminBackendId", backendSvc.ID())
return nil
}
Rather than exposing SSH ports to the internet or maintaining bastion hosts, the infrastructure project configures firewall rules that only permit ingress from Google’s IAP forwarding range. Operators use gcloud compute ssh --tunnel-through-iap to reach instances, and the IAP service handles authentication transparently.
// Firewall rule allowing IAP tunnel traffic only
func createIAPFirewallRule(ctx *pulumi.Context, network pulumi.StringInput) error {
_, err := compute.NewFirewall(ctx, "allow-iap-tunnel", &compute.FirewallArgs{
Network: network,
Direction: pulumi.String("INGRESS"),
Priority: pulumi.Int(1000),
Allows: compute.FirewallAllowArray{
&compute.FirewallAllowArgs{
Protocol: pulumi.String("tcp"),
Ports: pulumi.StringArray{
pulumi.String("22"), // SSH
pulumi.String("3389"), // RDP
},
},
},
// Only allow traffic from Google’s IAP forwarding range
SourceRanges: pulumi.StringArray{
pulumi.String("35.235.240.0/20"),
},
TargetTags: pulumi.StringArray{
pulumi.String("allow-iap-tunnel"),
},
})
return err
}
// Usage from the command line (no VPN or bastion required):
// gcloud compute ssh instance-name --tunnel-through-iap --zone us-central1-a
// gcloud compute start-iap-tunnel instance-name 5432 --local-host-port=localhost:5432
Access to IAP-protected resources is managed through Google Groups rather than individual user accounts. This pattern, used extensively in the infrastructure project, allows team membership changes to propagate instantly without modifying infrastructure code. Each environment has dedicated groups for operators, developers, and read-only viewers.
// IAM binding granting a Google Group access to IAP-protected web resources
func createIAPWebBinding(ctx *pulumi.Context, backendSvc *compute.BackendService) error {
_, err := iap.NewWebBackendServiceIamBinding(ctx, "admin-access", &iap.WebBackendServiceIamBindingArgs{
WebBackendService: backendSvc.Name,
Role: pulumi.String("roles/iap.httpsResourceAccessor"),
Members: pulumi.StringArray{
pulumi.String("group:platform-admins@example.com"),
pulumi.String("group:sre-oncall@example.com"),
},
})
return err
}
// IAM binding for IAP tunnel access to compute instances
func createIAPTunnelBinding(ctx *pulumi.Context, project string) error {
_, err := iap.NewTunnelInstanceIAMBinding(ctx, "tunnel-access", &iap.TunnelInstanceIAMBindingArgs{
Project: pulumi.String(project),
Role: pulumi.String("roles/iap.tunnelResourceAccessor"),
Members: pulumi.StringArray{
pulumi.String("group:infrastructure-ops@example.com"),
},
})
return err
}
Enabling IAP on existing backend services requires careful rollout to avoid disrupting active users. A production approach uses a three-phase strategy:
Rather than binding individual users to IAP resources, the infrastructure project uses a layered Google Groups structure:
platform-admins@ — Full access to all IAP-protected resources and tunnel access to all instancessre-oncall@ — Access to production dashboards and tunnel access for incident responsedevelopers@ — Access to staging and development IAP-protected services onlyreadonly-viewers@ — Read-only access to monitoring dashboards behind IAPGroup membership is managed through an identity provider, and changes propagate to IAP within minutes. This eliminates the toil of updating Pulumi code for routine access changes.
Every IAP access decision generates a Cloud Audit Log entry containing the user’s identity, the resource accessed, the access decision (allow or deny), and the policy that governed the decision. In a production infrastructure setup, these logs are exported to BigQuery for long-term retention and to Cloud Monitoring for real-time alerting on anomalous access patterns. A compliance reporting tool can aggregate these logs to produce reports showing who accessed what, when, and from where.
A database cluster typically exposes an administrative HTTP interface for configuration changes, schema management, and operational commands. In a production setup, this interface is deployed behind a GKE Ingress with IAP enabled. Only members of the platform-admins group can access it, and every request is logged with the authenticated user’s identity. This replaces an earlier pattern where the admin interface was accessible only through a bastion host with shared SSH keys — a significant security and auditability improvement.
Operators needing direct access to Cloud SQL instances or database cluster nodes use IAP TCP forwarding to establish secure tunnels. Instead of whitelisting IP addresses or maintaining a VPN, the operator runs gcloud compute start-iap-tunnel to forward a local port to the database port on the target instance. IAP verifies their identity, checks their group membership against the tunnelResourceAccessor binding, and establishes an encrypted tunnel. All tunnel creation events are logged for audit.
A cluster health and deployment readiness dashboard can be served as a static web application behind an IAP-protected load balancer. Different teams see different data based on their group membership, with IAP providing the authentication layer and the application reading the x-goog-iap-jwt-assertion header to determine authorization scope.
130.211.0.0/22 and 35.191.0.0/16) and that SSH is restricted to the IAP forwarding range (35.235.240.0/20).x-goog-iap-jwt-assertion header in your backend using Google’s public keys to ensure defense in depth.roles/iap.httpsResourceAccessor role. Audit existing service account traffic before enabling IAP enforcement.