Manage GCP BigQuery Dataset IAM Access

The gcp:bigquery/datasetIamMember:DatasetIamMember resource, part of the Pulumi GCP provider, grants IAM permissions on BigQuery datasets by adding individual members to roles without affecting other members or roles. This guide focuses on three capabilities: single-member role grants, time-limited access with IAM conditions, and role-level member management.

These resources reference existing BigQuery datasets and grant access to users, service accounts, or groups. The examples are intentionally small. Combine them with your own dataset and identity management.

Grant a single user access to a dataset

Most IAM configurations add individual users to specific roles, preserving all other permissions on the dataset.

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

const dataset = new gcp.bigquery.Dataset("dataset", {datasetId: "example_dataset"});
const editor = new gcp.bigquery.DatasetIamMember("editor", {
    datasetId: dataset.datasetId,
    role: "roles/bigquery.dataEditor",
    member: "user:jane@example.com",
});
import pulumi
import pulumi_gcp as gcp

dataset = gcp.bigquery.Dataset("dataset", dataset_id="example_dataset")
editor = gcp.bigquery.DatasetIamMember("editor",
    dataset_id=dataset.dataset_id,
    role="roles/bigquery.dataEditor",
    member="user:jane@example.com")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		dataset, err := bigquery.NewDataset(ctx, "dataset", &bigquery.DatasetArgs{
			DatasetId: pulumi.String("example_dataset"),
		})
		if err != nil {
			return err
		}
		_, err = bigquery.NewDatasetIamMember(ctx, "editor", &bigquery.DatasetIamMemberArgs{
			DatasetId: dataset.DatasetId,
			Role:      pulumi.String("roles/bigquery.dataEditor"),
			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 dataset = new Gcp.BigQuery.Dataset("dataset", new()
    {
        DatasetId = "example_dataset",
    });

    var editor = new Gcp.BigQuery.DatasetIamMember("editor", new()
    {
        DatasetId = dataset.DatasetId,
        Role = "roles/bigquery.dataEditor",
        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.bigquery.Dataset;
import com.pulumi.gcp.bigquery.DatasetArgs;
import com.pulumi.gcp.bigquery.DatasetIamMember;
import com.pulumi.gcp.bigquery.DatasetIamMemberArgs;
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 dataset = new Dataset("dataset", DatasetArgs.builder()
            .datasetId("example_dataset")
            .build());

        var editor = new DatasetIamMember("editor", DatasetIamMemberArgs.builder()
            .datasetId(dataset.datasetId())
            .role("roles/bigquery.dataEditor")
            .member("user:jane@example.com")
            .build());

    }
}
resources:
  editor:
    type: gcp:bigquery:DatasetIamMember
    properties:
      datasetId: ${dataset.datasetId}
      role: roles/bigquery.dataEditor
      member: user:jane@example.com
  dataset:
    type: gcp:bigquery:Dataset
    properties:
      datasetId: example_dataset

The member property identifies who receives access (user, service account, group, or special identifier). The role property specifies the permission level using the full role format like roles/bigquery.dataEditor. DatasetIamMember is non-authoritative: it adds this one member to this one role without removing other members or affecting other roles.

Add time-limited access with IAM conditions

Temporary access grants expire automatically at a specified time, eliminating manual cleanup for contractors or time-bound projects.

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

const dataset = new gcp.bigquery.Dataset("dataset", {datasetId: "example_dataset"});
const editor = new gcp.bigquery.DatasetIamMember("editor", {
    datasetId: dataset.datasetId,
    role: "roles/bigquery.dataEditor",
    member: "user:jane@example.com",
    condition: {
        title: "expires_after_2029_12_31",
        description: "Expiring at midnight of 2029-12-31",
        expression: "request.time < timestamp(\"2030-01-01T00:00:00Z\")",
    },
});
import pulumi
import pulumi_gcp as gcp

dataset = gcp.bigquery.Dataset("dataset", dataset_id="example_dataset")
editor = gcp.bigquery.DatasetIamMember("editor",
    dataset_id=dataset.dataset_id,
    role="roles/bigquery.dataEditor",
    member="user:jane@example.com",
    condition={
        "title": "expires_after_2029_12_31",
        "description": "Expiring at midnight of 2029-12-31",
        "expression": "request.time < timestamp(\"2030-01-01T00:00:00Z\")",
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		dataset, err := bigquery.NewDataset(ctx, "dataset", &bigquery.DatasetArgs{
			DatasetId: pulumi.String("example_dataset"),
		})
		if err != nil {
			return err
		}
		_, err = bigquery.NewDatasetIamMember(ctx, "editor", &bigquery.DatasetIamMemberArgs{
			DatasetId: dataset.DatasetId,
			Role:      pulumi.String("roles/bigquery.dataEditor"),
			Member:    pulumi.String("user:jane@example.com"),
			Condition: &bigquery.DatasetIamMemberConditionArgs{
				Title:       pulumi.String("expires_after_2029_12_31"),
				Description: pulumi.String("Expiring at midnight of 2029-12-31"),
				Expression:  pulumi.String("request.time < timestamp(\"2030-01-01T00:00:00Z\")"),
			},
		})
		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 dataset = new Gcp.BigQuery.Dataset("dataset", new()
    {
        DatasetId = "example_dataset",
    });

    var editor = new Gcp.BigQuery.DatasetIamMember("editor", new()
    {
        DatasetId = dataset.DatasetId,
        Role = "roles/bigquery.dataEditor",
        Member = "user:jane@example.com",
        Condition = new Gcp.BigQuery.Inputs.DatasetIamMemberConditionArgs
        {
            Title = "expires_after_2029_12_31",
            Description = "Expiring at midnight of 2029-12-31",
            Expression = "request.time < timestamp(\"2030-01-01T00:00:00Z\")",
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.bigquery.Dataset;
import com.pulumi.gcp.bigquery.DatasetArgs;
import com.pulumi.gcp.bigquery.DatasetIamMember;
import com.pulumi.gcp.bigquery.DatasetIamMemberArgs;
import com.pulumi.gcp.bigquery.inputs.DatasetIamMemberConditionArgs;
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 dataset = new Dataset("dataset", DatasetArgs.builder()
            .datasetId("example_dataset")
            .build());

        var editor = new DatasetIamMember("editor", DatasetIamMemberArgs.builder()
            .datasetId(dataset.datasetId())
            .role("roles/bigquery.dataEditor")
            .member("user:jane@example.com")
            .condition(DatasetIamMemberConditionArgs.builder()
                .title("expires_after_2029_12_31")
                .description("Expiring at midnight of 2029-12-31")
                .expression("request.time < timestamp(\"2030-01-01T00:00:00Z\")")
                .build())
            .build());

    }
}
resources:
  editor:
    type: gcp:bigquery:DatasetIamMember
    properties:
      datasetId: ${dataset.datasetId}
      role: roles/bigquery.dataEditor
      member: user:jane@example.com
      condition:
        title: expires_after_2029_12_31
        description: Expiring at midnight of 2029-12-31
        expression: request.time < timestamp("2030-01-01T00:00:00Z")
  dataset:
    type: gcp:bigquery:Dataset
    properties:
      datasetId: example_dataset

The condition block adds time-based restrictions to the role grant. The expression property uses CEL (Common Expression Language) to define when access is valid. Here, request.time < timestamp("2030-01-01T00:00:00Z") grants access until midnight on December 31, 2029. The title and description document the condition’s purpose.

Grant a role to multiple members at once

When multiple users need identical permissions, DatasetIamBinding manages the complete member list for a role as a single unit.

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

const dataset = new gcp.bigquery.Dataset("dataset", {datasetId: "example_dataset"});
const reader = new gcp.bigquery.DatasetIamBinding("reader", {
    datasetId: dataset.datasetId,
    role: "roles/bigquery.dataViewer",
    members: ["user:jane@example.com"],
});
import pulumi
import pulumi_gcp as gcp

dataset = gcp.bigquery.Dataset("dataset", dataset_id="example_dataset")
reader = gcp.bigquery.DatasetIamBinding("reader",
    dataset_id=dataset.dataset_id,
    role="roles/bigquery.dataViewer",
    members=["user:jane@example.com"])
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		dataset, err := bigquery.NewDataset(ctx, "dataset", &bigquery.DatasetArgs{
			DatasetId: pulumi.String("example_dataset"),
		})
		if err != nil {
			return err
		}
		_, err = bigquery.NewDatasetIamBinding(ctx, "reader", &bigquery.DatasetIamBindingArgs{
			DatasetId: dataset.DatasetId,
			Role:      pulumi.String("roles/bigquery.dataViewer"),
			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 dataset = new Gcp.BigQuery.Dataset("dataset", new()
    {
        DatasetId = "example_dataset",
    });

    var reader = new Gcp.BigQuery.DatasetIamBinding("reader", new()
    {
        DatasetId = dataset.DatasetId,
        Role = "roles/bigquery.dataViewer",
        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.bigquery.Dataset;
import com.pulumi.gcp.bigquery.DatasetArgs;
import com.pulumi.gcp.bigquery.DatasetIamBinding;
import com.pulumi.gcp.bigquery.DatasetIamBindingArgs;
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 dataset = new Dataset("dataset", DatasetArgs.builder()
            .datasetId("example_dataset")
            .build());

        var reader = new DatasetIamBinding("reader", DatasetIamBindingArgs.builder()
            .datasetId(dataset.datasetId())
            .role("roles/bigquery.dataViewer")
            .members("user:jane@example.com")
            .build());

    }
}
resources:
  reader:
    type: gcp:bigquery:DatasetIamBinding
    properties:
      datasetId: ${dataset.datasetId}
      role: roles/bigquery.dataViewer
      members:
        - user:jane@example.com
  dataset:
    type: gcp:bigquery:Dataset
    properties:
      datasetId: example_dataset

The members property lists all identities that should have this role. DatasetIamBinding is authoritative for the specified role: it replaces any existing members for roles/bigquery.dataViewer with this list. Other roles on the dataset remain unchanged. Use this when you want to manage all viewers together rather than adding them individually.

Beyond these examples

These snippets focus on specific IAM grant features: single-member grants (DatasetIamMember), role-level member lists (DatasetIamBinding), and time-based access conditions. They’re intentionally minimal rather than full access control policies.

The examples reference pre-existing infrastructure such as BigQuery datasets (gcp.bigquery.Dataset) and user accounts, service accounts, or groups to grant access to. They focus on granting permissions rather than provisioning datasets or managing identities.

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

  • Full policy replacement (DatasetIamPolicy)
  • Advanced access patterns (authorized views via DatasetAccess)
  • Custom role definitions
  • Audit logging configuration

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

Let's manage GCP BigQuery Dataset 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 Conflicts & Compatibility
Which BigQuery IAM resources conflict with each other?
DatasetIamPolicy cannot be used with DatasetIamBinding or DatasetIamMember (they’ll fight over the policy). DatasetIamBinding and DatasetIamMember can coexist only if they target different roles.
Can I use DatasetIamMember with DatasetAccess or the access field on Dataset?
No, these IAM resources cannot be used with gcp.bigquery.DatasetAccess or the access field on gcp.bigquery.Dataset. They will conflict over the policy configuration.
When should I use DatasetAccess instead of DatasetIamMember?
Use gcp.bigquery.DatasetAccess for advanced use cases like creating authorized views. IAM resources will remove authorized view permissions from the dataset.
IAM Roles & Permissions
Why can't I use OWNER, WRITER, or READER roles?
Legacy BigQuery roles are incompatible with IAM resources. Use the full role forms: roles/bigquery.dataOwner, roles/bigquery.dataEditor, and roles/bigquery.dataViewer.
What's the difference between DatasetIamPolicy, DatasetIamBinding, and DatasetIamMember?
DatasetIamPolicy is authoritative and replaces the entire policy. DatasetIamBinding is authoritative for a specific role but preserves other roles. DatasetIamMember is non-authoritative and adds a single member while preserving others.
What format do custom roles need to follow?
Custom roles must use the format [projects|organizations]/{parent-name}/roles/{role-name}.
Member Identity Formats
What member identity formats are supported?
Supported formats include user:{email}, serviceAccount:{email}, group:{email}, domain:{domain}, allUsers, allAuthenticatedUsers, projectOwners, projectReaders, projectWriters, and iamMember:{principal} for federated identities.
Configuration & Conditions
How do I set time-based access that expires?
Use the condition property with title, description, and expression. For example: expression: "request.time < timestamp(\"2030-01-01T00:00:00Z\")".
What properties can't be changed after creation?
All properties are immutable: datasetId, member, role, project, and condition. Changes require resource replacement.

Using a different cloud?

Explore security guides for other cloud providers: