The gcp:iap/webIamMember:WebIamMember resource, part of the Pulumi GCP provider, grants IAM permissions to individual identities for IAP-protected web resources without affecting other members of the same role. This guide focuses on two capabilities: non-authoritative single-member grants and time-based access expiration with IAM Conditions.
This resource operates on IAP-protected web resources within a GCP project and assumes IAP is already enabled. The examples are intentionally small. Combine them with your own IAP configuration and identity management.
Grant access to a single user
When managing IAP-protected applications, you often need to add individual users without disrupting existing permissions.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const member = new gcp.iap.WebIamMember("member", {
project: projectService.project,
role: "roles/iap.httpsResourceAccessor",
member: "user:jane@example.com",
});
import pulumi
import pulumi_gcp as gcp
member = gcp.iap.WebIamMember("member",
project=project_service["project"],
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.NewWebIamMember(ctx, "member", &iap.WebIamMemberArgs{
Project: pulumi.Any(projectService.Project),
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.WebIamMember("member", new()
{
Project = projectService.Project,
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.WebIamMember;
import com.pulumi.gcp.iap.WebIamMemberArgs;
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 WebIamMember("member", WebIamMemberArgs.builder()
.project(projectService.project())
.role("roles/iap.httpsResourceAccessor")
.member("user:jane@example.com")
.build());
}
}
resources:
member:
type: gcp:iap:WebIamMember
properties:
project: ${projectService.project}
role: roles/iap.httpsResourceAccessor
member: user:jane@example.com
The member property specifies the identity receiving access, using the format “user:email@example.com”. The role property defines the permission level; “roles/iap.httpsResourceAccessor” allows HTTPS access to IAP-protected resources. Because WebIamMember is non-authoritative, it adds this user without removing other members who already have the same role.
Grant time-limited access with IAM Conditions
IAM Conditions automatically revoke access when expressions evaluate to false, eliminating manual cleanup for temporary grants.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const member = new gcp.iap.WebIamMember("member", {
project: projectService.project,
role: "roles/iap.httpsResourceAccessor",
member: "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
member = gcp.iap.WebIamMember("member",
project=project_service["project"],
role="roles/iap.httpsResourceAccessor",
member="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.NewWebIamMember(ctx, "member", &iap.WebIamMemberArgs{
Project: pulumi.Any(projectService.Project),
Role: pulumi.String("roles/iap.httpsResourceAccessor"),
Member: pulumi.String("user:jane@example.com"),
Condition: &iap.WebIamMemberConditionArgs{
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 member = new Gcp.Iap.WebIamMember("member", new()
{
Project = projectService.Project,
Role = "roles/iap.httpsResourceAccessor",
Member = "user:jane@example.com",
Condition = new Gcp.Iap.Inputs.WebIamMemberConditionArgs
{
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.WebIamMember;
import com.pulumi.gcp.iap.WebIamMemberArgs;
import com.pulumi.gcp.iap.inputs.WebIamMemberConditionArgs;
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 WebIamMember("member", WebIamMemberArgs.builder()
.project(projectService.project())
.role("roles/iap.httpsResourceAccessor")
.member("user:jane@example.com")
.condition(WebIamMemberConditionArgs.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:
member:
type: gcp:iap:WebIamMember
properties:
project: ${projectService.project}
role: roles/iap.httpsResourceAccessor
member: 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")
The condition block defines when access is valid. The expression property uses CEL (Common Expression Language) to compare request.time against a timestamp; access expires when the condition becomes false. The title and description properties document the condition’s purpose. This configuration grants access that automatically expires at midnight on 2020-01-01.
Beyond these examples
These snippets focus on specific IAM member features: single-member grants and time-based access expiration. They’re intentionally minimal rather than complete access control configurations.
The examples assume pre-existing infrastructure such as a GCP project with IAP enabled and IAP-protected web resources. They focus on granting individual permissions rather than provisioning IAP itself.
To keep things focused, common IAM patterns are omitted, including:
- Multi-member role grants (use WebIamBinding)
- Full policy replacement (use WebIamPolicy)
- Complex condition expressions (location, resource attributes)
- Service account and group identities
These omissions are intentional: the goal is to illustrate how IAM member grants are wired, not provide drop-in access control modules. See the IAP WebIamMember resource reference for all available configuration options.
Let's configure Google Cloud IAP Web IAM Permissions
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Resource Conflicts & Compatibility
gcp.iap.WebIamPolicy cannot be used with gcp.iap.WebIamBinding or gcp.iap.WebIamMember because they will conflict over policy control. Choose one approach: use WebIamPolicy alone for authoritative management, or use WebIamBinding/WebIamMember for non-authoritative management.IAM Configuration & Identity Formats
WebIamPolicy is authoritative and replaces the entire policy. WebIamBinding is authoritative for a specific role but preserves other roles. WebIamMember is non-authoritative and adds individual members without affecting existing members for that role.The member property supports multiple formats:
- Special identifiers:
allUsers,allAuthenticatedUsers - Individual accounts:
user:{email},serviceAccount:{email} - Groups and domains:
group:{email},domain:{domain} - Project roles:
projectOwner:{projectid},projectEditor:{projectid},projectViewer:{projectid} - Federated identities:
principal://iam.googleapis.com/...(see GCP Principal identifiers documentation)
[projects|organizations]/{parent-name}/roles/{role-name}. For example, projects/my-project/roles/my-custom-role or organizations/my-org/roles/my-custom-role.IAM Conditions & Advanced Features
condition property with title, description, and expression fields. For time-based restrictions, use expressions like request.time < timestamp("2020-01-01T00:00:00Z") to set expiration dates.Immutability & Lifecycle
member, role, project, and condition. To change any of these, you must destroy and recreate the resource.