The gcp:compute/instanceIAMBinding:InstanceIAMBinding resource, part of the Pulumi GCP provider, manages IAM access to Compute Engine instances by controlling which members have specific roles. This guide focuses on three capabilities: authoritative role management with multiple members, incremental member addition, and time-based access with IAM Conditions.
InstanceIAMBinding is one of three related resources for instance access control. InstanceIAMPolicy replaces the entire policy, InstanceIAMBinding manages all members for a specific role, and InstanceIAMMember adds individual members. The examples are intentionally small. Combine them with your own instance infrastructure and access requirements.
Grant a role to multiple members at once
Teams managing instance access often need to grant the same role to multiple users, service accounts, or groups simultaneously.
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
InstanceIAMBinding is authoritative for the specified role: it controls the complete member list for that role on the instance. The role property specifies which permission set to grant (e.g., “roles/compute.osLogin” for SSH access). The members array lists all identities that should have this role. When you update the members list, the binding replaces the previous member set entirely.
Add a single member to a role incrementally
When multiple teams manage access to the same instance, InstanceIAMMember allows adding individual members without coordinating the full member list.
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
InstanceIAMMember is non-authoritative: it adds one member to a role without affecting other members. This lets different Pulumi stacks or teams grant access independently. The member property takes a single identity (user, service account, group, or domain), while InstanceIAMBinding’s members property takes an array. You can use multiple InstanceIAMMember resources for the same role, but only one InstanceIAMBinding per role.
Apply time-based access with IAM Conditions
Temporary access grants expire automatically when you attach IAM Conditions to bindings.
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"],
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
binding = gcp.compute.InstanceIAMBinding("binding",
project=default["project"],
zone=default["zone"],
instance_name=default["name"],
role="roles/compute.osLogin",
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/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"),
},
Condition: &compute.InstanceIAMBindingConditionArgs{
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 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",
},
Condition = new Gcp.Compute.Inputs.InstanceIAMBindingConditionArgs
{
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.InstanceIAMBinding;
import com.pulumi.gcp.compute.InstanceIAMBindingArgs;
import com.pulumi.gcp.compute.inputs.InstanceIAMBindingConditionArgs;
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")
.condition(InstanceIAMBindingConditionArgs.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:
binding:
type: gcp:compute:InstanceIAMBinding
properties:
project: ${default.project}
zone: ${default.zone}
instanceName: ${default.name}
role: roles/compute.osLogin
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 temporal or contextual constraints to role grants. The expression property uses Common Expression Language (CEL) to define when access is valid. Here, the expression compares request.time against a timestamp to enforce an expiration date. The title and description properties document the condition’s purpose. IAM Conditions work with both InstanceIAMBinding and InstanceIAMMember, but have known limitations documented by Google Cloud.
Beyond these examples
These snippets focus on specific IAM binding features: role-based and member-based access control, and IAM Conditions for time-based access. They’re intentionally minimal rather than full access management solutions.
The examples reference pre-existing infrastructure such as Compute Engine instances and Google Cloud project with configured zone. They focus on configuring IAM bindings rather than provisioning the instances themselves.
To keep things focused, common IAM patterns are omitted, including:
- Full policy replacement (InstanceIAMPolicy resource)
- Custom role definitions and formatting
- Conflict resolution between Policy, Binding, and Member resources
- Advanced IAM Condition expressions (location, resource attributes)
These omissions are intentional: the goal is to illustrate how each IAM binding feature is wired, not provide drop-in access control modules. See the Compute Instance IAM Binding resource reference for all available configuration options.
Let's manage GCP Compute Instance IAM Bindings
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. InstanceIAMMember is non-authoritative, adding a single member to a role while preserving other members.InstanceIAMPolicy cannot be used with InstanceIAMBinding or InstanceIAMMember, as they will conflict. However, InstanceIAMBinding and InstanceIAMMember can be used together only if they manage different roles.Configuration & Identity Management
allUsers, allAuthenticatedUsers, user:{email}, serviceAccount:{email}, group:{email}, domain:{domain}, projectOwner/Editor/Viewer:{projectid}, and federated identities (e.g., principal://iam.googleapis.com/...).[projects|organizations]/{parent-name}/roles/{role-name}.instanceName, role, zone, project, and condition properties are immutable and cannot be changed after creation.project and zone are parsed from the parent resource identifier. If unavailable there, the provider configuration is used.Advanced Features
condition property with title, description, and expression fields. For example, set expression to request.time < timestamp("2020-01-01T00:00:00Z") for access expiring at a specific time.