Configure Google Cloud IAP Web IAM Permissions

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 FREE

Frequently Asked Questions

Resource Conflicts & Compatibility
Can I use WebIamPolicy with WebIamBinding or WebIamMember?
No, 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.
Can I use WebIamBinding and WebIamMember together?
Yes, but only if they don’t grant privileges to the same role. Using both resources for the same role will cause conflicts.
IAM Configuration & Identity Formats
What's the difference between WebIamPolicy, WebIamBinding, and WebIamMember?
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.
What identity formats can I use for the member property?

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)
How do I specify a custom IAM role?
Custom roles must use the format [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
How do I add time-based access restrictions?
Use the 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.
What are the limitations of IAM Conditions?
IAM Conditions are supported but have known limitations. If you encounter issues with conditions, review the GCP documentation on IAM Conditions limitations.
Immutability & Lifecycle
What properties are immutable after creation?
All core properties are immutable: member, role, project, and condition. To change any of these, you must destroy and recreate the resource.

Using a different cloud?

Explore iam guides for other cloud providers: