The gcp:bigquery/datasetAccess:DatasetAccess resource, part of the Pulumi GCP provider, grants access to a BigQuery dataset for a single entity: a user, service account, view, routine, or another dataset. This guide focuses on three capabilities: user and service account access, view authorization, and dataset and routine authorization.
This resource attaches to existing datasets and references existing service accounts, views, routines, or other datasets. It’s designed for cases where you can’t compile a full access list in the Dataset resource itself. The examples are intentionally small. Combine them with your own datasets and identity management.
Grant user access with a service account
Teams often grant service accounts specific roles on datasets for automated pipelines or data analysis workflows.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const dataset = new gcp.bigquery.Dataset("dataset", {datasetId: "example_dataset"});
const bqowner = new gcp.serviceaccount.Account("bqowner", {accountId: "bqowner"});
const access = new gcp.bigquery.DatasetAccess("access", {
datasetId: dataset.datasetId,
role: "OWNER",
userByEmail: bqowner.email,
});
import pulumi
import pulumi_gcp as gcp
dataset = gcp.bigquery.Dataset("dataset", dataset_id="example_dataset")
bqowner = gcp.serviceaccount.Account("bqowner", account_id="bqowner")
access = gcp.bigquery.DatasetAccess("access",
dataset_id=dataset.dataset_id,
role="OWNER",
user_by_email=bqowner.email)
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/bigquery"
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/serviceaccount"
"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
}
bqowner, err := serviceaccount.NewAccount(ctx, "bqowner", &serviceaccount.AccountArgs{
AccountId: pulumi.String("bqowner"),
})
if err != nil {
return err
}
_, err = bigquery.NewDatasetAccess(ctx, "access", &bigquery.DatasetAccessArgs{
DatasetId: dataset.DatasetId,
Role: pulumi.String("OWNER"),
UserByEmail: bqowner.Email,
})
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 bqowner = new Gcp.ServiceAccount.Account("bqowner", new()
{
AccountId = "bqowner",
});
var access = new Gcp.BigQuery.DatasetAccess("access", new()
{
DatasetId = dataset.DatasetId,
Role = "OWNER",
UserByEmail = bqowner.Email,
});
});
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.serviceaccount.Account;
import com.pulumi.gcp.serviceaccount.AccountArgs;
import com.pulumi.gcp.bigquery.DatasetAccess;
import com.pulumi.gcp.bigquery.DatasetAccessArgs;
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 bqowner = new Account("bqowner", AccountArgs.builder()
.accountId("bqowner")
.build());
var access = new DatasetAccess("access", DatasetAccessArgs.builder()
.datasetId(dataset.datasetId())
.role("OWNER")
.userByEmail(bqowner.email())
.build());
}
}
resources:
access:
type: gcp:bigquery:DatasetAccess
properties:
datasetId: ${dataset.datasetId}
role: OWNER
userByEmail: ${bqowner.email}
dataset:
type: gcp:bigquery:Dataset
properties:
datasetId: example_dataset
bqowner:
type: gcp:serviceaccount:Account
properties:
accountId: bqowner
The datasetId property identifies the target dataset. The role property uses legacy format (OWNER, READER, WRITER) rather than roles/bigquery.dataOwner. The userByEmail property specifies the service account email that receives access.
Grant access to a view from another dataset
When a view in one dataset needs to query tables in another dataset, you authorize the view rather than individual users.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const _private = new gcp.bigquery.Dataset("private", {datasetId: "example_dataset"});
const _public = new gcp.bigquery.Dataset("public", {datasetId: "example_dataset2"});
const publicTable = new gcp.bigquery.Table("public", {
deletionProtection: false,
datasetId: _public.datasetId,
tableId: "example_table",
view: {
query: "SELECT state FROM [lookerdata:cdc.project_tycho_reports]",
useLegacySql: false,
},
});
const access = new gcp.bigquery.DatasetAccess("access", {
datasetId: _private.datasetId,
view: {
projectId: publicTable.project,
datasetId: _public.datasetId,
tableId: publicTable.tableId,
},
});
import pulumi
import pulumi_gcp as gcp
private = gcp.bigquery.Dataset("private", dataset_id="example_dataset")
public = gcp.bigquery.Dataset("public", dataset_id="example_dataset2")
public_table = gcp.bigquery.Table("public",
deletion_protection=False,
dataset_id=public.dataset_id,
table_id="example_table",
view={
"query": "SELECT state FROM [lookerdata:cdc.project_tycho_reports]",
"use_legacy_sql": False,
})
access = gcp.bigquery.DatasetAccess("access",
dataset_id=private.dataset_id,
view={
"project_id": public_table.project,
"dataset_id": public.dataset_id,
"table_id": public_table.table_id,
})
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 {
private, err := bigquery.NewDataset(ctx, "private", &bigquery.DatasetArgs{
DatasetId: pulumi.String("example_dataset"),
})
if err != nil {
return err
}
public, err := bigquery.NewDataset(ctx, "public", &bigquery.DatasetArgs{
DatasetId: pulumi.String("example_dataset2"),
})
if err != nil {
return err
}
publicTable, err := bigquery.NewTable(ctx, "public", &bigquery.TableArgs{
DeletionProtection: pulumi.Bool(false),
DatasetId: public.DatasetId,
TableId: pulumi.String("example_table"),
View: &bigquery.TableViewArgs{
Query: pulumi.String("SELECT state FROM [lookerdata:cdc.project_tycho_reports]"),
UseLegacySql: pulumi.Bool(false),
},
})
if err != nil {
return err
}
_, err = bigquery.NewDatasetAccess(ctx, "access", &bigquery.DatasetAccessArgs{
DatasetId: private.DatasetId,
View: &bigquery.DatasetAccessViewArgs{
ProjectId: publicTable.Project,
DatasetId: public.DatasetId,
TableId: publicTable.TableId,
},
})
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 @private = new Gcp.BigQuery.Dataset("private", new()
{
DatasetId = "example_dataset",
});
var @public = new Gcp.BigQuery.Dataset("public", new()
{
DatasetId = "example_dataset2",
});
var publicTable = new Gcp.BigQuery.Table("public", new()
{
DeletionProtection = false,
DatasetId = @public.DatasetId,
TableId = "example_table",
View = new Gcp.BigQuery.Inputs.TableViewArgs
{
Query = "SELECT state FROM [lookerdata:cdc.project_tycho_reports]",
UseLegacySql = false,
},
});
var access = new Gcp.BigQuery.DatasetAccess("access", new()
{
DatasetId = @private.DatasetId,
View = new Gcp.BigQuery.Inputs.DatasetAccessViewArgs
{
ProjectId = publicTable.Project,
DatasetId = @public.DatasetId,
TableId = publicTable.TableId,
},
});
});
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.Table;
import com.pulumi.gcp.bigquery.TableArgs;
import com.pulumi.gcp.bigquery.inputs.TableViewArgs;
import com.pulumi.gcp.bigquery.DatasetAccess;
import com.pulumi.gcp.bigquery.DatasetAccessArgs;
import com.pulumi.gcp.bigquery.inputs.DatasetAccessViewArgs;
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 private_ = new Dataset("private", DatasetArgs.builder()
.datasetId("example_dataset")
.build());
var public_ = new Dataset("public", DatasetArgs.builder()
.datasetId("example_dataset2")
.build());
var publicTable = new Table("publicTable", TableArgs.builder()
.deletionProtection(false)
.datasetId(public_.datasetId())
.tableId("example_table")
.view(TableViewArgs.builder()
.query("SELECT state FROM [lookerdata:cdc.project_tycho_reports]")
.useLegacySql(false)
.build())
.build());
var access = new DatasetAccess("access", DatasetAccessArgs.builder()
.datasetId(private_.datasetId())
.view(DatasetAccessViewArgs.builder()
.projectId(publicTable.project())
.datasetId(public_.datasetId())
.tableId(publicTable.tableId())
.build())
.build());
}
}
resources:
access:
type: gcp:bigquery:DatasetAccess
properties:
datasetId: ${private.datasetId}
view:
projectId: ${publicTable.project}
datasetId: ${public.datasetId}
tableId: ${publicTable.tableId}
private:
type: gcp:bigquery:Dataset
properties:
datasetId: example_dataset
public:
type: gcp:bigquery:Dataset
properties:
datasetId: example_dataset2
publicTable:
type: gcp:bigquery:Table
name: public
properties:
deletionProtection: false
datasetId: ${public.datasetId}
tableId: example_table
view:
query: SELECT state FROM [lookerdata:cdc.project_tycho_reports]
useLegacySql: false
The view block identifies the view by projectId, datasetId, and tableId. When you grant view access, queries against that view can read tables in the target dataset. No role property is required for view authorization.
Authorize all views in another dataset
Instead of authorizing individual views, you can grant access to all views in a dataset at once.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const _private = new gcp.bigquery.Dataset("private", {datasetId: "private"});
const _public = new gcp.bigquery.Dataset("public", {datasetId: "public"});
const access = new gcp.bigquery.DatasetAccess("access", {
datasetId: _private.datasetId,
authorizedDataset: {
dataset: {
projectId: _public.project,
datasetId: _public.datasetId,
},
targetTypes: ["VIEWS"],
},
});
import pulumi
import pulumi_gcp as gcp
private = gcp.bigquery.Dataset("private", dataset_id="private")
public = gcp.bigquery.Dataset("public", dataset_id="public")
access = gcp.bigquery.DatasetAccess("access",
dataset_id=private.dataset_id,
authorized_dataset={
"dataset": {
"project_id": public.project,
"dataset_id": public.dataset_id,
},
"target_types": ["VIEWS"],
})
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 {
private, err := bigquery.NewDataset(ctx, "private", &bigquery.DatasetArgs{
DatasetId: pulumi.String("private"),
})
if err != nil {
return err
}
public, err := bigquery.NewDataset(ctx, "public", &bigquery.DatasetArgs{
DatasetId: pulumi.String("public"),
})
if err != nil {
return err
}
_, err = bigquery.NewDatasetAccess(ctx, "access", &bigquery.DatasetAccessArgs{
DatasetId: private.DatasetId,
AuthorizedDataset: &bigquery.DatasetAccessAuthorizedDatasetArgs{
Dataset: &bigquery.DatasetAccessAuthorizedDatasetDatasetArgs{
ProjectId: public.Project,
DatasetId: public.DatasetId,
},
TargetTypes: pulumi.StringArray{
pulumi.String("VIEWS"),
},
},
})
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 @private = new Gcp.BigQuery.Dataset("private", new()
{
DatasetId = "private",
});
var @public = new Gcp.BigQuery.Dataset("public", new()
{
DatasetId = "public",
});
var access = new Gcp.BigQuery.DatasetAccess("access", new()
{
DatasetId = @private.DatasetId,
AuthorizedDataset = new Gcp.BigQuery.Inputs.DatasetAccessAuthorizedDatasetArgs
{
Dataset = new Gcp.BigQuery.Inputs.DatasetAccessAuthorizedDatasetDatasetArgs
{
ProjectId = @public.Project,
DatasetId = @public.DatasetId,
},
TargetTypes = new[]
{
"VIEWS",
},
},
});
});
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.DatasetAccess;
import com.pulumi.gcp.bigquery.DatasetAccessArgs;
import com.pulumi.gcp.bigquery.inputs.DatasetAccessAuthorizedDatasetArgs;
import com.pulumi.gcp.bigquery.inputs.DatasetAccessAuthorizedDatasetDatasetArgs;
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 private_ = new Dataset("private", DatasetArgs.builder()
.datasetId("private")
.build());
var public_ = new Dataset("public", DatasetArgs.builder()
.datasetId("public")
.build());
var access = new DatasetAccess("access", DatasetAccessArgs.builder()
.datasetId(private_.datasetId())
.authorizedDataset(DatasetAccessAuthorizedDatasetArgs.builder()
.dataset(DatasetAccessAuthorizedDatasetDatasetArgs.builder()
.projectId(public_.project())
.datasetId(public_.datasetId())
.build())
.targetTypes("VIEWS")
.build())
.build());
}
}
resources:
access:
type: gcp:bigquery:DatasetAccess
properties:
datasetId: ${private.datasetId}
authorizedDataset:
dataset:
projectId: ${public.project}
datasetId: ${public.datasetId}
targetTypes:
- VIEWS
private:
type: gcp:bigquery:Dataset
properties:
datasetId: private
public:
type: gcp:bigquery:Dataset
properties:
datasetId: public
The authorizedDataset block identifies the source dataset and specifies targetTypes to limit which resource types receive access. Setting targetTypes to [“VIEWS”] means only views in the public dataset can query the private dataset.
Authorize a routine from another dataset
User-defined functions and stored procedures sometimes need to read tables from another dataset.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
const _public = new gcp.bigquery.Dataset("public", {
datasetId: "public_dataset",
description: "This dataset is public",
});
const publicRoutine = new gcp.bigquery.Routine("public", {
datasetId: _public.datasetId,
routineId: "public_routine",
routineType: "TABLE_VALUED_FUNCTION",
language: "SQL",
definitionBody: "SELECT 1 + value AS value\n",
arguments: [{
name: "value",
argumentKind: "FIXED_TYPE",
dataType: JSON.stringify({
typeKind: "INT64",
}),
}],
returnTableType: JSON.stringify({
columns: [{
name: "value",
type: {
typeKind: "INT64",
},
}],
}),
});
const _private = new gcp.bigquery.Dataset("private", {
datasetId: "private_dataset",
description: "This dataset is private",
});
const authorizedRoutine = new gcp.bigquery.DatasetAccess("authorized_routine", {
datasetId: _private.datasetId,
routine: {
projectId: publicRoutine.project,
datasetId: publicRoutine.datasetId,
routineId: publicRoutine.routineId,
},
});
import pulumi
import json
import pulumi_gcp as gcp
public = gcp.bigquery.Dataset("public",
dataset_id="public_dataset",
description="This dataset is public")
public_routine = gcp.bigquery.Routine("public",
dataset_id=public.dataset_id,
routine_id="public_routine",
routine_type="TABLE_VALUED_FUNCTION",
language="SQL",
definition_body="SELECT 1 + value AS value\n",
arguments=[{
"name": "value",
"argument_kind": "FIXED_TYPE",
"data_type": json.dumps({
"typeKind": "INT64",
}),
}],
return_table_type=json.dumps({
"columns": [{
"name": "value",
"type": {
"typeKind": "INT64",
},
}],
}))
private = gcp.bigquery.Dataset("private",
dataset_id="private_dataset",
description="This dataset is private")
authorized_routine = gcp.bigquery.DatasetAccess("authorized_routine",
dataset_id=private.dataset_id,
routine={
"project_id": public_routine.project,
"dataset_id": public_routine.dataset_id,
"routine_id": public_routine.routine_id,
})
package main
import (
"encoding/json"
"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 {
public, err := bigquery.NewDataset(ctx, "public", &bigquery.DatasetArgs{
DatasetId: pulumi.String("public_dataset"),
Description: pulumi.String("This dataset is public"),
})
if err != nil {
return err
}
tmpJSON0, err := json.Marshal(map[string]interface{}{
"typeKind": "INT64",
})
if err != nil {
return err
}
json0 := string(tmpJSON0)
tmpJSON1, err := json.Marshal(map[string]interface{}{
"columns": []map[string]interface{}{
map[string]interface{}{
"name": "value",
"type": map[string]interface{}{
"typeKind": "INT64",
},
},
},
})
if err != nil {
return err
}
json1 := string(tmpJSON1)
publicRoutine, err := bigquery.NewRoutine(ctx, "public", &bigquery.RoutineArgs{
DatasetId: public.DatasetId,
RoutineId: pulumi.String("public_routine"),
RoutineType: pulumi.String("TABLE_VALUED_FUNCTION"),
Language: pulumi.String("SQL"),
DefinitionBody: pulumi.String("SELECT 1 + value AS value\n"),
Arguments: bigquery.RoutineArgumentArray{
&bigquery.RoutineArgumentArgs{
Name: pulumi.String("value"),
ArgumentKind: pulumi.String("FIXED_TYPE"),
DataType: pulumi.String(json0),
},
},
ReturnTableType: pulumi.String(json1),
})
if err != nil {
return err
}
private, err := bigquery.NewDataset(ctx, "private", &bigquery.DatasetArgs{
DatasetId: pulumi.String("private_dataset"),
Description: pulumi.String("This dataset is private"),
})
if err != nil {
return err
}
_, err = bigquery.NewDatasetAccess(ctx, "authorized_routine", &bigquery.DatasetAccessArgs{
DatasetId: private.DatasetId,
Routine: &bigquery.DatasetAccessRoutineArgs{
ProjectId: publicRoutine.Project,
DatasetId: publicRoutine.DatasetId,
RoutineId: publicRoutine.RoutineId,
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Gcp = Pulumi.Gcp;
return await Deployment.RunAsync(() =>
{
var @public = new Gcp.BigQuery.Dataset("public", new()
{
DatasetId = "public_dataset",
Description = "This dataset is public",
});
var publicRoutine = new Gcp.BigQuery.Routine("public", new()
{
DatasetId = @public.DatasetId,
RoutineId = "public_routine",
RoutineType = "TABLE_VALUED_FUNCTION",
Language = "SQL",
DefinitionBody = @"SELECT 1 + value AS value
",
Arguments = new[]
{
new Gcp.BigQuery.Inputs.RoutineArgumentArgs
{
Name = "value",
ArgumentKind = "FIXED_TYPE",
DataType = JsonSerializer.Serialize(new Dictionary<string, object?>
{
["typeKind"] = "INT64",
}),
},
},
ReturnTableType = JsonSerializer.Serialize(new Dictionary<string, object?>
{
["columns"] = new[]
{
new Dictionary<string, object?>
{
["name"] = "value",
["type"] = new Dictionary<string, object?>
{
["typeKind"] = "INT64",
},
},
},
}),
});
var @private = new Gcp.BigQuery.Dataset("private", new()
{
DatasetId = "private_dataset",
Description = "This dataset is private",
});
var authorizedRoutine = new Gcp.BigQuery.DatasetAccess("authorized_routine", new()
{
DatasetId = @private.DatasetId,
Routine = new Gcp.BigQuery.Inputs.DatasetAccessRoutineArgs
{
ProjectId = publicRoutine.Project,
DatasetId = publicRoutine.DatasetId,
RoutineId = publicRoutine.RoutineId,
},
});
});
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.Routine;
import com.pulumi.gcp.bigquery.RoutineArgs;
import com.pulumi.gcp.bigquery.inputs.RoutineArgumentArgs;
import com.pulumi.gcp.bigquery.DatasetAccess;
import com.pulumi.gcp.bigquery.DatasetAccessArgs;
import com.pulumi.gcp.bigquery.inputs.DatasetAccessRoutineArgs;
import static com.pulumi.codegen.internal.Serialization.*;
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 public_ = new Dataset("public", DatasetArgs.builder()
.datasetId("public_dataset")
.description("This dataset is public")
.build());
var publicRoutine = new Routine("publicRoutine", RoutineArgs.builder()
.datasetId(public_.datasetId())
.routineId("public_routine")
.routineType("TABLE_VALUED_FUNCTION")
.language("SQL")
.definitionBody("""
SELECT 1 + value AS value
""")
.arguments(RoutineArgumentArgs.builder()
.name("value")
.argumentKind("FIXED_TYPE")
.dataType(serializeJson(
jsonObject(
jsonProperty("typeKind", "INT64")
)))
.build())
.returnTableType(serializeJson(
jsonObject(
jsonProperty("columns", jsonArray(jsonObject(
jsonProperty("name", "value"),
jsonProperty("type", jsonObject(
jsonProperty("typeKind", "INT64")
))
)))
)))
.build());
var private_ = new Dataset("private", DatasetArgs.builder()
.datasetId("private_dataset")
.description("This dataset is private")
.build());
var authorizedRoutine = new DatasetAccess("authorizedRoutine", DatasetAccessArgs.builder()
.datasetId(private_.datasetId())
.routine(DatasetAccessRoutineArgs.builder()
.projectId(publicRoutine.project())
.datasetId(publicRoutine.datasetId())
.routineId(publicRoutine.routineId())
.build())
.build());
}
}
resources:
public:
type: gcp:bigquery:Dataset
properties:
datasetId: public_dataset
description: This dataset is public
publicRoutine:
type: gcp:bigquery:Routine
name: public
properties:
datasetId: ${public.datasetId}
routineId: public_routine
routineType: TABLE_VALUED_FUNCTION
language: SQL
definitionBody: |
SELECT 1 + value AS value
arguments:
- name: value
argumentKind: FIXED_TYPE
dataType:
fn::toJSON:
typeKind: INT64
returnTableType:
fn::toJSON:
columns:
- name: value
type:
typeKind: INT64
private:
type: gcp:bigquery:Dataset
properties:
datasetId: private_dataset
description: This dataset is private
authorizedRoutine:
type: gcp:bigquery:DatasetAccess
name: authorized_routine
properties:
datasetId: ${private.datasetId}
routine:
projectId: ${publicRoutine.project}
datasetId: ${publicRoutine.datasetId}
routineId: ${publicRoutine.routineId}
The routine block identifies the routine by projectId, datasetId, and routineId. Queries executed against that routine can read tables in the target dataset. Like view authorization, no role property is required.
Beyond these examples
These snippets focus on specific dataset access features: user and service account access, view and routine authorization, and dataset-level authorization. They’re intentionally minimal rather than full access control systems.
The examples reference pre-existing infrastructure such as BigQuery datasets (the access resource attaches to existing datasets), and service accounts, views, routines, or other datasets being authorized. They focus on configuring access grants rather than provisioning the underlying resources.
To keep things focused, common access patterns are omitted, including:
- Group and domain-based access (groupByEmail, domain)
- Special groups (projectOwners, projectReaders, allAuthenticatedUsers)
- IAM member syntax (iamMember for allUsers, etc.)
- Conditional access with CEL expressions (condition block)
These omissions are intentional: the goal is to illustrate how each access type is wired, not provide drop-in access control modules. See the BigQuery DatasetAccess resource reference for all available configuration options.
Let's configure GCP BigQuery Dataset Access
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Resource Conflicts & Lifecycle
DatasetAccess alongside gcp.bigquery.Dataset, the Dataset resource must either have no access blocks defined or include a lifecycle block with ignore_changes = [access]. Additionally, you cannot modify both resources in the same apply operation.Role Configuration & Formatting
OWNER instead of roles/bigquery.dataOwner. The API accepts both formats but always returns the legacy format, causing perpetual diffs if you use the modern format.apiUpdatedMember is true, it indicates that the iamMember you specified was translated to a different member type by the API and is stored in state differently.Access Types & Configuration
userByEmail, groupByEmail, domain, specialGroup (projectOwners, projectReaders, projectWriters, allAuthenticatedUsers), iamMember, view, routine, or authorizedDataset.projectOwners, projectReaders, projectWriters, and allAuthenticatedUsers.Immutability & Updates
datasetId, role, or access member properties require replacing the resource.DatasetAccess resource.Advanced Access Patterns
view property with projectId, datasetId, and tableId pointing to the view. The role field is not required when granting view access.authorizedDataset with the target dataset’s projectId and datasetId, and set targetTypes to ["VIEWS"].Using a different cloud?
Explore analytics guides for other cloud providers: