Manage GCP Pub/Sub Subscription IAM Access

The gcp:pubsub/subscriptionIAMMember:SubscriptionIAMMember resource, part of the Pulumi GCP provider, grants IAM roles to individual identities on Pub/Sub subscriptions without affecting other members or roles. This guide focuses on two capabilities: single-member role grants and multi-member role management.

IAM resources reference existing Pub/Sub subscriptions and assume identities already exist in your GCP organization. The examples are intentionally small. Combine them with your own subscription references and identity management.

Grant a role to a single member

Most IAM configurations grant a specific role to one identity, preserving existing assignments for other members.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const editor = new gcp.pubsub.SubscriptionIAMMember("editor", {
    subscription: "your-subscription-name",
    role: "roles/editor",
    member: "user:jane@example.com",
});
import pulumi
import pulumi_gcp as gcp

editor = gcp.pubsub.SubscriptionIAMMember("editor",
    subscription="your-subscription-name",
    role="roles/editor",
    member="user:jane@example.com")
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/pubsub"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := pubsub.NewSubscriptionIAMMember(ctx, "editor", &pubsub.SubscriptionIAMMemberArgs{
			Subscription: pulumi.String("your-subscription-name"),
			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 editor = new Gcp.PubSub.SubscriptionIAMMember("editor", new()
    {
        Subscription = "your-subscription-name",
        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.pubsub.SubscriptionIAMMember;
import com.pulumi.gcp.pubsub.SubscriptionIAMMemberArgs;
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 editor = new SubscriptionIAMMember("editor", SubscriptionIAMMemberArgs.builder()
            .subscription("your-subscription-name")
            .role("roles/editor")
            .member("user:jane@example.com")
            .build());

    }
}
resources:
  editor:
    type: gcp:pubsub:SubscriptionIAMMember
    properties:
      subscription: your-subscription-name
      role: roles/editor
      member: user:jane@example.com

The member property specifies the identity receiving access, using formats like user:email@example.com or serviceAccount:name@project.iam.gserviceaccount.com. The role property defines the permission level. SubscriptionIAMMember is non-authoritative: it adds this member without removing others who already have the role.

Grant a role to multiple members at once

When multiple identities need the same role, SubscriptionIAMBinding manages the complete member list.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const editor = new gcp.pubsub.SubscriptionIAMBinding("editor", {
    subscription: "your-subscription-name",
    role: "roles/editor",
    members: ["user:jane@example.com"],
});
import pulumi
import pulumi_gcp as gcp

editor = gcp.pubsub.SubscriptionIAMBinding("editor",
    subscription="your-subscription-name",
    role="roles/editor",
    members=["user:jane@example.com"])
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/pubsub"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := pubsub.NewSubscriptionIAMBinding(ctx, "editor", &pubsub.SubscriptionIAMBindingArgs{
			Subscription: pulumi.String("your-subscription-name"),
			Role:         pulumi.String("roles/editor"),
			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 editor = new Gcp.PubSub.SubscriptionIAMBinding("editor", new()
    {
        Subscription = "your-subscription-name",
        Role = "roles/editor",
        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.pubsub.SubscriptionIAMBinding;
import com.pulumi.gcp.pubsub.SubscriptionIAMBindingArgs;
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 editor = new SubscriptionIAMBinding("editor", SubscriptionIAMBindingArgs.builder()
            .subscription("your-subscription-name")
            .role("roles/editor")
            .members("user:jane@example.com")
            .build());

    }
}
resources:
  editor:
    type: gcp:pubsub:SubscriptionIAMBinding
    properties:
      subscription: your-subscription-name
      role: roles/editor
      members:
        - user:jane@example.com

The members property lists all identities that should have this role. SubscriptionIAMBinding is authoritative for the specified role: it replaces any existing members for that role but preserves other roles on the subscription. Use this when you want to control the full member list for a role in one place.

Beyond these examples

These snippets focus on specific IAM binding features: single-member and multi-member role grants. They’re intentionally minimal rather than full access control configurations.

The examples reference pre-existing infrastructure such as Pub/Sub subscriptions. They focus on granting access rather than creating the underlying resources.

To keep things focused, common IAM patterns are omitted, including:

  • Conditional IAM bindings (condition property)
  • Full policy replacement (SubscriptionIAMPolicy)
  • Custom role definitions

These omissions are intentional: the goal is to illustrate how IAM bindings are wired, not provide drop-in access control modules. See the Pub/Sub SubscriptionIAMMember resource reference for all available configuration options.

Let's manage GCP Pub/Sub Subscription IAM Access

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 SubscriptionIAMPolicy, SubscriptionIAMBinding, and SubscriptionIAMMember?
SubscriptionIAMPolicy is authoritative and replaces the entire IAM policy. SubscriptionIAMBinding is authoritative for a specific role, preserving other roles. SubscriptionIAMMember is non-authoritative, adding a single member to a role while preserving other members.
Can I use these IAM resources together?
SubscriptionIAMPolicy cannot be used with SubscriptionIAMBinding or SubscriptionIAMMember, as they’ll conflict over the policy. You can use SubscriptionIAMBinding and SubscriptionIAMMember together only if they don’t grant privileges to the same role.
Configuration & Formats
What member formats are supported?

The member property supports these formats:

  • allUsers - Anyone on the internet
  • allAuthenticatedUsers - Anyone with a Google account
  • user:{email} - Specific Google account (e.g., user:alice@gmail.com)
  • serviceAccount:{email} - Service account (e.g., serviceAccount:my-app@appspot.gserviceaccount.com)
  • group:{email} - Google group (e.g., group:admins@example.com)
  • domain:{domain} - G Suite domain (e.g., domain:example.com)
What format do custom roles need?
Custom roles must use the format [projects|organizations]/{parent-name}/roles/{role-name}.
Immutability & Lifecycle
Can I change the member, role, or subscription after creation?
No, all properties (member, role, subscription, project, condition) are immutable and require resource recreation to change.
What is the etag output used for?
The etag is a computed output representing the subscription’s IAM policy version, useful for detecting policy changes.

Using a different cloud?

Explore security guides for other cloud providers: