The gcp:compute/instanceIAMMember:InstanceIAMMember resource, part of the Pulumi GCP provider, grants IAM permissions on Compute Engine instances by adding individual members to roles. This guide focuses on three capabilities: single-member role grants, time-limited access with IAM Conditions, and multi-member role bindings.
Three related resources manage instance IAM: InstanceIAMPolicy (authoritative, replaces entire policy), InstanceIAMBinding (authoritative for one role), and InstanceIAMMember (non-authoritative, adds one member). InstanceIAMPolicy cannot be used with the other two; they conflict. The examples are intentionally small. Combine them with your own instance references and identity management.
Grant a single user access to an instance
Most IAM configurations add individual users to specific roles without affecting other permissions.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const member = new gcp.compute.InstanceIAMMember("member", {
project: _default.project,
zone: _default.zone,
instanceName: _default.name,
role: "roles/compute.osLogin",
member: "user:jane@example.com",
});
import pulumi
import pulumi_gcp as gcp
member = gcp.compute.InstanceIAMMember("member",
project=default["project"],
zone=default["zone"],
instance_name=default["name"],
role="roles/compute.osLogin",
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.NewInstanceIAMMember(ctx, "member", &compute.InstanceIAMMemberArgs{
Project: pulumi.Any(_default.Project),
Zone: pulumi.Any(_default.Zone),
InstanceName: pulumi.Any(_default.Name),
Role: pulumi.String("roles/compute.osLogin"),
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.InstanceIAMMember("member", new()
{
Project = @default.Project,
Zone = @default.Zone,
InstanceName = @default.Name,
Role = "roles/compute.osLogin",
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.InstanceIAMMember;
import com.pulumi.gcp.compute.InstanceIAMMemberArgs;
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 InstanceIAMMember("member", InstanceIAMMemberArgs.builder()
.project(default_.project())
.zone(default_.zone())
.instanceName(default_.name())
.role("roles/compute.osLogin")
.member("user:jane@example.com")
.build());
}
}
resources:
member:
type: gcp:compute:InstanceIAMMember
properties:
project: ${default.project}
zone: ${default.zone}
instanceName: ${default.name}
role: roles/compute.osLogin
member: user:jane@example.com
The member property identifies who receives access, using formats like “user:jane@example.com” for Google accounts or “serviceAccount:app@project.iam.gserviceaccount.com” for service accounts. The role property specifies the permission set, such as “roles/compute.osLogin” for SSH access. InstanceIAMMember is non-authoritative: it adds this one member to this one role, preserving other members and other roles on the instance.
Add time-limited access with IAM Conditions
Temporary access expires automatically when you attach time constraints to role bindings.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const member = new gcp.compute.InstanceIAMMember("member", {
project: _default.project,
zone: _default.zone,
instanceName: _default.name,
role: "roles/compute.osLogin",
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.InstanceIAMMember("member",
project=default["project"],
zone=default["zone"],
instance_name=default["name"],
role="roles/compute.osLogin",
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.NewInstanceIAMMember(ctx, "member", &compute.InstanceIAMMemberArgs{
Project: pulumi.Any(_default.Project),
Zone: pulumi.Any(_default.Zone),
InstanceName: pulumi.Any(_default.Name),
Role: pulumi.String("roles/compute.osLogin"),
Member: pulumi.String("user:jane@example.com"),
Condition: &compute.InstanceIAMMemberConditionArgs{
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.InstanceIAMMember("member", new()
{
Project = @default.Project,
Zone = @default.Zone,
InstanceName = @default.Name,
Role = "roles/compute.osLogin",
Member = "user:jane@example.com",
Condition = new Gcp.Compute.Inputs.InstanceIAMMemberConditionArgs
{
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.InstanceIAMMember;
import com.pulumi.gcp.compute.InstanceIAMMemberArgs;
import com.pulumi.gcp.compute.inputs.InstanceIAMMemberConditionArgs;
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 InstanceIAMMember("member", InstanceIAMMemberArgs.builder()
.project(default_.project())
.zone(default_.zone())
.instanceName(default_.name())
.role("roles/compute.osLogin")
.member("user:jane@example.com")
.condition(InstanceIAMMemberConditionArgs.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:InstanceIAMMember
properties:
project: ${default.project}
zone: ${default.zone}
instanceName: ${default.name}
role: roles/compute.osLogin
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 logic to the role binding. The expression property uses Common Expression Language (CEL) to define when the binding applies; here, “request.time < timestamp(…)” expires access at midnight on 2020-01-01. The title and description properties document the condition’s purpose. IAM Conditions have known limitations; review Google Cloud’s documentation before using them in production.
Grant a role to multiple members at once
When several identities need identical permissions, InstanceIAMBinding manages all members for one role together.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const binding = new gcp.compute.InstanceIAMBinding("binding", {
project: _default.project,
zone: _default.zone,
instanceName: _default.name,
role: "roles/compute.osLogin",
members: ["user:jane@example.com"],
});
import pulumi
import pulumi_gcp as gcp
binding = gcp.compute.InstanceIAMBinding("binding",
project=default["project"],
zone=default["zone"],
instance_name=default["name"],
role="roles/compute.osLogin",
members=["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.NewInstanceIAMBinding(ctx, "binding", &compute.InstanceIAMBindingArgs{
Project: pulumi.Any(_default.Project),
Zone: pulumi.Any(_default.Zone),
InstanceName: pulumi.Any(_default.Name),
Role: pulumi.String("roles/compute.osLogin"),
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 binding = new Gcp.Compute.InstanceIAMBinding("binding", new()
{
Project = @default.Project,
Zone = @default.Zone,
InstanceName = @default.Name,
Role = "roles/compute.osLogin",
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.compute.InstanceIAMBinding;
import com.pulumi.gcp.compute.InstanceIAMBindingArgs;
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 binding = new InstanceIAMBinding("binding", InstanceIAMBindingArgs.builder()
.project(default_.project())
.zone(default_.zone())
.instanceName(default_.name())
.role("roles/compute.osLogin")
.members("user:jane@example.com")
.build());
}
}
resources:
binding:
type: gcp:compute:InstanceIAMBinding
properties:
project: ${default.project}
zone: ${default.zone}
instanceName: ${default.name}
role: roles/compute.osLogin
members:
- user:jane@example.com
The members property lists all identities that should have this role. InstanceIAMBinding is authoritative for its role: it replaces any existing member list for “roles/compute.osLogin” on this instance. Use InstanceIAMMember instead if you need to add members without affecting others, or if multiple Pulumi stacks manage the same role.
Beyond these examples
These snippets focus on specific IAM management patterns: single-member grants, multi-member role bindings, and time-based access with IAM Conditions. They’re intentionally minimal rather than full access control configurations.
The examples reference pre-existing infrastructure such as Compute Engine instances and a Google Cloud project with configured zone. They focus on granting permissions rather than provisioning instances or defining custom roles.
To keep things focused, common IAM patterns are omitted, including:
- Full policy replacement (InstanceIAMPolicy resource)
- Custom role definitions and formatting
- Service account and group identity patterns
- Federated identity and workload identity pool configuration
These omissions are intentional: the goal is to illustrate how each IAM resource type is wired, not provide drop-in access control modules. See the Compute Instance IAM Member resource reference for all available configuration options.
Let's manage GCP Compute Instance 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 Selection & Conflicts
InstanceIAMPolicy is authoritative and replaces the entire IAM policy. InstanceIAMBinding is authoritative for a specific role, preserving other roles in the policy. InstanceIAMMember is non-authoritative and adds a single member to a role while preserving other members for that role.InstanceIAMPolicy cannot be used with InstanceIAMBinding or InstanceIAMMember because they will conflict over the policy configuration.Configuration & Identity Formats
allUsers, allAuthenticatedUsers, user:{email}, serviceAccount:{email}, group:{email}, domain:{domain}, projectOwner:projectid, projectEditor:projectid, projectViewer:projectid, and federated identities like principal://iam.googleapis.com/....[projects|organizations]/{parent-name}/roles/{role-name}, for example projects/my-project/roles/my-custom-role.instanceName, member, role, project, zone, and condition) are immutable and require resource replacement if changed.Advanced Features
condition block with title, description, and expression fields. However, IAM Conditions have known limitations that you should review before use.