Manage GCP Gemini Repository Group IAM Access

The gcp:gemini/repositoryGroupIamMember:RepositoryGroupIamMember resource, part of the Pulumi GCP provider, manages IAM access to Gemini repository groups by granting roles to individual members, multiple members, or replacing the entire policy. This guide focuses on three capabilities: individual member grants, role bindings for multiple users, and authoritative policy replacement.

IAM resources for repository groups come in three variants: IamMember (non-authoritative, adds one member), IamBinding (authoritative for a role, manages all members for that role), and IamPolicy (authoritative for the entire policy). All three reference existing repository groups within code repository indexes. The examples are intentionally small. Combine them with your own repository group infrastructure and access requirements.

Grant a single user access to a repository group

Most access grants start by adding individual users to repository groups without affecting existing members or roles.

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

const member = new gcp.gemini.RepositoryGroupIamMember("member", {
    project: example.project,
    location: example.location,
    codeRepositoryIndex: example.codeRepositoryIndex,
    repositoryGroupId: example.repositoryGroupId,
    role: "roles/cloudaicompanion.repositoryGroupsUser",
    member: "user:jane@example.com",
});
import pulumi
import pulumi_gcp as gcp

member = gcp.gemini.RepositoryGroupIamMember("member",
    project=example["project"],
    location=example["location"],
    code_repository_index=example["codeRepositoryIndex"],
    repository_group_id=example["repositoryGroupId"],
    role="roles/cloudaicompanion.repositoryGroupsUser",
    member="user:jane@example.com")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := gemini.NewRepositoryGroupIamMember(ctx, "member", &gemini.RepositoryGroupIamMemberArgs{
			Project:             pulumi.Any(example.Project),
			Location:            pulumi.Any(example.Location),
			CodeRepositoryIndex: pulumi.Any(example.CodeRepositoryIndex),
			RepositoryGroupId:   pulumi.Any(example.RepositoryGroupId),
			Role:                pulumi.String("roles/cloudaicompanion.repositoryGroupsUser"),
			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.Gemini.RepositoryGroupIamMember("member", new()
    {
        Project = example.Project,
        Location = example.Location,
        CodeRepositoryIndex = example.CodeRepositoryIndex,
        RepositoryGroupId = example.RepositoryGroupId,
        Role = "roles/cloudaicompanion.repositoryGroupsUser",
        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.gemini.RepositoryGroupIamMember;
import com.pulumi.gcp.gemini.RepositoryGroupIamMemberArgs;
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 RepositoryGroupIamMember("member", RepositoryGroupIamMemberArgs.builder()
            .project(example.project())
            .location(example.location())
            .codeRepositoryIndex(example.codeRepositoryIndex())
            .repositoryGroupId(example.repositoryGroupId())
            .role("roles/cloudaicompanion.repositoryGroupsUser")
            .member("user:jane@example.com")
            .build());

    }
}
resources:
  member:
    type: gcp:gemini:RepositoryGroupIamMember
    properties:
      project: ${example.project}
      location: ${example.location}
      codeRepositoryIndex: ${example.codeRepositoryIndex}
      repositoryGroupId: ${example.repositoryGroupId}
      role: roles/cloudaicompanion.repositoryGroupsUser
      member: user:jane@example.com

The member property specifies the identity to grant access, using formats like “user:jane@example.com” for Google accounts or “serviceAccount:…” for service accounts. The role property defines the permission level, here using the predefined repositoryGroupsUser role. The repositoryGroupId and codeRepositoryIndex properties identify which repository group receives the access grant. This resource is non-authoritative: it adds the member without removing other members for the same role.

Grant a role to multiple users at once

When onboarding teams or granting access to groups, binding a role to multiple members simplifies management.

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

const binding = new gcp.gemini.RepositoryGroupIamBinding("binding", {
    project: example.project,
    location: example.location,
    codeRepositoryIndex: example.codeRepositoryIndex,
    repositoryGroupId: example.repositoryGroupId,
    role: "roles/cloudaicompanion.repositoryGroupsUser",
    members: ["user:jane@example.com"],
});
import pulumi
import pulumi_gcp as gcp

binding = gcp.gemini.RepositoryGroupIamBinding("binding",
    project=example["project"],
    location=example["location"],
    code_repository_index=example["codeRepositoryIndex"],
    repository_group_id=example["repositoryGroupId"],
    role="roles/cloudaicompanion.repositoryGroupsUser",
    members=["user:jane@example.com"])
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := gemini.NewRepositoryGroupIamBinding(ctx, "binding", &gemini.RepositoryGroupIamBindingArgs{
			Project:             pulumi.Any(example.Project),
			Location:            pulumi.Any(example.Location),
			CodeRepositoryIndex: pulumi.Any(example.CodeRepositoryIndex),
			RepositoryGroupId:   pulumi.Any(example.RepositoryGroupId),
			Role:                pulumi.String("roles/cloudaicompanion.repositoryGroupsUser"),
			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.Gemini.RepositoryGroupIamBinding("binding", new()
    {
        Project = example.Project,
        Location = example.Location,
        CodeRepositoryIndex = example.CodeRepositoryIndex,
        RepositoryGroupId = example.RepositoryGroupId,
        Role = "roles/cloudaicompanion.repositoryGroupsUser",
        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.gemini.RepositoryGroupIamBinding;
import com.pulumi.gcp.gemini.RepositoryGroupIamBindingArgs;
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 RepositoryGroupIamBinding("binding", RepositoryGroupIamBindingArgs.builder()
            .project(example.project())
            .location(example.location())
            .codeRepositoryIndex(example.codeRepositoryIndex())
            .repositoryGroupId(example.repositoryGroupId())
            .role("roles/cloudaicompanion.repositoryGroupsUser")
            .members("user:jane@example.com")
            .build());

    }
}
resources:
  binding:
    type: gcp:gemini:RepositoryGroupIamBinding
    properties:
      project: ${example.project}
      location: ${example.location}
      codeRepositoryIndex: ${example.codeRepositoryIndex}
      repositoryGroupId: ${example.repositoryGroupId}
      role: roles/cloudaicompanion.repositoryGroupsUser
      members:
        - user:jane@example.com

The members property accepts an array of identities, allowing you to grant the same role to multiple users in one resource. This resource is authoritative for the specified role: it replaces all members for that role on the repository group. Other roles remain unchanged. Use IamBinding when you want to manage all members for a role together, rather than tracking individual IamMember resources.

Replace the entire IAM policy with a custom definition

Organizations with complex requirements sometimes need to define the complete IAM policy from scratch.

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

const admin = gcp.organizations.getIAMPolicy({
    bindings: [{
        role: "roles/cloudaicompanion.repositoryGroupsUser",
        members: ["user:jane@example.com"],
    }],
});
const policy = new gcp.gemini.RepositoryGroupIamPolicy("policy", {
    project: example.project,
    location: example.location,
    codeRepositoryIndex: example.codeRepositoryIndex,
    repositoryGroupId: example.repositoryGroupId,
    policyData: admin.then(admin => admin.policyData),
});
import pulumi
import pulumi_gcp as gcp

admin = gcp.organizations.get_iam_policy(bindings=[{
    "role": "roles/cloudaicompanion.repositoryGroupsUser",
    "members": ["user:jane@example.com"],
}])
policy = gcp.gemini.RepositoryGroupIamPolicy("policy",
    project=example["project"],
    location=example["location"],
    code_repository_index=example["codeRepositoryIndex"],
    repository_group_id=example["repositoryGroupId"],
    policy_data=admin.policy_data)
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/gemini"
	"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/cloudaicompanion.repositoryGroupsUser",
					Members: []string{
						"user:jane@example.com",
					},
				},
			},
		}, nil)
		if err != nil {
			return err
		}
		_, err = gemini.NewRepositoryGroupIamPolicy(ctx, "policy", &gemini.RepositoryGroupIamPolicyArgs{
			Project:             pulumi.Any(example.Project),
			Location:            pulumi.Any(example.Location),
			CodeRepositoryIndex: pulumi.Any(example.CodeRepositoryIndex),
			RepositoryGroupId:   pulumi.Any(example.RepositoryGroupId),
			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/cloudaicompanion.repositoryGroupsUser",
                Members = new[]
                {
                    "user:jane@example.com",
                },
            },
        },
    });

    var policy = new Gcp.Gemini.RepositoryGroupIamPolicy("policy", new()
    {
        Project = example.Project,
        Location = example.Location,
        CodeRepositoryIndex = example.CodeRepositoryIndex,
        RepositoryGroupId = example.RepositoryGroupId,
        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.gemini.RepositoryGroupIamPolicy;
import com.pulumi.gcp.gemini.RepositoryGroupIamPolicyArgs;
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/cloudaicompanion.repositoryGroupsUser")
                .members("user:jane@example.com")
                .build())
            .build());

        var policy = new RepositoryGroupIamPolicy("policy", RepositoryGroupIamPolicyArgs.builder()
            .project(example.project())
            .location(example.location())
            .codeRepositoryIndex(example.codeRepositoryIndex())
            .repositoryGroupId(example.repositoryGroupId())
            .policyData(admin.policyData())
            .build());

    }
}
resources:
  policy:
    type: gcp:gemini:RepositoryGroupIamPolicy
    properties:
      project: ${example.project}
      location: ${example.location}
      codeRepositoryIndex: ${example.codeRepositoryIndex}
      repositoryGroupId: ${example.repositoryGroupId}
      policyData: ${admin.policyData}
variables:
  admin:
    fn::invoke:
      function: gcp:organizations:getIAMPolicy
      arguments:
        bindings:
          - role: roles/cloudaicompanion.repositoryGroupsUser
            members:
              - user:jane@example.com

The policyData property accepts a complete IAM policy document, typically retrieved from getIAMPolicy. The bindings array within the policy defines all role-to-members mappings. This resource is fully authoritative: it replaces the entire IAM policy for the repository group. You cannot use IamPolicy alongside IamBinding or IamMember resources on the same repository group, as they will conflict over policy ownership.

Beyond these examples

These snippets focus on specific IAM management features: individual member grants, role bindings for multiple users, and authoritative policy replacement. They’re intentionally minimal rather than full access control configurations.

The examples reference pre-existing infrastructure such as Gemini code repository indexes and repository groups within those indexes. They focus on configuring IAM access rather than provisioning the repository infrastructure itself.

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

  • Conditional IAM bindings (condition property)
  • Custom role definitions
  • Service account and group member types
  • Federated identity principals

These omissions are intentional: the goal is to illustrate how each IAM resource type is wired, not provide drop-in access control modules. See the RepositoryGroupIamMember resource reference for all available configuration options.

Let's manage GCP Gemini Repository Group 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
Which IAM resource should I use for managing repository group permissions?

You have three options:

  1. RepositoryGroupIamPolicy - Authoritative. Replaces the entire IAM policy.
  2. RepositoryGroupIamBinding - Authoritative for a specific role. Preserves other roles in the policy.
  3. RepositoryGroupIamMember - Non-authoritative. Adds a single member to a role, preserving other members.
Can I use RepositoryGroupIamPolicy with RepositoryGroupIamBinding or RepositoryGroupIamMember?
No. RepositoryGroupIamPolicy cannot be used with RepositoryGroupIamBinding or RepositoryGroupIamMember because they will conflict over policy control. Use either Policy (authoritative) or Binding/Member (non-authoritative), never mix them.
Can I use RepositoryGroupIamBinding and RepositoryGroupIamMember together?
Yes, but only if they don’t grant privileges to the same role. If both resources target the same role, they will conflict.
Configuration & Identity Management
What member identity formats are supported?

The member property supports:

  • allUsers - Anyone on the internet
  • allAuthenticatedUsers - Anyone with a Google account
  • user:{emailid} - Specific Google account (e.g., user:alice@gmail.com)
  • serviceAccount:{emailid} - Service account (e.g., serviceAccount:my-app@appspot.gserviceaccount.com)
  • group:{emailid} - Google group (e.g., group:admins@example.com)
  • domain:{domain} - G Suite domain (e.g., domain:example.com)
  • projectOwner:projectid, projectEditor:projectid, projectViewer:projectid - Project-level roles
  • Federated identities (e.g., principal://iam.googleapis.com/locations/global/workforcePools/...)
What properties can't I change after creating the resource?
All properties are immutable: codeRepositoryIndex, location, member, project, repositoryGroupId, and role. To change any of these, you must recreate the resource.
Advanced Topics
How do I specify custom IAM roles?
Custom roles must use the format [projects|organizations]/{parent-name}/roles/{role-name}. For example, projects/my-project/roles/my-custom-role or organizations/my-org/roles/my-custom-role.
How do I import existing IAM resources?

Use space-delimited identifiers:

  • Member: pulumi import gcp:gemini/repositoryGroupIamMember:RepositoryGroupIamMember editor "projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index}}/repositoryGroups/{{repository_group_id}} roles/cloudaicompanion.repositoryGroupsUser user:jane@example.com"
  • Binding: pulumi import gcp:gemini/repositoryGroupIamMember:RepositoryGroupIamMember editor "projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index}}/repositoryGroups/{{repository_group_id}} roles/cloudaicompanion.repositoryGroupsUser"
  • Policy: pulumi import gcp:gemini/repositoryGroupIamMember:RepositoryGroupIamMember editor projects/{{project}}/locations/{{location}}/codeRepositoryIndexes/{{code_repository_index}}/repositoryGroups/{{repository_group_id}}

Using a different cloud?

Explore security guides for other cloud providers: