Manage GCP Artifact Registry Repository IAM Access

The gcp:artifactregistry/repositoryIamMember:RepositoryIamMember resource, part of the Pulumi GCP provider, grants IAM permissions to Artifact Registry repositories by adding individual members to roles. This guide focuses on three approaches: adding single members to roles, binding multiple members to a role, and replacing entire IAM policies.

Three related resources manage repository access with different behaviors. RepositoryIamMember adds one member without affecting others (non-authoritative). RepositoryIamBinding manages all members for a role (authoritative for that role). RepositoryIamPolicy replaces the entire policy (fully authoritative). The examples are intentionally small. Choose the resource that matches your access control model.

Grant a single user read access to a repository

When you need to give one developer or service account access without changing existing permissions, use RepositoryIamMember.

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

const member = new gcp.artifactregistry.RepositoryIamMember("member", {
    project: my_repo.project,
    location: my_repo.location,
    repository: my_repo.name,
    role: "roles/artifactregistry.reader",
    member: "user:jane@example.com",
});
import pulumi
import pulumi_gcp as gcp

member = gcp.artifactregistry.RepositoryIamMember("member",
    project=my_repo["project"],
    location=my_repo["location"],
    repository=my_repo["name"],
    role="roles/artifactregistry.reader",
    member="user:jane@example.com")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := artifactregistry.NewRepositoryIamMember(ctx, "member", &artifactregistry.RepositoryIamMemberArgs{
			Project:    pulumi.Any(my_repo.Project),
			Location:   pulumi.Any(my_repo.Location),
			Repository: pulumi.Any(my_repo.Name),
			Role:       pulumi.String("roles/artifactregistry.reader"),
			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.ArtifactRegistry.RepositoryIamMember("member", new()
    {
        Project = my_repo.Project,
        Location = my_repo.Location,
        Repository = my_repo.Name,
        Role = "roles/artifactregistry.reader",
        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.artifactregistry.RepositoryIamMember;
import com.pulumi.gcp.artifactregistry.RepositoryIamMemberArgs;
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 RepositoryIamMember("member", RepositoryIamMemberArgs.builder()
            .project(my_repo.project())
            .location(my_repo.location())
            .repository(my_repo.name())
            .role("roles/artifactregistry.reader")
            .member("user:jane@example.com")
            .build());

    }
}
resources:
  member:
    type: gcp:artifactregistry:RepositoryIamMember
    properties:
      project: ${["my-repo"].project}
      location: ${["my-repo"].location}
      repository: ${["my-repo"].name}
      role: roles/artifactregistry.reader
      member: user:jane@example.com

The member property identifies who receives access using formats like “user:jane@example.com” or “serviceAccount:app@project.iam.gserviceaccount.com”. The role property specifies what they can do; “roles/artifactregistry.reader” allows pulling images and artifacts. This resource adds the member without removing others who already have the same role.

Grant a role to multiple members at once

When several identities need identical access, RepositoryIamBinding assigns them together.

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

const binding = new gcp.artifactregistry.RepositoryIamBinding("binding", {
    project: my_repo.project,
    location: my_repo.location,
    repository: my_repo.name,
    role: "roles/artifactregistry.reader",
    members: ["user:jane@example.com"],
});
import pulumi
import pulumi_gcp as gcp

binding = gcp.artifactregistry.RepositoryIamBinding("binding",
    project=my_repo["project"],
    location=my_repo["location"],
    repository=my_repo["name"],
    role="roles/artifactregistry.reader",
    members=["user:jane@example.com"])
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := artifactregistry.NewRepositoryIamBinding(ctx, "binding", &artifactregistry.RepositoryIamBindingArgs{
			Project:    pulumi.Any(my_repo.Project),
			Location:   pulumi.Any(my_repo.Location),
			Repository: pulumi.Any(my_repo.Name),
			Role:       pulumi.String("roles/artifactregistry.reader"),
			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.ArtifactRegistry.RepositoryIamBinding("binding", new()
    {
        Project = my_repo.Project,
        Location = my_repo.Location,
        Repository = my_repo.Name,
        Role = "roles/artifactregistry.reader",
        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.artifactregistry.RepositoryIamBinding;
import com.pulumi.gcp.artifactregistry.RepositoryIamBindingArgs;
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 RepositoryIamBinding("binding", RepositoryIamBindingArgs.builder()
            .project(my_repo.project())
            .location(my_repo.location())
            .repository(my_repo.name())
            .role("roles/artifactregistry.reader")
            .members("user:jane@example.com")
            .build());

    }
}
resources:
  binding:
    type: gcp:artifactregistry:RepositoryIamBinding
    properties:
      project: ${["my-repo"].project}
      location: ${["my-repo"].location}
      repository: ${["my-repo"].name}
      role: roles/artifactregistry.reader
      members:
        - user:jane@example.com

The members property takes a list of identities that all receive the specified role. RepositoryIamBinding is authoritative for this role: it replaces any existing members for “roles/artifactregistry.reader” but leaves other roles untouched. Use this when you want to define exactly who has a particular role.

Replace the entire IAM policy with a new definition

Organizations managing access through centralized policy documents can set the complete policy in one operation.

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

const admin = gcp.organizations.getIAMPolicy({
    bindings: [{
        role: "roles/artifactregistry.reader",
        members: ["user:jane@example.com"],
    }],
});
const policy = new gcp.artifactregistry.RepositoryIamPolicy("policy", {
    project: my_repo.project,
    location: my_repo.location,
    repository: my_repo.name,
    policyData: admin.then(admin => admin.policyData),
});
import pulumi
import pulumi_gcp as gcp

admin = gcp.organizations.get_iam_policy(bindings=[{
    "role": "roles/artifactregistry.reader",
    "members": ["user:jane@example.com"],
}])
policy = gcp.artifactregistry.RepositoryIamPolicy("policy",
    project=my_repo["project"],
    location=my_repo["location"],
    repository=my_repo["name"],
    policy_data=admin.policy_data)
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		admin, err := organizations.LookupIAMPolicy(ctx, &organizations.LookupIAMPolicyArgs{
			Bindings: []organizations.GetIAMPolicyBinding{
				{
					Role: "roles/artifactregistry.reader",
					Members: []string{
						"user:jane@example.com",
					},
				},
			},
		}, nil)
		if err != nil {
			return err
		}
		_, err = artifactregistry.NewRepositoryIamPolicy(ctx, "policy", &artifactregistry.RepositoryIamPolicyArgs{
			Project:    pulumi.Any(my_repo.Project),
			Location:   pulumi.Any(my_repo.Location),
			Repository: pulumi.Any(my_repo.Name),
			PolicyData: pulumi.String(admin.PolicyData),
		})
		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 admin = Gcp.Organizations.GetIAMPolicy.Invoke(new()
    {
        Bindings = new[]
        {
            new Gcp.Organizations.Inputs.GetIAMPolicyBindingInputArgs
            {
                Role = "roles/artifactregistry.reader",
                Members = new[]
                {
                    "user:jane@example.com",
                },
            },
        },
    });

    var policy = new Gcp.ArtifactRegistry.RepositoryIamPolicy("policy", new()
    {
        Project = my_repo.Project,
        Location = my_repo.Location,
        Repository = my_repo.Name,
        PolicyData = admin.Apply(getIAMPolicyResult => getIAMPolicyResult.PolicyData),
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.organizations.OrganizationsFunctions;
import com.pulumi.gcp.organizations.inputs.GetIAMPolicyArgs;
import com.pulumi.gcp.artifactregistry.RepositoryIamPolicy;
import com.pulumi.gcp.artifactregistry.RepositoryIamPolicyArgs;
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) {
        final var admin = OrganizationsFunctions.getIAMPolicy(GetIAMPolicyArgs.builder()
            .bindings(GetIAMPolicyBindingArgs.builder()
                .role("roles/artifactregistry.reader")
                .members("user:jane@example.com")
                .build())
            .build());

        var policy = new RepositoryIamPolicy("policy", RepositoryIamPolicyArgs.builder()
            .project(my_repo.project())
            .location(my_repo.location())
            .repository(my_repo.name())
            .policyData(admin.policyData())
            .build());

    }
}
resources:
  policy:
    type: gcp:artifactregistry:RepositoryIamPolicy
    properties:
      project: ${["my-repo"].project}
      location: ${["my-repo"].location}
      repository: ${["my-repo"].name}
      policyData: ${admin.policyData}
variables:
  admin:
    fn::invoke:
      function: gcp:organizations:getIAMPolicy
      arguments:
        bindings:
          - role: roles/artifactregistry.reader
            members:
              - user:jane@example.com

RepositoryIamPolicy takes a policyData document from getIAMPolicy and replaces the repository’s entire IAM configuration. This is authoritative: it removes any bindings not in the policy document. You cannot use RepositoryIamPolicy alongside RepositoryIamBinding or RepositoryIamMember; they will conflict over policy ownership.

Beyond these examples

These snippets focus on specific IAM management approaches: incremental member grants, role-based binding, and full policy replacement. They’re intentionally minimal rather than complete access control configurations.

The examples reference pre-existing infrastructure such as Artifact Registry repositories (my_repo references). They focus on granting access rather than creating repositories or defining custom roles.

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

  • Conditional IAM bindings (condition property)
  • Custom role definitions
  • Federated identity principals
  • Policy retrieval via data sources

These omissions are intentional: the goal is to illustrate how each IAM resource modifies access, not provide drop-in security modules. See the Artifact Registry RepositoryIamMember resource reference for all available configuration options.

Let's manage GCP Artifact Registry Repository 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 & Conflicts
What's the difference between RepositoryIamPolicy, RepositoryIamBinding, and RepositoryIamMember?
RepositoryIamPolicy is authoritative and replaces the entire IAM policy. RepositoryIamBinding is authoritative for a specific role, preserving other roles. RepositoryIamMember is non-authoritative and adds a single member to a role without affecting other members.
Can I use these IAM resources together?
RepositoryIamPolicy cannot be used with RepositoryIamBinding or RepositoryIamMember as they will conflict. However, RepositoryIamBinding and RepositoryIamMember can be used together only if they manage different roles.
Configuration & Identity Formats
What member identity formats are supported?
You can use allUsers, allAuthenticatedUsers, user:{email}, serviceAccount:{email}, group:{email}, domain:{domain}, projectOwner:projectid, projectEditor:projectid, projectViewer:projectid, or federated identities like principal://iam.googleapis.com/....
How do I specify custom roles?
Custom roles must use the format [projects|organizations]/{parent-name}/roles/{role-name}. When importing, use the full name like projects/my-project/roles/my-custom-role.
What location values can I use for multi-region repositories?
In addition to specific regions, you can use multi-region values: asia, europe, and us.
Immutability & Lifecycle
Can I change the member, role, or repository after creation?
No, all properties (member, role, repository, location, project) are immutable and require resource replacement if changed.

Using a different cloud?

Explore security guides for other cloud providers: