Manage GCP BigQuery Analytics Hub Data Exchange IAM Policies

The gcp:bigqueryanalyticshub/dataExchangeIamPolicy:DataExchangeIamPolicy resource, part of the Pulumi GCP provider, manages IAM permissions for BigQuery Analytics Hub data exchanges at three levels: entire policy replacement, role-level binding, or individual member grants. This guide focuses on three capabilities: authoritative policy replacement (DataExchangeIamPolicy), role-level member binding (DataExchangeIamBinding), and incremental member grants (DataExchangeIamMember).

These resources reference an existing data exchange and have important compatibility constraints. DataExchangeIamPolicy cannot be used with DataExchangeIamBinding or DataExchangeIamMember, as they will conflict over policy state. DataExchangeIamBinding and DataExchangeIamMember can coexist only if they manage different roles. The examples are intentionally small. Choose the resource that matches your access control needs.

Replace the entire IAM policy for a data exchange

When you need complete control over who can access a data exchange, you can set the entire IAM policy at once.

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.bigqueryanalyticshub.DataExchangeIamPolicy("policy", {
    project: dataExchange.project,
    location: dataExchange.location,
    dataExchangeId: dataExchange.dataExchangeId,
    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.bigqueryanalyticshub.DataExchangeIamPolicy("policy",
    project=data_exchange["project"],
    location=data_exchange["location"],
    data_exchange_id=data_exchange["dataExchangeId"],
    policy_data=admin.policy_data)
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/bigqueryanalyticshub"
	"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 = bigqueryanalyticshub.NewDataExchangeIamPolicy(ctx, "policy", &bigqueryanalyticshub.DataExchangeIamPolicyArgs{
			Project:        pulumi.Any(dataExchange.Project),
			Location:       pulumi.Any(dataExchange.Location),
			DataExchangeId: pulumi.Any(dataExchange.DataExchangeId),
			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.BigQueryAnalyticsHub.DataExchangeIamPolicy("policy", new()
    {
        Project = dataExchange.Project,
        Location = dataExchange.Location,
        DataExchangeId = dataExchange.DataExchangeId,
        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.bigqueryanalyticshub.DataExchangeIamPolicy;
import com.pulumi.gcp.bigqueryanalyticshub.DataExchangeIamPolicyArgs;
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 DataExchangeIamPolicy("policy", DataExchangeIamPolicyArgs.builder()
            .project(dataExchange.project())
            .location(dataExchange.location())
            .dataExchangeId(dataExchange.dataExchangeId())
            .policyData(admin.policyData())
            .build());

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

The DataExchangeIamPolicy resource is authoritative: it replaces all existing IAM bindings on the data exchange. The policyData property accepts output from the getIAMPolicy data source, which defines roles and members. Any permissions not included in policyData are removed when the policy is applied.

Grant a role to multiple members at once

Teams often need to grant the same role to several users or service accounts while preserving other role assignments.

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

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

binding = gcp.bigqueryanalyticshub.DataExchangeIamBinding("binding",
    project=data_exchange["project"],
    location=data_exchange["location"],
    data_exchange_id=data_exchange["dataExchangeId"],
    role="roles/viewer",
    members=["user:jane@example.com"])
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := bigqueryanalyticshub.NewDataExchangeIamBinding(ctx, "binding", &bigqueryanalyticshub.DataExchangeIamBindingArgs{
			Project:        pulumi.Any(dataExchange.Project),
			Location:       pulumi.Any(dataExchange.Location),
			DataExchangeId: pulumi.Any(dataExchange.DataExchangeId),
			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.BigQueryAnalyticsHub.DataExchangeIamBinding("binding", new()
    {
        Project = dataExchange.Project,
        Location = dataExchange.Location,
        DataExchangeId = dataExchange.DataExchangeId,
        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.bigqueryanalyticshub.DataExchangeIamBinding;
import com.pulumi.gcp.bigqueryanalyticshub.DataExchangeIamBindingArgs;
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 DataExchangeIamBinding("binding", DataExchangeIamBindingArgs.builder()
            .project(dataExchange.project())
            .location(dataExchange.location())
            .dataExchangeId(dataExchange.dataExchangeId())
            .role("roles/viewer")
            .members("user:jane@example.com")
            .build());

    }
}
resources:
  binding:
    type: gcp:bigqueryanalyticshub:DataExchangeIamBinding
    properties:
      project: ${dataExchange.project}
      location: ${dataExchange.location}
      dataExchangeId: ${dataExchange.dataExchangeId}
      role: roles/viewer
      members:
        - user:jane@example.com

The DataExchangeIamBinding resource is authoritative for a single role. The members property lists all identities that should have the specified role. Other roles on the data exchange remain unchanged, but this resource replaces any existing members for the role you specify.

Add a single member to a role incrementally

When you need to grant access to one user without affecting other members or roles, a non-authoritative member binding lets you add permissions incrementally.

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

const member = new gcp.bigqueryanalyticshub.DataExchangeIamMember("member", {
    project: dataExchange.project,
    location: dataExchange.location,
    dataExchangeId: dataExchange.dataExchangeId,
    role: "roles/viewer",
    member: "user:jane@example.com",
});
import pulumi
import pulumi_gcp as gcp

member = gcp.bigqueryanalyticshub.DataExchangeIamMember("member",
    project=data_exchange["project"],
    location=data_exchange["location"],
    data_exchange_id=data_exchange["dataExchangeId"],
    role="roles/viewer",
    member="user:jane@example.com")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := bigqueryanalyticshub.NewDataExchangeIamMember(ctx, "member", &bigqueryanalyticshub.DataExchangeIamMemberArgs{
			Project:        pulumi.Any(dataExchange.Project),
			Location:       pulumi.Any(dataExchange.Location),
			DataExchangeId: pulumi.Any(dataExchange.DataExchangeId),
			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.BigQueryAnalyticsHub.DataExchangeIamMember("member", new()
    {
        Project = dataExchange.Project,
        Location = dataExchange.Location,
        DataExchangeId = dataExchange.DataExchangeId,
        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.bigqueryanalyticshub.DataExchangeIamMember;
import com.pulumi.gcp.bigqueryanalyticshub.DataExchangeIamMemberArgs;
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 DataExchangeIamMember("member", DataExchangeIamMemberArgs.builder()
            .project(dataExchange.project())
            .location(dataExchange.location())
            .dataExchangeId(dataExchange.dataExchangeId())
            .role("roles/viewer")
            .member("user:jane@example.com")
            .build());

    }
}
resources:
  member:
    type: gcp:bigqueryanalyticshub:DataExchangeIamMember
    properties:
      project: ${dataExchange.project}
      location: ${dataExchange.location}
      dataExchangeId: ${dataExchange.dataExchangeId}
      role: roles/viewer
      member: user:jane@example.com

The DataExchangeIamMember resource is non-authoritative: it adds one member to one role without modifying other members for that role. This is the most flexible option for incremental access grants, as it preserves all existing permissions while adding new ones.

Beyond these examples

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

The examples reference pre-existing infrastructure such as BigQuery Analytics Hub data exchanges (dataExchangeId), and GCP projects and locations. They focus on IAM binding configuration rather than provisioning the data exchange itself.

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

  • Conditional IAM bindings (conditions)
  • Custom role definitions
  • Service account impersonation
  • Domain-restricted sharing

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

Let's manage GCP BigQuery Analytics Hub Data Exchange IAM Policies

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
Can I use DataExchangeIamPolicy with DataExchangeIamBinding or DataExchangeIamMember?
No, DataExchangeIamPolicy cannot be used with DataExchangeIamBinding or DataExchangeIamMember because they will conflict over policy management. Choose one approach: use IamPolicy alone for full authoritative control, or use IamBinding/IamMember together.
Can I use DataExchangeIamBinding and DataExchangeIamMember together?
Yes, but only if they don’t grant privileges to the same role. Each role must be managed by only one resource type to avoid conflicts.
Which IAM resource should I use for managing DataExchange permissions?

Choose based on your needs:

  • DataExchangeIamPolicy - Authoritative control over the entire policy (replaces any existing policy)
  • DataExchangeIamBinding - Authoritative control per role (preserves other roles in the policy)
  • DataExchangeIamMember - Non-authoritative additions (preserves other members for the role)
Configuration & Setup
How do I create a DataExchangeIamPolicy resource?
Use the gcp.organizations.getIAMPolicy data source to generate policyData with your desired bindings, then pass it to the DataExchangeIamPolicy resource’s policyData property.
Properties & Immutability
What properties can't be changed after creating a DataExchangeIamPolicy?
The dataExchangeId, location, and project properties are immutable. The location and project can be inferred from the parent resource identifier or provider configuration if not explicitly specified.

Using a different cloud?

Explore security guides for other cloud providers: