The gcp:iap/webRegionBackendServiceIamPolicy:WebRegionBackendServiceIamPolicy resource, part of the Pulumi GCP provider, manages IAM policies for Identity-Aware Proxy regional backend services, controlling who can access IAP-protected resources. This guide focuses on three capabilities: authoritative policy replacement, role-based member grants, and time-based access conditions.
IAM management for IAP backend services comes in three forms: Policy (authoritative, replaces entire policy), Binding (authoritative for one role, preserves other roles), and Member (non-authoritative, adds one member to a role). The examples are intentionally small. Combine them with your own backend services and access requirements.
Grant a role to multiple members with Binding
Teams managing IAP access often need to grant the same role to multiple users or service accounts at once.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const binding = new gcp.iap.WebRegionBackendServiceIamBinding("binding", {
project: _default.project,
region: _default.region,
webRegionBackendService: _default.name,
role: "roles/iap.httpsResourceAccessor",
members: ["user:jane@example.com"],
});
import pulumi
import pulumi_gcp as gcp
binding = gcp.iap.WebRegionBackendServiceIamBinding("binding",
project=default["project"],
region=default["region"],
web_region_backend_service=default["name"],
role="roles/iap.httpsResourceAccessor",
members=["user:jane@example.com"])
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/iap"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := iap.NewWebRegionBackendServiceIamBinding(ctx, "binding", &iap.WebRegionBackendServiceIamBindingArgs{
Project: pulumi.Any(_default.Project),
Region: pulumi.Any(_default.Region),
WebRegionBackendService: pulumi.Any(_default.Name),
Role: pulumi.String("roles/iap.httpsResourceAccessor"),
Members: pulumi.StringArray{
pulumi.String("user:jane@example.com"),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var binding = new Gcp.Iap.WebRegionBackendServiceIamBinding("binding", new()
{
Project = @default.Project,
Region = @default.Region,
WebRegionBackendService = @default.Name,
Role = "roles/iap.httpsResourceAccessor",
Members = new[]
{
"user:jane@example.com",
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.iap.WebRegionBackendServiceIamBinding;
import com.pulumi.gcp.iap.WebRegionBackendServiceIamBindingArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var binding = new WebRegionBackendServiceIamBinding("binding", WebRegionBackendServiceIamBindingArgs.builder()
.project(default_.project())
.region(default_.region())
.webRegionBackendService(default_.name())
.role("roles/iap.httpsResourceAccessor")
.members("user:jane@example.com")
.build());
}
}
resources:
binding:
type: gcp:iap:WebRegionBackendServiceIamBinding
properties:
project: ${default.project}
region: ${default.region}
webRegionBackendService: ${default.name}
role: roles/iap.httpsResourceAccessor
members:
- user:jane@example.com
The WebRegionBackendServiceIamBinding resource manages all members for a specific role while preserving other roles in the policy. The members property lists all identities that should have the role; the role property specifies which IAP permission to grant. This approach is authoritative for the specified role but non-authoritative for the overall policy.
Add a single member to a role with Member
When you need to grant access to one user without affecting other members of the role, Member resources provide non-authoritative updates.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const member = new gcp.iap.WebRegionBackendServiceIamMember("member", {
project: _default.project,
region: _default.region,
webRegionBackendService: _default.name,
role: "roles/iap.httpsResourceAccessor",
member: "user:jane@example.com",
});
import pulumi
import pulumi_gcp as gcp
member = gcp.iap.WebRegionBackendServiceIamMember("member",
project=default["project"],
region=default["region"],
web_region_backend_service=default["name"],
role="roles/iap.httpsResourceAccessor",
member="user:jane@example.com")
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/iap"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := iap.NewWebRegionBackendServiceIamMember(ctx, "member", &iap.WebRegionBackendServiceIamMemberArgs{
Project: pulumi.Any(_default.Project),
Region: pulumi.Any(_default.Region),
WebRegionBackendService: pulumi.Any(_default.Name),
Role: pulumi.String("roles/iap.httpsResourceAccessor"),
Member: pulumi.String("user:jane@example.com"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var member = new Gcp.Iap.WebRegionBackendServiceIamMember("member", new()
{
Project = @default.Project,
Region = @default.Region,
WebRegionBackendService = @default.Name,
Role = "roles/iap.httpsResourceAccessor",
Member = "user:jane@example.com",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.iap.WebRegionBackendServiceIamMember;
import com.pulumi.gcp.iap.WebRegionBackendServiceIamMemberArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var member = new WebRegionBackendServiceIamMember("member", WebRegionBackendServiceIamMemberArgs.builder()
.project(default_.project())
.region(default_.region())
.webRegionBackendService(default_.name())
.role("roles/iap.httpsResourceAccessor")
.member("user:jane@example.com")
.build());
}
}
resources:
member:
type: gcp:iap:WebRegionBackendServiceIamMember
properties:
project: ${default.project}
region: ${default.region}
webRegionBackendService: ${default.name}
role: roles/iap.httpsResourceAccessor
member: user:jane@example.com
The WebRegionBackendServiceIamMember resource adds one identity to a role without replacing existing members. The member property specifies a single identity (user, service account, or group). Multiple Member resources can target the same role, and they can coexist with Binding resources as long as they don’t manage the same role.
Replace the entire IAM policy with Policy
Some deployments require complete control over the IAM policy, replacing any existing grants with a new authoritative configuration.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const admin = gcp.organizations.getIAMPolicy({
bindings: [{
role: "roles/iap.httpsResourceAccessor",
members: ["user:jane@example.com"],
}],
});
const policy = new gcp.iap.WebRegionBackendServiceIamPolicy("policy", {
project: _default.project,
region: _default.region,
webRegionBackendService: _default.name,
policyData: admin.then(admin => admin.policyData),
});
import pulumi
import pulumi_gcp as gcp
admin = gcp.organizations.get_iam_policy(bindings=[{
"role": "roles/iap.httpsResourceAccessor",
"members": ["user:jane@example.com"],
}])
policy = gcp.iap.WebRegionBackendServiceIamPolicy("policy",
project=default["project"],
region=default["region"],
web_region_backend_service=default["name"],
policy_data=admin.policy_data)
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/iap"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/organizations"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
admin, err := organizations.LookupIAMPolicy(ctx, &organizations.LookupIAMPolicyArgs{
Bindings: []organizations.GetIAMPolicyBinding{
{
Role: "roles/iap.httpsResourceAccessor",
Members: []string{
"user:jane@example.com",
},
},
},
}, nil)
if err != nil {
return err
}
_, err = iap.NewWebRegionBackendServiceIamPolicy(ctx, "policy", &iap.WebRegionBackendServiceIamPolicyArgs{
Project: pulumi.Any(_default.Project),
Region: pulumi.Any(_default.Region),
WebRegionBackendService: pulumi.Any(_default.Name),
PolicyData: pulumi.String(admin.PolicyData),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var admin = Gcp.Organizations.GetIAMPolicy.Invoke(new()
{
Bindings = new[]
{
new Gcp.Organizations.Inputs.GetIAMPolicyBindingInputArgs
{
Role = "roles/iap.httpsResourceAccessor",
Members = new[]
{
"user:jane@example.com",
},
},
},
});
var policy = new Gcp.Iap.WebRegionBackendServiceIamPolicy("policy", new()
{
Project = @default.Project,
Region = @default.Region,
WebRegionBackendService = @default.Name,
PolicyData = admin.Apply(getIAMPolicyResult => getIAMPolicyResult.PolicyData),
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetIAMPolicyArgs;
import com.pulumi.gcp.iap.WebRegionBackendServiceIamPolicy;
import com.pulumi.gcp.iap.WebRegionBackendServiceIamPolicyArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
final var admin = OrganizationsFunctions.getIAMPolicy(GetIAMPolicyArgs.builder()
.bindings(GetIAMPolicyBindingArgs.builder()
.role("roles/iap.httpsResourceAccessor")
.members("user:jane@example.com")
.build())
.build());
var policy = new WebRegionBackendServiceIamPolicy("policy", WebRegionBackendServiceIamPolicyArgs.builder()
.project(default_.project())
.region(default_.region())
.webRegionBackendService(default_.name())
.policyData(admin.policyData())
.build());
}
}
resources:
policy:
type: gcp:iap:WebRegionBackendServiceIamPolicy
properties:
project: ${default.project}
region: ${default.region}
webRegionBackendService: ${default.name}
policyData: ${admin.policyData}
variables:
admin:
fn::invoke:
function: gcp:organizations:getIAMPolicy
arguments:
bindings:
- role: roles/iap.httpsResourceAccessor
members:
- user:jane@example.com
The WebRegionBackendServiceIamPolicy resource sets the complete IAM policy from a data source. The policyData property comes from gcp.organizations.getIAMPolicy, which constructs the policy structure with bindings. This resource cannot be used alongside Binding or Member resources because it replaces the entire policy, not just specific roles or members.
Apply time-based access with IAM Conditions
Access requirements often include temporal constraints, such as granting permissions that expire after a specific date.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const binding = new gcp.iap.WebRegionBackendServiceIamBinding("binding", {
project: _default.project,
region: _default.region,
webRegionBackendService: _default.name,
role: "roles/iap.httpsResourceAccessor",
members: ["user:jane@example.com"],
condition: {
title: "expires_after_2019_12_31",
description: "Expiring at midnight of 2019-12-31",
expression: "request.time < timestamp(\"2020-01-01T00:00:00Z\")",
},
});
import pulumi
import pulumi_gcp as gcp
binding = gcp.iap.WebRegionBackendServiceIamBinding("binding",
project=default["project"],
region=default["region"],
web_region_backend_service=default["name"],
role="roles/iap.httpsResourceAccessor",
members=["user:jane@example.com"],
condition={
"title": "expires_after_2019_12_31",
"description": "Expiring at midnight of 2019-12-31",
"expression": "request.time < timestamp(\"2020-01-01T00:00:00Z\")",
})
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/iap"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := iap.NewWebRegionBackendServiceIamBinding(ctx, "binding", &iap.WebRegionBackendServiceIamBindingArgs{
Project: pulumi.Any(_default.Project),
Region: pulumi.Any(_default.Region),
WebRegionBackendService: pulumi.Any(_default.Name),
Role: pulumi.String("roles/iap.httpsResourceAccessor"),
Members: pulumi.StringArray{
pulumi.String("user:jane@example.com"),
},
Condition: &iap.WebRegionBackendServiceIamBindingConditionArgs{
Title: pulumi.String("expires_after_2019_12_31"),
Description: pulumi.String("Expiring at midnight of 2019-12-31"),
Expression: pulumi.String("request.time < timestamp(\"2020-01-01T00:00:00Z\")"),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var binding = new Gcp.Iap.WebRegionBackendServiceIamBinding("binding", new()
{
Project = @default.Project,
Region = @default.Region,
WebRegionBackendService = @default.Name,
Role = "roles/iap.httpsResourceAccessor",
Members = new[]
{
"user:jane@example.com",
},
Condition = new Gcp.Iap.Inputs.WebRegionBackendServiceIamBindingConditionArgs
{
Title = "expires_after_2019_12_31",
Description = "Expiring at midnight of 2019-12-31",
Expression = "request.time < timestamp(\"2020-01-01T00:00:00Z\")",
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.iap.WebRegionBackendServiceIamBinding;
import com.pulumi.gcp.iap.WebRegionBackendServiceIamBindingArgs;
import com.pulumi.gcp.iap.inputs.WebRegionBackendServiceIamBindingConditionArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var binding = new WebRegionBackendServiceIamBinding("binding", WebRegionBackendServiceIamBindingArgs.builder()
.project(default_.project())
.region(default_.region())
.webRegionBackendService(default_.name())
.role("roles/iap.httpsResourceAccessor")
.members("user:jane@example.com")
.condition(WebRegionBackendServiceIamBindingConditionArgs.builder()
.title("expires_after_2019_12_31")
.description("Expiring at midnight of 2019-12-31")
.expression("request.time < timestamp(\"2020-01-01T00:00:00Z\")")
.build())
.build());
}
}
resources:
binding:
type: gcp:iap:WebRegionBackendServiceIamBinding
properties:
project: ${default.project}
region: ${default.region}
webRegionBackendService: ${default.name}
role: roles/iap.httpsResourceAccessor
members:
- user:jane@example.com
condition:
title: expires_after_2019_12_31
description: Expiring at midnight of 2019-12-31
expression: request.time < timestamp("2020-01-01T00:00:00Z")
IAM Conditions add constraint expressions to role grants. The condition block requires a title, optional description, and an expression using Common Expression Language (CEL). The expression compares request.time against a timestamp to enforce expiration. Conditions work with Binding and Member resources but have known limitations documented by Google Cloud.
Beyond these examples
These snippets focus on specific IAM management features: authoritative vs non-authoritative IAM management, role-based access control, and time-based access with IAM Conditions. They’re intentionally minimal rather than full access control configurations.
The examples reference pre-existing infrastructure such as regional backend services (webRegionBackendService) and GCP project and region configuration. They focus on configuring IAM policies rather than provisioning the backend services themselves.
To keep things focused, common IAM patterns are omitted, including:
- Policy data source for reading existing policies
- Combining Binding and Member resources for the same role
- Custom IAM roles (examples use predefined roles/iap.httpsResourceAccessor)
- Advanced condition expressions (resource attributes, request context)
These omissions are intentional: the goal is to illustrate how each IAM resource type is wired, not provide drop-in access control modules. See the WebRegionBackendServiceIamPolicy resource reference for all available configuration options.
Let's configure GCP Identity-Aware Proxy IAM Policies
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Resource Selection & Conflicts
gcp.iap.WebRegionBackendServiceIamPolicy for full policy control (replaces entire policy), gcp.iap.WebRegionBackendServiceIamBinding to manage all members for a specific role (preserves other roles), or gcp.iap.WebRegionBackendServiceIamMember to add individual members (preserves other members and roles).gcp.iap.WebRegionBackendServiceIamPolicy cannot be used with gcp.iap.WebRegionBackendServiceIamBinding or gcp.iap.WebRegionBackendServiceIamMember because they will conflict over policy management. Choose one approach for your use case.gcp.iap.WebRegionBackendServiceIamBinding and gcp.iap.WebRegionBackendServiceIamMember will conflict if they grant privileges to the same role.IAM Conditions
condition block with title, description, and expression fields. For example, use expression: "request.time < timestamp(\"2020-01-01T00:00:00Z\")" for time-based expiration.Configuration & Properties
project, region, and webRegionBackendService properties are immutable and cannot be changed after resource creation.gcp.organizations.getIAMPolicy data source to generate policyData, then pass it to the policyData property as shown in the examples.