Manage GCP Dataplex AspectType IAM Access

The gcp:dataplex/aspectTypeIamMember:AspectTypeIamMember resource, part of the Pulumi GCP provider, manages IAM access for Dataplex AspectType resources. This resource is one of three related resources that control access: AspectTypeIamMember grants roles to individual identities non-authoritatively, AspectTypeIamBinding manages complete member lists for a role authoritatively, and AspectTypeIamPolicy replaces the entire IAM policy. This guide focuses on three capabilities: non-authoritative single-member grants, authoritative role bindings, and full policy replacement.

These resources reference existing AspectType resources and require appropriate IAM permissions. The examples are intentionally small. Combine them with your own AspectType definitions and organizational access policies.

Grant a role to a single member non-authoritatively

When adding access for individual users or service accounts, non-authoritative member grants let you add one identity at a time without affecting other role assignments.

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

const member = new gcp.dataplex.AspectTypeIamMember("member", {
    project: testAspectTypeBasic.project,
    location: testAspectTypeBasic.location,
    aspectTypeId: testAspectTypeBasic.aspectTypeId,
    role: "roles/viewer",
    member: "user:jane@example.com",
});
import pulumi
import pulumi_gcp as gcp

member = gcp.dataplex.AspectTypeIamMember("member",
    project=test_aspect_type_basic["project"],
    location=test_aspect_type_basic["location"],
    aspect_type_id=test_aspect_type_basic["aspectTypeId"],
    role="roles/viewer",
    member="user:jane@example.com")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := dataplex.NewAspectTypeIamMember(ctx, "member", &dataplex.AspectTypeIamMemberArgs{
			Project:      pulumi.Any(testAspectTypeBasic.Project),
			Location:     pulumi.Any(testAspectTypeBasic.Location),
			AspectTypeId: pulumi.Any(testAspectTypeBasic.AspectTypeId),
			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.DataPlex.AspectTypeIamMember("member", new()
    {
        Project = testAspectTypeBasic.Project,
        Location = testAspectTypeBasic.Location,
        AspectTypeId = testAspectTypeBasic.AspectTypeId,
        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.dataplex.AspectTypeIamMember;
import com.pulumi.gcp.dataplex.AspectTypeIamMemberArgs;
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 AspectTypeIamMember("member", AspectTypeIamMemberArgs.builder()
            .project(testAspectTypeBasic.project())
            .location(testAspectTypeBasic.location())
            .aspectTypeId(testAspectTypeBasic.aspectTypeId())
            .role("roles/viewer")
            .member("user:jane@example.com")
            .build());

    }
}
resources:
  member:
    type: gcp:dataplex:AspectTypeIamMember
    properties:
      project: ${testAspectTypeBasic.project}
      location: ${testAspectTypeBasic.location}
      aspectTypeId: ${testAspectTypeBasic.aspectTypeId}
      role: roles/viewer
      member: user:jane@example.com

The AspectTypeIamMember resource adds one member to a role without modifying other members. The member property accepts various identity formats: user emails, service accounts, groups, domains, or federated identities. The aspectTypeId, location, and project properties identify which AspectType to modify. This approach is safe for incremental access grants because it preserves existing role assignments.

Grant a role to multiple members authoritatively

When managing a complete list of identities for a specific role, binding resources provide authoritative control over that role’s membership.

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

const binding = new gcp.dataplex.AspectTypeIamBinding("binding", {
    project: testAspectTypeBasic.project,
    location: testAspectTypeBasic.location,
    aspectTypeId: testAspectTypeBasic.aspectTypeId,
    role: "roles/viewer",
    members: ["user:jane@example.com"],
});
import pulumi
import pulumi_gcp as gcp

binding = gcp.dataplex.AspectTypeIamBinding("binding",
    project=test_aspect_type_basic["project"],
    location=test_aspect_type_basic["location"],
    aspect_type_id=test_aspect_type_basic["aspectTypeId"],
    role="roles/viewer",
    members=["user:jane@example.com"])
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := dataplex.NewAspectTypeIamBinding(ctx, "binding", &dataplex.AspectTypeIamBindingArgs{
			Project:      pulumi.Any(testAspectTypeBasic.Project),
			Location:     pulumi.Any(testAspectTypeBasic.Location),
			AspectTypeId: pulumi.Any(testAspectTypeBasic.AspectTypeId),
			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.DataPlex.AspectTypeIamBinding("binding", new()
    {
        Project = testAspectTypeBasic.Project,
        Location = testAspectTypeBasic.Location,
        AspectTypeId = testAspectTypeBasic.AspectTypeId,
        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.dataplex.AspectTypeIamBinding;
import com.pulumi.gcp.dataplex.AspectTypeIamBindingArgs;
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 AspectTypeIamBinding("binding", AspectTypeIamBindingArgs.builder()
            .project(testAspectTypeBasic.project())
            .location(testAspectTypeBasic.location())
            .aspectTypeId(testAspectTypeBasic.aspectTypeId())
            .role("roles/viewer")
            .members("user:jane@example.com")
            .build());

    }
}
resources:
  binding:
    type: gcp:dataplex:AspectTypeIamBinding
    properties:
      project: ${testAspectTypeBasic.project}
      location: ${testAspectTypeBasic.location}
      aspectTypeId: ${testAspectTypeBasic.aspectTypeId}
      role: roles/viewer
      members:
        - user:jane@example.com

The AspectTypeIamBinding resource defines the complete set of members for a role. The members array replaces all existing members for that role, but other roles on the AspectType remain unchanged. This approach works well when you need to manage a role’s membership as a single unit, such as defining all viewers or all editors.

Replace the entire IAM policy authoritatively

Organizations with centralized access control sometimes need to define the complete IAM policy, replacing any existing configuration.

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

const admin = gcp.organizations.getIAMPolicy({
    bindings: [{
        role: "roles/viewer",
        members: ["user:jane@example.com"],
    }],
});
const policy = new gcp.dataplex.AspectTypeIamPolicy("policy", {
    project: testAspectTypeBasic.project,
    location: testAspectTypeBasic.location,
    aspectTypeId: testAspectTypeBasic.aspectTypeId,
    policyData: admin.then(admin => admin.policyData),
});
import pulumi
import pulumi_gcp as gcp

admin = gcp.organizations.get_iam_policy(bindings=[{
    "role": "roles/viewer",
    "members": ["user:jane@example.com"],
}])
policy = gcp.dataplex.AspectTypeIamPolicy("policy",
    project=test_aspect_type_basic["project"],
    location=test_aspect_type_basic["location"],
    aspect_type_id=test_aspect_type_basic["aspectTypeId"],
    policy_data=admin.policy_data)
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/dataplex"
	"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/viewer",
					Members: []string{
						"user:jane@example.com",
					},
				},
			},
		}, nil)
		if err != nil {
			return err
		}
		_, err = dataplex.NewAspectTypeIamPolicy(ctx, "policy", &dataplex.AspectTypeIamPolicyArgs{
			Project:      pulumi.Any(testAspectTypeBasic.Project),
			Location:     pulumi.Any(testAspectTypeBasic.Location),
			AspectTypeId: pulumi.Any(testAspectTypeBasic.AspectTypeId),
			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/viewer",
                Members = new[]
                {
                    "user:jane@example.com",
                },
            },
        },
    });

    var policy = new Gcp.DataPlex.AspectTypeIamPolicy("policy", new()
    {
        Project = testAspectTypeBasic.Project,
        Location = testAspectTypeBasic.Location,
        AspectTypeId = testAspectTypeBasic.AspectTypeId,
        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.dataplex.AspectTypeIamPolicy;
import com.pulumi.gcp.dataplex.AspectTypeIamPolicyArgs;
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/viewer")
                .members("user:jane@example.com")
                .build())
            .build());

        var policy = new AspectTypeIamPolicy("policy", AspectTypeIamPolicyArgs.builder()
            .project(testAspectTypeBasic.project())
            .location(testAspectTypeBasic.location())
            .aspectTypeId(testAspectTypeBasic.aspectTypeId())
            .policyData(admin.policyData())
            .build());

    }
}
resources:
  policy:
    type: gcp:dataplex:AspectTypeIamPolicy
    properties:
      project: ${testAspectTypeBasic.project}
      location: ${testAspectTypeBasic.location}
      aspectTypeId: ${testAspectTypeBasic.aspectTypeId}
      policyData: ${admin.policyData}
variables:
  admin:
    fn::invoke:
      function: gcp:organizations:getIAMPolicy
      arguments:
        bindings:
          - role: roles/viewer
            members:
              - user:jane@example.com

The AspectTypeIamPolicy resource replaces the entire IAM policy for an AspectType. The policyData property accepts a complete policy definition, typically constructed using the getIAMPolicy data source. The bindings array defines all roles and their members. This resource cannot be used alongside AspectTypeIamBinding or AspectTypeIamMember because they would conflict over policy ownership.

Beyond these examples

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

The examples reference pre-existing infrastructure such as Dataplex AspectType resources and IAM policy definitions (for the policy resource). They focus on configuring access rather than provisioning the AspectTypes themselves.

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

  • Conditional IAM bindings (condition property)
  • Custom role definitions
  • Federated identity configuration
  • Cross-project or organization-level policies

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

Let's manage GCP Dataplex AspectType 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 AspectTypeIamPolicy, AspectTypeIamBinding, and AspectTypeIamMember?
AspectTypeIamPolicy is authoritative and replaces the entire IAM policy. AspectTypeIamBinding is authoritative for a specific role, preserving other roles. AspectTypeIamMember is non-authoritative and adds a single member to a role without affecting other members.
Can I use AspectTypeIamPolicy with AspectTypeIamBinding or AspectTypeIamMember?
No, AspectTypeIamPolicy cannot be used with AspectTypeIamBinding or AspectTypeIamMember because they will conflict over the policy configuration.
Can I use AspectTypeIamBinding and AspectTypeIamMember together?
Yes, but only if they don’t grant privileges to the same role. If they manage the same role, they will conflict.
IAM Configuration
How do I specify custom roles?
Custom roles must use the format [projects|organizations]/{parent-name}/roles/{role-name}, for example projects/my-project/roles/my-custom-role.
What member identity formats are supported?
Supported formats include allUsers, allAuthenticatedUsers, user:{email}, serviceAccount:{email}, group:{email}, domain:{domain}, projectOwner:{projectid}, projectEditor:{projectid}, projectViewer:{projectid}, and federated identities like principal://iam.googleapis.com/....
How do I grant a role to a single user?
Use AspectTypeIamMember with the role and member properties. For example, set role to roles/viewer and member to user:jane@example.com.
How do I grant a role to multiple members at once?
Use AspectTypeIamBinding with the role property and a members list containing all the identities you want to grant the role to.
Resource Management
What properties can I change after creating an AspectTypeIamMember?
None. All properties (aspectTypeId, location, member, project, and role) are immutable after creation.

Using a different cloud?

Explore security guides for other cloud providers: