The gcp:projects/iAMMember:IAMMember resource, part of the Pulumi GCP provider, grants a single identity access to a project-level IAM role without affecting other members of that role. This guide focuses on three capabilities: non-authoritative member assignment, time-limited access with IAM Conditions, and authoritative role binding with IAMBinding.
IAM resources reference existing GCP projects and identities. The examples are intentionally small. Combine them with your own project IDs and identity management.
Grant a single member access to a role
Most IAM configurations add one identity to a role without disrupting existing assignments.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const project = new gcp.projects.IAMMember("project", {
project: "your-project-id",
role: "roles/editor",
member: "user:jane@example.com",
});
import pulumi
import pulumi_gcp as gcp
project = gcp.projects.IAMMember("project",
project="your-project-id",
role="roles/editor",
member="user:jane@example.com")
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/projects"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := projects.NewIAMMember(ctx, "project", &projects.IAMMemberArgs{
Project: pulumi.String("your-project-id"),
Role: pulumi.String("roles/editor"),
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 project = new Gcp.Projects.IAMMember("project", new()
{
Project = "your-project-id",
Role = "roles/editor",
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.projects.IAMMember;
import com.pulumi.gcp.projects.IAMMemberArgs;
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 project = new IAMMember("project", IAMMemberArgs.builder()
.project("your-project-id")
.role("roles/editor")
.member("user:jane@example.com")
.build());
}
}
resources:
project:
type: gcp:projects:IAMMember
properties:
project: your-project-id
role: roles/editor
member: user:jane@example.com
The member property specifies the identity using a prefix format: user: for Google accounts, serviceAccount: for service accounts, group: for Google groups, or domain: for G Suite domains. The role property references a predefined or custom role. IAMMember is non-authoritative, so it preserves other members already assigned to the role.
Add time-limited access with IAM Conditions
Teams often grant temporary access that expires automatically, such as contractor access or time-boxed privileges.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const project = new gcp.projects.IAMMember("project", {
project: "your-project-id",
role: "roles/firebase.admin",
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
project = gcp.projects.IAMMember("project",
project="your-project-id",
role="roles/firebase.admin",
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/projects"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := projects.NewIAMMember(ctx, "project", &projects.IAMMemberArgs{
Project: pulumi.String("your-project-id"),
Role: pulumi.String("roles/firebase.admin"),
Member: pulumi.String("user:jane@example.com"),
Condition: &projects.IAMMemberConditionArgs{
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 project = new Gcp.Projects.IAMMember("project", new()
{
Project = "your-project-id",
Role = "roles/firebase.admin",
Member = "user:jane@example.com",
Condition = new Gcp.Projects.Inputs.IAMMemberConditionArgs
{
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.projects.IAMMember;
import com.pulumi.gcp.projects.IAMMemberArgs;
import com.pulumi.gcp.projects.inputs.IAMMemberConditionArgs;
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 project = new IAMMember("project", IAMMemberArgs.builder()
.project("your-project-id")
.role("roles/firebase.admin")
.member("user:jane@example.com")
.condition(IAMMemberConditionArgs.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:
project:
type: gcp:projects:IAMMember
properties:
project: your-project-id
role: roles/firebase.admin
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 adds time-based constraints to the role binding. The expression property uses Common Expression Language (CEL) to define when access is valid. Here, request.time < timestamp("2020-01-01T00:00:00Z") grants access until midnight on December 31, 2019. The title property uniquely identifies the condition.
Replace all members for a role with IAMBinding
When you need to define the complete set of members for a role, IAMBinding provides authoritative control.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const project = new gcp.projects.IAMBinding("project", {
project: "your-project-id",
role: "roles/editor",
members: ["user:jane@example.com"],
});
import pulumi
import pulumi_gcp as gcp
project = gcp.projects.IAMBinding("project",
project="your-project-id",
role="roles/editor",
members=["user:jane@example.com"])
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/projects"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := projects.NewIAMBinding(ctx, "project", &projects.IAMBindingArgs{
Project: pulumi.String("your-project-id"),
Role: pulumi.String("roles/editor"),
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 project = new Gcp.Projects.IAMBinding("project", new()
{
Project = "your-project-id",
Role = "roles/editor",
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.projects.IAMBinding;
import com.pulumi.gcp.projects.IAMBindingArgs;
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 project = new IAMBinding("project", IAMBindingArgs.builder()
.project("your-project-id")
.role("roles/editor")
.members("user:jane@example.com")
.build());
}
}
resources:
project:
type: gcp:projects:IAMBinding
properties:
project: your-project-id
role: roles/editor
members:
- user:jane@example.com
IAMBinding replaces any existing members for the specified role with the members array. This is authoritative for the role: any members not listed are removed. Use IAMBinding when you want to define the exact membership list, and IAMMember when you want to add members incrementally.
Beyond these examples
These snippets focus on specific IAM assignment features: single-member and multi-member role assignment, and time-based access with IAM Conditions. They’re intentionally minimal rather than full access control policies.
The examples reference pre-existing infrastructure such as GCP projects with project IDs, and user accounts, service accounts, or groups to grant access to. They focus on configuring role assignments rather than provisioning projects or identities.
To keep things focused, common IAM patterns are omitted, including:
- IAMPolicy for full policy replacement (high risk of lockout)
- IAMAuditConfig for audit logging configuration
- Custom role definitions (assumes predefined roles)
- Domain-wide delegation and group membership
These omissions are intentional: the goal is to illustrate how each IAM assignment feature is wired, not provide drop-in access control modules. See the IAMMember resource reference for all available configuration options.
Let's manage GCP Project IAM Members
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.projects.IAMPolicy is authoritative and replaces the entire IAM policy. gcp.projects.IAMBinding is authoritative for a specific role, preserving other roles. gcp.projects.IAMMember is non-authoritative, adding a single member to a role while preserving other members.gcp.projects.IAMPolicy cannot be used with gcp.projects.IAMBinding, gcp.projects.IAMMember, or gcp.projects.IAMAuditConfig. They will conflict over the policy state.Security & Access Control
gcp.projects.IAMPolicy removes access from anyone without organization-level access. It’s not recommended to use gcp.projects.IAMPolicy with your provider project. Import the policy before applying changes.user:{emailid} for Google accounts, serviceAccount:{emailid} for service accounts, group:{emailid} for Google groups, and domain:{domain} for G Suite domains.Configuration & Constraints
[projects|organizations]/{parent-name}/roles/{role-name}, for example projects/my-project/roles/my-custom-role.project property is required and not inferred from the provider.Immutability & Lifecycle
member, project, role, and condition properties are all immutable. Changing any of these requires recreating the resource.[projects/my-project|organizations/my-org]/roles/my-custom-role when importing.terraform import google_project_iam_binding.my_project "{{your-project-id}} roles/{{role_id}} condition-title".