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 FREEFrequently Asked Questions
Resource Selection & Conflicts
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.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
allUsers, allAuthenticatedUsers, user:{email}, serviceAccount:{email}, group:{email}, domain:{domain}, projectOwner:projectid, projectEditor:projectid, projectViewer:projectid, or federated identities like principal://iam.googleapis.com/....[projects|organizations]/{parent-name}/roles/{role-name}. When importing, use the full name like projects/my-project/roles/my-custom-role.asia, europe, and us.Immutability & Lifecycle
member, role, repository, location, project) are immutable and require resource replacement if changed.