The gcp:projects/iAMBinding:IAMBinding resource, part of the Pulumi GCP provider, grants a GCP IAM role to a list of members at the project level, replacing any existing members for that role. This guide focuses on two capabilities: authoritative role assignment to multiple members and time-based conditional access.
IAMBinding is one of four IAM resources for project access control. It’s authoritative for a single role, meaning it replaces the member list for that role while preserving other roles. Use IAMMember for incremental additions or IAMPolicy for complete policy control. Bindings reference existing projects and grant access to identities that must exist. The examples are intentionally small. Combine them with your own project IDs and identity management.
Grant a role to multiple members
When managing project access, you often need to grant the same role to multiple users, service accounts, or groups at once.
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
The members array lists identities that receive the specified role. Each entry uses a prefix (user:, serviceAccount:, group:, or domain:) followed by the identifier. IAMBinding is authoritative for this role, so any members not in this list lose access when you apply the configuration.
Add time-based access with IAM Conditions
Temporary access grants expire automatically when you attach IAM Conditions, eliminating manual cleanup for contractors or time-limited permissions.
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/container.admin",
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
project = gcp.projects.IAMBinding("project",
project="your-project-id",
role="roles/container.admin",
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/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/container.admin"),
Members: pulumi.StringArray{
pulumi.String("user:jane@example.com"),
},
Condition: &projects.IAMBindingConditionArgs{
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.IAMBinding("project", new()
{
Project = "your-project-id",
Role = "roles/container.admin",
Members = new[]
{
"user:jane@example.com",
},
Condition = new Gcp.Projects.Inputs.IAMBindingConditionArgs
{
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.IAMBinding;
import com.pulumi.gcp.projects.IAMBindingArgs;
import com.pulumi.gcp.projects.inputs.IAMBindingConditionArgs;
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/container.admin")
.members("user:jane@example.com")
.condition(IAMBindingConditionArgs.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:IAMBinding
properties:
project: your-project-id
role: roles/container.admin
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")
The condition block adds a CEL expression that controls when the binding applies. The expression property uses Common Expression Language to define access rules; here, it checks whether the current time is before a timestamp. The title and description properties document the condition’s purpose. When the condition evaluates to false, members lose access automatically.
Beyond these examples
These snippets focus on specific IAMBinding features: role-based access control and time-based conditional access. They’re intentionally minimal rather than full access management solutions.
The examples reference pre-existing infrastructure such as GCP projects with valid project IDs, and user accounts, service accounts, or groups to grant access to. They focus on configuring the binding rather than provisioning identity infrastructure.
To keep things focused, common IAM patterns are omitted, including:
- Single-member grants (use IAMMember for incremental additions)
- Full policy replacement (use IAMPolicy for complete control)
- Audit logging configuration (use IAMAuditConfig)
- Resource-level conditions beyond time-based expiration
These omissions are intentional: the goal is to illustrate how IAMBinding wires role assignments, not provide drop-in access control modules. See the IAMBinding resource reference for all available configuration options.
Let's configure GCP Project IAM Bindings
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Safety & Lockout Prevention
gcp.projects.IAMPolicy removes access from anyone without organization-level access to the project. It’s recommended to import the policy before applying changes and avoid using IAMPolicy with your provider project. Only use it with projects fully managed by Pulumi.gcp.projects.IAMPolicy.Resource Compatibility
gcp.projects.IAMPolicy is authoritative and replaces the entire IAM policy. gcp.projects.IAMBinding is authoritative for a given role, preserving other roles. gcp.projects.IAMMember is non-authoritative, adding one member to a role while preserving other members. gcp.projects.IAMAuditConfig is authoritative for audit logging on a given service.gcp.projects.IAMPolicy cannot be used with gcp.projects.IAMBinding, gcp.projects.IAMMember, or gcp.projects.IAMAuditConfig because they will conflict over the policy.IAMBinding or IAMMember, not both.Configuration & Member Formats
Four formats are supported:
- user:{emailid} - Specific Google account (e.g.,
alice@gmail.com) - serviceAccount:{emailid} - Service account (e.g.,
my-app@appspot.gserviceaccount.com) - group:{emailid} - Google group (e.g.,
admins@example.com) - domain:{domain} - G Suite domain for all users (e.g.,
example.com)
[projects|organizations]/{parent-name}/roles/{role-name}.condition block with title, description, and expression fields. For example, to create a time-based condition, use an expression like request.time < timestamp("2020-01-01T00:00:00Z").Limitations & Constraints
project property is not inferred from the provider and must be explicitly specified for the target project.role and project are immutable properties and cannot be changed after resource creation.