The gcp:compute/storagePoolIamMember:StoragePoolIamMember resource, part of the Pulumi GCP provider, grants IAM access to Compute Engine storage pools by adding individual members to roles without affecting other bindings. This guide focuses on two capabilities: single-member role grants and time-based access expiration with IAM Conditions.
This resource is non-authoritative: it adds one member to one role while preserving other members and roles. It references existing storage pools by name, project, and zone. The examples are intentionally small. Combine them with your own storage pool infrastructure and access policies.
Grant a single user access to a storage pool
When you need to add one user or service account to a role without replacing existing members, StoragePoolIamMember preserves other access grants.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const member = new gcp.compute.StoragePoolIamMember("member", {
project: test_storage_pool_basic.project,
zone: test_storage_pool_basic.zone,
name: test_storage_pool_basic.name,
role: "roles/compute.viewer",
member: "user:jane@example.com",
});
import pulumi
import pulumi_gcp as gcp
member = gcp.compute.StoragePoolIamMember("member",
project=test_storage_pool_basic["project"],
zone=test_storage_pool_basic["zone"],
name=test_storage_pool_basic["name"],
role="roles/compute.viewer",
member="user:jane@example.com")
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/compute"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := compute.NewStoragePoolIamMember(ctx, "member", &compute.StoragePoolIamMemberArgs{
Project: pulumi.Any(test_storage_pool_basic.Project),
Zone: pulumi.Any(test_storage_pool_basic.Zone),
Name: pulumi.Any(test_storage_pool_basic.Name),
Role: pulumi.String("roles/compute.viewer"),
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.Compute.StoragePoolIamMember("member", new()
{
Project = test_storage_pool_basic.Project,
Zone = test_storage_pool_basic.Zone,
Name = test_storage_pool_basic.Name,
Role = "roles/compute.viewer",
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.compute.StoragePoolIamMember;
import com.pulumi.gcp.compute.StoragePoolIamMemberArgs;
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 StoragePoolIamMember("member", StoragePoolIamMemberArgs.builder()
.project(test_storage_pool_basic.project())
.zone(test_storage_pool_basic.zone())
.name(test_storage_pool_basic.name())
.role("roles/compute.viewer")
.member("user:jane@example.com")
.build());
}
}
resources:
member:
type: gcp:compute:StoragePoolIamMember
properties:
project: ${["test-storage-pool-basic"].project}
zone: ${["test-storage-pool-basic"].zone}
name: ${["test-storage-pool-basic"].name}
role: roles/compute.viewer
member: user:jane@example.com
The member property identifies who receives access (user, service account, group, or domain). The role property specifies the permission level. The name, project, and zone properties locate the storage pool. This resource adds the member to the role without affecting other members already granted that role or other roles on the same storage pool.
Add 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.compute.StoragePoolIamMember("member", {
project: test_storage_pool_basic.project,
zone: test_storage_pool_basic.zone,
name: test_storage_pool_basic.name,
role: "roles/compute.viewer",
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.compute.StoragePoolIamMember("member",
project=test_storage_pool_basic["project"],
zone=test_storage_pool_basic["zone"],
name=test_storage_pool_basic["name"],
role="roles/compute.viewer",
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/compute"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := compute.NewStoragePoolIamMember(ctx, "member", &compute.StoragePoolIamMemberArgs{
Project: pulumi.Any(test_storage_pool_basic.Project),
Zone: pulumi.Any(test_storage_pool_basic.Zone),
Name: pulumi.Any(test_storage_pool_basic.Name),
Role: pulumi.String("roles/compute.viewer"),
Member: pulumi.String("user:jane@example.com"),
Condition: &compute.StoragePoolIamMemberConditionArgs{
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.Compute.StoragePoolIamMember("member", new()
{
Project = test_storage_pool_basic.Project,
Zone = test_storage_pool_basic.Zone,
Name = test_storage_pool_basic.Name,
Role = "roles/compute.viewer",
Member = "user:jane@example.com",
Condition = new Gcp.Compute.Inputs.StoragePoolIamMemberConditionArgs
{
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.compute.StoragePoolIamMember;
import com.pulumi.gcp.compute.StoragePoolIamMemberArgs;
import com.pulumi.gcp.compute.inputs.StoragePoolIamMemberConditionArgs;
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 StoragePoolIamMember("member", StoragePoolIamMemberArgs.builder()
.project(test_storage_pool_basic.project())
.zone(test_storage_pool_basic.zone())
.name(test_storage_pool_basic.name())
.role("roles/compute.viewer")
.member("user:jane@example.com")
.condition(StoragePoolIamMemberConditionArgs.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:compute:StoragePoolIamMember
properties:
project: ${["test-storage-pool-basic"].project}
zone: ${["test-storage-pool-basic"].zone}
name: ${["test-storage-pool-basic"].name}
role: roles/compute.viewer
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 evaluate request context; here it checks whether the current time is before midnight on January 1, 2020. The title and description properties document the condition’s purpose. When the expression evaluates to false, GCP denies access even though the member-role binding still exists.
Beyond these examples
These snippets focus on specific member-level features: single-member IAM grants and time-based access expiration. They’re intentionally minimal rather than full access control policies.
The examples reference pre-existing infrastructure such as storage pools (identified by name, project, and zone). They focus on granting access rather than provisioning storage pools or managing complete IAM policies.
To keep things focused, common IAM patterns are omitted, including:
- Full policy replacement (StoragePoolIamPolicy)
- Role-level binding management (StoragePoolIamBinding)
- Complex condition expressions (location, resource attributes)
- Custom role definitions
These omissions are intentional: the goal is to illustrate how member grants are wired, not provide drop-in access control modules. See the StoragePoolIamMember resource reference for all available configuration options.
Let's manage GCP Storage Pool IAM Access
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Resource Conflicts & Compatibility
StoragePoolIamPolicy cannot be used together with StoragePoolIamBinding or StoragePoolIamMember, as they will conflict over the policy. Use either the authoritative IamPolicy resource OR the non-authoritative IamBinding/IamMember resources, but not both.IAM Configuration
You can use multiple formats:
- Special identifiers:
allUsers,allAuthenticatedUsers - User accounts:
user:alice@gmail.com - Service accounts:
serviceAccount:my-app@appspot.gserviceaccount.com - Groups:
group:admins@example.com - Domains:
domain:example.com - Project roles:
projectOwner:my-project,projectEditor:my-project,projectViewer:my-project - Federated identities:
principal://iam.googleapis.com/locations/global/workforcePools/example-contractors/subject/joe@example.com
[projects|organizations]/{parent-name}/roles/{role-name}. For example: projects/my-project/roles/customStorageRole or organizations/my-org/roles/customRole.condition property with title, description, and expression fields. For example, to expire at midnight on 2020-01-01: expression: "request.time < timestamp(\"2020-01-01T00:00:00Z\")".Resource Properties
member, role, name, project, zone, and condition. To change any of these, you must recreate the resource.