Manage GCP Cloud Run IAM Permissions

The gcp:cloudrun/iamBinding:IamBinding resource, part of the Pulumi GCP provider, manages IAM role bindings for Cloud Run services by granting a specific role to a list of members. This guide focuses on two capabilities: granting roles to multiple members and adding individual members non-authoritatively.

IamBinding is authoritative for a given role, meaning it replaces all members for that role while preserving other roles on the service. It references existing Cloud Run services and requires project and location configuration. The examples are intentionally small. Combine them with your own service definitions and organizational identity management.

Grant a role to multiple members

Teams controlling access to Cloud Run services use IamBinding to grant a specific role to a list of members, replacing any previous members for that role.

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

const binding = new gcp.cloudrun.IamBinding("binding", {
    location: _default.location,
    project: _default.project,
    service: _default.name,
    role: "roles/viewer",
    members: ["user:jane@example.com"],
});
import pulumi
import pulumi_gcp as gcp

binding = gcp.cloudrun.IamBinding("binding",
    location=default["location"],
    project=default["project"],
    service=default["name"],
    role="roles/viewer",
    members=["user:jane@example.com"])
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := cloudrun.NewIamBinding(ctx, "binding", &cloudrun.IamBindingArgs{
			Location: pulumi.Any(_default.Location),
			Project:  pulumi.Any(_default.Project),
			Service:  pulumi.Any(_default.Name),
			Role:     pulumi.String("roles/viewer"),
			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.CloudRun.IamBinding("binding", new()
    {
        Location = @default.Location,
        Project = @default.Project,
        Service = @default.Name,
        Role = "roles/viewer",
        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.cloudrun.IamBinding;
import com.pulumi.gcp.cloudrun.IamBindingArgs;
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 IamBinding("binding", IamBindingArgs.builder()
            .location(default_.location())
            .project(default_.project())
            .service(default_.name())
            .role("roles/viewer")
            .members("user:jane@example.com")
            .build());

    }
}
resources:
  binding:
    type: gcp:cloudrun:IamBinding
    properties:
      location: ${default.location}
      project: ${default.project}
      service: ${default.name}
      role: roles/viewer
      members:
        - user:jane@example.com

The role property specifies which IAM role to grant (e.g., “roles/viewer” for read-only access). The members array lists identities in specific formats: “user:email@example.com” for individual users, “serviceAccount:email@project.iam.gserviceaccount.com” for service accounts, or “allUsers” for public access. The service property identifies which Cloud Run service to configure, and location specifies the region. This binding is authoritative for the viewer role, meaning it replaces any existing viewer role members while leaving other roles unchanged.

Add a single member to a role

When you need to grant access to one additional user without replacing existing members, use IamMember to add a single identity non-authoritatively.

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

const member = new gcp.cloudrun.IamMember("member", {
    location: _default.location,
    project: _default.project,
    service: _default.name,
    role: "roles/viewer",
    member: "user:jane@example.com",
});
import pulumi
import pulumi_gcp as gcp

member = gcp.cloudrun.IamMember("member",
    location=default["location"],
    project=default["project"],
    service=default["name"],
    role="roles/viewer",
    member="user:jane@example.com")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := cloudrun.NewIamMember(ctx, "member", &cloudrun.IamMemberArgs{
			Location: pulumi.Any(_default.Location),
			Project:  pulumi.Any(_default.Project),
			Service:  pulumi.Any(_default.Name),
			Role:     pulumi.String("roles/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.CloudRun.IamMember("member", new()
    {
        Location = @default.Location,
        Project = @default.Project,
        Service = @default.Name,
        Role = "roles/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.cloudrun.IamMember;
import com.pulumi.gcp.cloudrun.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 member = new IamMember("member", IamMemberArgs.builder()
            .location(default_.location())
            .project(default_.project())
            .service(default_.name())
            .role("roles/viewer")
            .member("user:jane@example.com")
            .build());

    }
}
resources:
  member:
    type: gcp:cloudrun:IamMember
    properties:
      location: ${default.location}
      project: ${default.project}
      service: ${default.name}
      role: roles/viewer
      member: user:jane@example.com

The member property (singular) specifies one identity to add to the role. Unlike IamBinding, IamMember preserves existing members for the role and only adds the new identity. This is useful when multiple teams manage access independently or when you want to avoid accidentally removing existing members. The same member identity formats apply: user accounts, service accounts, groups, or special identifiers like “allAuthenticatedUsers”.

Beyond these examples

These snippets focus on specific IAM binding features: role-based access control and member identity formats. They’re intentionally minimal rather than full access management solutions.

The examples reference pre-existing infrastructure such as Cloud Run services and GCP project and location configuration. They focus on configuring IAM bindings rather than provisioning the services themselves.

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

  • Conditional IAM bindings (condition property)
  • Custom role definitions
  • IamPolicy for full policy replacement
  • Service account creation and management

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 Cloud Run IamBinding resource reference for all available configuration options.

Let's manage GCP Cloud Run IAM Permissions

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
Which IAM resource should I use for managing Cloud Run permissions?
Choose based on your needs: gcp.cloudrun.IamPolicy for full policy control (replaces entire policy), gcp.cloudrun.IamBinding for managing all members of a specific role (authoritative for that role), or gcp.cloudrun.IamMember for adding individual members without affecting others (non-authoritative).
Can I use IamPolicy with IamBinding or IamMember?
No, gcp.cloudrun.IamPolicy cannot be used together with gcp.cloudrun.IamBinding or gcp.cloudrun.IamMember because they will conflict over policy management.
Can I use IamBinding and IamMember together?
Yes, but only if they manage different roles. Using gcp.cloudrun.IamBinding and gcp.cloudrun.IamMember for the same role will cause conflicts.
Configuration & Identity Management
What member identity formats can I use?

You can use multiple formats in the members property:

  • Special identifiers: allUsers, allAuthenticatedUsers
  • Individual accounts: user:{email}, serviceAccount:{email}
  • Groups and domains: group:{email}, domain:{domain}
  • Project roles: projectOwner:{projectid}, projectEditor:{projectid}, projectViewer:{projectid}
  • Federated identities: Workload/workforce identity pools (see Principal identifiers documentation)
How do I specify a custom role?
Custom roles must use the format [projects|organizations]/{parent-name}/roles/{role-name} in the role property (e.g., projects/my-project/roles/my-custom-role).
Immutability & Lifecycle
What properties can't be changed after creation?
The following properties are immutable: location, project, role, service, and condition. You must recreate the resource to change any of these.

Using a different cloud?

Explore iam guides for other cloud providers: