The gcp:folder/iAMMember:IAMMember resource, part of the Pulumi GCP provider, grants a single member access to a folder role without affecting other members already assigned to that role. This guide focuses on two capabilities: single-member role grants and time-based IAM Conditions.
IAMMember is non-authoritative: it adds one member to a role while preserving existing members. It references folders by numeric ID and can work alongside IAMBinding resources as long as they manage different roles. The examples are intentionally small. Combine them with your own folder hierarchy and access policies.
Grant a single member access to a folder
Most IAM configurations add individual users or service accounts to roles without disrupting existing access.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const folder = new gcp.folder.IAMMember("folder", {
folder: "folders/1234567",
role: "roles/editor",
member: "user:jane@example.com",
});
import pulumi
import pulumi_gcp as gcp
folder = gcp.folder.IAMMember("folder",
folder="folders/1234567",
role="roles/editor",
member="user:jane@example.com")
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/folder"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := folder.NewIAMMember(ctx, "folder", &folder.IAMMemberArgs{
Folder: pulumi.String("folders/1234567"),
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 folder = new Gcp.Folder.IAMMember("folder", new()
{
Folder = "folders/1234567",
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.folder.IAMMember;
import com.pulumi.gcp.folder.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 folder = new IAMMember("folder", IAMMemberArgs.builder()
.folder("folders/1234567")
.role("roles/editor")
.member("user:jane@example.com")
.build());
}
}
resources:
folder:
type: gcp:folder:IAMMember
properties:
folder: folders/1234567
role: roles/editor
member: user:jane@example.com
The folder property identifies the target folder using its numeric ID (format: “folders/{folder_id}”). The role property specifies a predefined or custom role. The member property identifies one principal using the format “user:{email}”, “serviceAccount:{email}”, “group:{email}”, or “domain:{domain}”. This resource is non-authoritative: it adds this member to the role without removing others.
Grant time-limited access with IAM Conditions
Temporary access grants expire automatically when their condition evaluates to false, eliminating manual cleanup.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const folder = new gcp.folder.IAMMember("folder", {
folder: "folders/1234567",
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
folder = gcp.folder.IAMMember("folder",
folder="folders/1234567",
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/folder"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := folder.NewIAMMember(ctx, "folder", &folder.IAMMemberArgs{
Folder: pulumi.String("folders/1234567"),
Role: pulumi.String("roles/firebase.admin"),
Member: pulumi.String("user:jane@example.com"),
Condition: &folder.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 folder = new Gcp.Folder.IAMMember("folder", new()
{
Folder = "folders/1234567",
Role = "roles/firebase.admin",
Member = "user:jane@example.com",
Condition = new Gcp.Folder.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.folder.IAMMember;
import com.pulumi.gcp.folder.IAMMemberArgs;
import com.pulumi.gcp.folder.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 folder = new IAMMember("folder", IAMMemberArgs.builder()
.folder("folders/1234567")
.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:
folder:
type: gcp:folder:IAMMember
properties:
folder: folders/1234567
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 attaches restrictions to the role binding. The title property names the condition for identification. The expression property uses Common Expression Language (CEL) to define when access is granted; here, “request.time < timestamp(…)” expires access at midnight on 2020-01-01. IAM Conditions cannot be used with Basic Roles like Owner; use predefined or custom roles instead.
Beyond these examples
These snippets focus on specific IAMMember features: single-member role grants and time-based IAM Conditions. They’re intentionally minimal rather than full access control policies.
The examples reference pre-existing infrastructure such as GCP folders with numeric IDs. They focus on granting member access rather than provisioning folder hierarchies.
To keep things focused, common folder IAM patterns are omitted, including:
- Multi-member role grants (IAMBinding)
- Full policy replacement (IAMPolicy)
- Audit logging configuration (IamAuditConfig)
- Service accounts and groups as members
These omissions are intentional: the goal is to illustrate how IAMMember grants are wired, not provide drop-in access control modules. See the Folder IAMMember resource reference for all available configuration options.
Let's manage GCP Folder 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 & Compatibility
gcp.folder.IAMPolicy is authoritative and replaces the entire IAM policy. gcp.folder.IAMBinding is authoritative for a specific role but preserves other roles. gcp.folder.IAMMember is non-authoritative and adds a single member to a role while preserving other members.gcp.folder.IAMPolicy cannot be used with gcp.folder.IAMBinding, gcp.folder.IAMMember, or gcp.folder.IamAuditConfig as they will conflict over the policy.Configuration & Syntax
user:{emailid} for Google accounts, serviceAccount:{emailid} for service accounts, group:{emailid} for Google groups, and domain:{domain} for G Suite domains.organizations/{{org_id}}/roles/{{role_id}}. This full path is required for both configuration and import operations.condition property with title, description, and expression fields. For example, set expression to request.time < timestamp("2020-01-01T00:00:00Z") for time-based expiration.Common Pitfalls & Errors
gcp.folder.IAMPolicy removes all access for users without parent folder/organization permissions. Import the existing policy before applying changes, and avoid using gcp.folder.IAMPolicy with your provider folder.folder, member, role, and condition properties are all immutable and require resource replacement if changed.