Manage GCP Folder IAM Members

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 FREE

Frequently Asked Questions

Resource Selection & Compatibility
What's the difference between IAMPolicy, IAMBinding, and IAMMember?
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.
Can I use IAMPolicy with other folder IAM resources?
No, gcp.folder.IAMPolicy cannot be used with gcp.folder.IAMBinding, gcp.folder.IAMMember, or gcp.folder.IamAuditConfig as they will conflict over the policy.
Can I use IAMBinding and IAMMember together?
Yes, but only if they don’t grant privileges to the same role. Using both for the same role causes conflicts.
Configuration & Syntax
What member formats are supported?
Four formats are supported: user:{emailid} for Google accounts, serviceAccount:{emailid} for service accounts, group:{emailid} for Google groups, and domain:{domain} for G Suite domains.
What format do custom roles require?
Custom roles must use the format organizations/{{org_id}}/roles/{{role_id}}. This full path is required for both configuration and import operations.
How do I add time-based or conditional access?
Use the 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
How do I avoid locking myself out with IAMPolicy?
Deleting 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.
Why am I getting a 400 error when using IAM Conditions?
IAM Conditions cannot be used with Basic Roles like Owner. Use predefined or custom roles instead.
What properties are immutable after creation?
The folder, member, role, and condition properties are all immutable and require resource replacement if changed.

Using a different cloud?

Explore security guides for other cloud providers: