The gcp:bigquery/datasetIamPolicy:DatasetIamPolicy resource, part of the Pulumi GCP provider, manages IAM permissions for BigQuery datasets using standard IAM roles and bindings. This guide focuses on four capabilities: authoritative policy replacement (DatasetIamPolicy), single-role management (DatasetIamBinding), individual member grants (DatasetIamMember), and time-based conditional access.
These resources reference existing BigQuery datasets and convert BigQuery’s legacy permission system to standard IAM. They cannot be used with DatasetAccess resources or the access field on Dataset, as they will conflict. For authorized views, use DatasetAccess instead. The examples are intentionally small. Combine them with your own datasets and IAM principals.
Replace the entire IAM policy with DatasetIamPolicy
When you need complete control over dataset access, DatasetIamPolicy replaces the entire IAM policy in one operation. This is useful when migrating from legacy BigQuery permissions to standard IAM roles.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const owner = gcp.organizations.getIAMPolicy({
bindings: [{
role: "roles/bigquery.dataOwner",
members: ["user:jane@example.com"],
}],
});
const datasetDataset = new gcp.bigquery.Dataset("dataset", {datasetId: "example_dataset"});
const dataset = new gcp.bigquery.DatasetIamPolicy("dataset", {
datasetId: datasetDataset.datasetId,
policyData: owner.then(owner => owner.policyData),
});
import pulumi
import pulumi_gcp as gcp
owner = gcp.organizations.get_iam_policy(bindings=[{
"role": "roles/bigquery.dataOwner",
"members": ["user:jane@example.com"],
}])
dataset_dataset = gcp.bigquery.Dataset("dataset", dataset_id="example_dataset")
dataset = gcp.bigquery.DatasetIamPolicy("dataset",
dataset_id=dataset_dataset.dataset_id,
policy_data=owner.policy_data)
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/bigquery"
"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 {
owner, err := organizations.LookupIAMPolicy(ctx, &organizations.LookupIAMPolicyArgs{
Bindings: []organizations.GetIAMPolicyBinding{
{
Role: "roles/bigquery.dataOwner",
Members: []string{
"user:jane@example.com",
},
},
},
}, nil)
if err != nil {
return err
}
datasetDataset, err := bigquery.NewDataset(ctx, "dataset", &bigquery.DatasetArgs{
DatasetId: pulumi.String("example_dataset"),
})
if err != nil {
return err
}
_, err = bigquery.NewDatasetIamPolicy(ctx, "dataset", &bigquery.DatasetIamPolicyArgs{
DatasetId: datasetDataset.DatasetId,
PolicyData: pulumi.String(owner.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 owner = Gcp.Organizations.GetIAMPolicy.Invoke(new()
{
Bindings = new[]
{
new Gcp.Organizations.Inputs.GetIAMPolicyBindingInputArgs
{
Role = "roles/bigquery.dataOwner",
Members = new[]
{
"user:jane@example.com",
},
},
},
});
var datasetDataset = new Gcp.BigQuery.Dataset("dataset", new()
{
DatasetId = "example_dataset",
});
var dataset = new Gcp.BigQuery.DatasetIamPolicy("dataset", new()
{
DatasetId = datasetDataset.DatasetId,
PolicyData = owner.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.bigquery.Dataset;
import com.pulumi.gcp.bigquery.DatasetArgs;
import com.pulumi.gcp.bigquery.DatasetIamPolicy;
import com.pulumi.gcp.bigquery.DatasetIamPolicyArgs;
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 owner = OrganizationsFunctions.getIAMPolicy(GetIAMPolicyArgs.builder()
.bindings(GetIAMPolicyBindingArgs.builder()
.role("roles/bigquery.dataOwner")
.members("user:jane@example.com")
.build())
.build());
var datasetDataset = new Dataset("datasetDataset", DatasetArgs.builder()
.datasetId("example_dataset")
.build());
var dataset = new DatasetIamPolicy("dataset", DatasetIamPolicyArgs.builder()
.datasetId(datasetDataset.datasetId())
.policyData(owner.policyData())
.build());
}
}
resources:
dataset:
type: gcp:bigquery:DatasetIamPolicy
properties:
datasetId: ${datasetDataset.datasetId}
policyData: ${owner.policyData}
datasetDataset:
type: gcp:bigquery:Dataset
name: dataset
properties:
datasetId: example_dataset
variables:
owner:
fn::invoke:
function: gcp:organizations:getIAMPolicy
arguments:
bindings:
- role: roles/bigquery.dataOwner
members:
- user:jane@example.com
The getIAMPolicy data source generates the policy document with role bindings. DatasetIamPolicy applies this policy to the dataset, replacing any existing permissions. The policyData property contains the complete IAM policy; any roles or members not listed are removed.
Add time-based conditions to policy bindings
IAM conditions let you grant temporary access that expires automatically, useful for contractors or time-limited projects.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const owner = gcp.organizations.getIAMPolicy({
bindings: [{
role: "roles/bigquery.dataOwner",
members: ["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\")",
},
}],
});
const datasetDataset = new gcp.bigquery.Dataset("dataset", {datasetId: "example_dataset"});
const dataset = new gcp.bigquery.DatasetIamPolicy("dataset", {
datasetId: datasetDataset.datasetId,
policyData: owner.then(owner => owner.policyData),
});
import pulumi
import pulumi_gcp as gcp
owner = gcp.organizations.get_iam_policy(bindings=[{
"role": "roles/bigquery.dataOwner",
"members": ["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_dataset = gcp.bigquery.Dataset("dataset", dataset_id="example_dataset")
dataset = gcp.bigquery.DatasetIamPolicy("dataset",
dataset_id=dataset_dataset.dataset_id,
policy_data=owner.policy_data)
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/bigquery"
"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 {
owner, err := organizations.LookupIAMPolicy(ctx, &organizations.LookupIAMPolicyArgs{
Bindings: []organizations.GetIAMPolicyBinding{
{
Role: "roles/bigquery.dataOwner",
Members: []string{
"user:jane@example.com",
},
Condition: {
Title: "expires_after_2029_12_31",
Description: pulumi.StringRef("Expiring at midnight of 2029-12-31"),
Expression: "request.time < timestamp(\"2030-01-01T00:00:00Z\")",
},
},
},
}, nil)
if err != nil {
return err
}
datasetDataset, err := bigquery.NewDataset(ctx, "dataset", &bigquery.DatasetArgs{
DatasetId: pulumi.String("example_dataset"),
})
if err != nil {
return err
}
_, err = bigquery.NewDatasetIamPolicy(ctx, "dataset", &bigquery.DatasetIamPolicyArgs{
DatasetId: datasetDataset.DatasetId,
PolicyData: pulumi.String(owner.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 owner = Gcp.Organizations.GetIAMPolicy.Invoke(new()
{
Bindings = new[]
{
new Gcp.Organizations.Inputs.GetIAMPolicyBindingInputArgs
{
Role = "roles/bigquery.dataOwner",
Members = new[]
{
"user:jane@example.com",
},
Condition = new Gcp.Organizations.Inputs.GetIAMPolicyBindingConditionInputArgs
{
Title = "expires_after_2029_12_31",
Description = "Expiring at midnight of 2029-12-31",
Expression = "request.time < timestamp(\"2030-01-01T00:00:00Z\")",
},
},
},
});
var datasetDataset = new Gcp.BigQuery.Dataset("dataset", new()
{
DatasetId = "example_dataset",
});
var dataset = new Gcp.BigQuery.DatasetIamPolicy("dataset", new()
{
DatasetId = datasetDataset.DatasetId,
PolicyData = owner.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.bigquery.Dataset;
import com.pulumi.gcp.bigquery.DatasetArgs;
import com.pulumi.gcp.bigquery.DatasetIamPolicy;
import com.pulumi.gcp.bigquery.DatasetIamPolicyArgs;
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 owner = OrganizationsFunctions.getIAMPolicy(GetIAMPolicyArgs.builder()
.bindings(GetIAMPolicyBindingArgs.builder()
.role("roles/bigquery.dataOwner")
.members("user:jane@example.com")
.condition(GetIAMPolicyBindingConditionArgs.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())
.build());
var datasetDataset = new Dataset("datasetDataset", DatasetArgs.builder()
.datasetId("example_dataset")
.build());
var dataset = new DatasetIamPolicy("dataset", DatasetIamPolicyArgs.builder()
.datasetId(datasetDataset.datasetId())
.policyData(owner.policyData())
.build());
}
}
resources:
dataset:
type: gcp:bigquery:DatasetIamPolicy
properties:
datasetId: ${datasetDataset.datasetId}
policyData: ${owner.policyData}
datasetDataset:
type: gcp:bigquery:Dataset
name: dataset
properties:
datasetId: example_dataset
variables:
owner:
fn::invoke:
function: gcp:organizations:getIAMPolicy
arguments:
bindings:
- role: roles/bigquery.dataOwner
members:
- 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")
The condition block adds temporal constraints to role bindings. The expression uses CEL (Common Expression Language) to compare request.time against a timestamp. When the condition evaluates to false, the binding no longer grants access. The title and description help identify the condition’s purpose.
Grant a role to multiple members with DatasetIamBinding
When multiple users need the same level of access, DatasetIamBinding manages all members for a single role without affecting other roles 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 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
DatasetIamBinding is authoritative for a single role but non-authoritative for the dataset. It sets the complete member list for roles/bigquery.dataViewer, but other roles (like dataOwner or dataEditor) remain unchanged. The members array accepts user, serviceAccount, and group identities.
Add individual members with DatasetIamMember
For incremental permission changes, DatasetIamMember adds one member to one role without disturbing existing members or other roles.
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
DatasetIamMember is non-authoritative at both the role and dataset level. It adds a single member to a role, preserving other members for that role and all other role bindings. Use this when you need to grant access without knowing or affecting the complete member list.
Beyond these examples
These snippets focus on specific IAM management features: authoritative vs non-authoritative IAM management, conditional access with time-based expiration, and role-level and member-level permission grants. They’re intentionally minimal rather than full access control configurations.
The examples reference pre-existing infrastructure such as BigQuery datasets (created separately) and a GCP project with BigQuery API enabled. They focus on IAM binding configuration rather than dataset provisioning.
To keep things focused, common IAM patterns are omitted, including:
- Advanced conditions (resource attributes, request context)
- Service account and group member types
- Multiple role bindings in a single policy
- Authorized view permissions (requires DatasetAccess resource)
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 BigQuery DatasetIamPolicy resource reference for all available configuration options.
Let's manage GCP BigQuery Dataset IAM Policies
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Resource Conflicts & Compatibility
gcp.bigquery.DatasetAccess or the access field on gcp.bigquery.Dataset - they will conflict over the policy configuration.gcp.bigquery.DatasetIamPolicy cannot be used with gcp.bigquery.DatasetIamBinding or gcp.bigquery.DatasetIamMember - they will conflict over the policy. Use DatasetIamPolicy alone, or use Binding/Member together without Policy.gcp.bigquery.DatasetAccess instead.Resource Selection
DatasetIamPolicy is authoritative and replaces the entire IAM policy. DatasetIamBinding is authoritative for a specific role but preserves other roles. DatasetIamMember is non-authoritative and adds a single member to a role without affecting other members.gcp.bigquery.DatasetAccess for advanced use cases like creating authorized views, or when you need to preserve existing authorized view permissions.Role Configuration
roles/bigquery.dataOwner, roles/bigquery.dataEditor, and roles/bigquery.dataViewer.IAM Conditions
condition block with title, description, and expression fields. For example, use request.time < timestamp("2030-01-01T00:00:00Z") to expire permissions at a specific date.