Skip to content

Commit f2b62df

Browse files
feat(bigquery): add samples for control access
1 parent 4401f90 commit f2b62df

File tree

6 files changed

+650
-0
lines changed

6 files changed

+650
-0
lines changed
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
/**
18+
* Grants access to a BigQuery dataset for a specified entity.
19+
*
20+
* @param {string} datasetId ID of the dataset to grant access to.
21+
* @param {string} entityId ID of the entity to grant access to.
22+
* @param {string} role Role to grant.
23+
* @returns {Promise<Array>} Array of access entries.
24+
*/
25+
async function grantAccessToDataset(datasetId, entityId, role) {
26+
// [START bigquery_grant_access_to_dataset]
27+
const {BigQuery} = require('@google-cloud/bigquery');
28+
29+
// Define enum for HTTP codes.
30+
const HTTP_STATUS = {
31+
PRECONDITION_FAILED: 412,
32+
};
33+
34+
// TODO(developer): Update and un-comment below lines.
35+
36+
// ID of the dataset to revoke access to.
37+
// datasetId = "my_project_id.my_dataset_name";
38+
39+
// ID of the user or group from whom you are adding access.
40+
// Alternatively, the JSON REST API representation of the entity,
41+
// such as a view's table reference.
42+
// entityId = "[email protected]";
43+
44+
// One of the "Basic roles for datasets" described here:
45+
// https://cloud.google.com/bigquery/docs/access-control-basic-roles#dataset-basic-roles
46+
// role = "READER";
47+
48+
// Type of entity you are granting access to.
49+
// Find allowed allowed entity type names here:
50+
// https://cloud.google.com/bigquery/docs/reference/rest/v2/datasets#resource:-dataset
51+
// In this case, we're using groupByEmail
52+
const entityType = 'groupByEmail';
53+
54+
// Instantiate a client.
55+
const client = new BigQuery();
56+
57+
try {
58+
// Get a reference to the dataset.
59+
const [dataset] = await client.dataset(datasetId).get();
60+
61+
// The 'access entries' array is immutable. Create a copy for modifications.
62+
const entries = Array.isArray(dataset.metadata.access)
63+
? [...dataset.metadata.access]
64+
: [];
65+
66+
// Append an AccessEntry to grant the role to a dataset.
67+
// Find more details about the AccessEntry object in the BigQuery documentation:
68+
// https://cloud.google.com/python/docs/reference/bigquery/latest/google.cloud.bigquery.dataset.AccessEntry
69+
entries.push({
70+
role: role,
71+
[entityType]: entityId,
72+
});
73+
74+
// Assign the array of AccessEntries back to the dataset.
75+
const metadata = {
76+
access: entries,
77+
};
78+
79+
// Update will only succeed if the dataset
80+
// has not been modified externally since retrieval.
81+
//
82+
// See the BigQuery client library documentation for more details on metadata updates:
83+
// https://cloud.google.com/nodejs/docs/reference/bigquery/latest
84+
85+
// Update just the 'access entries' property of the dataset.
86+
const [updatedDataset] = await client
87+
.dataset(datasetId)
88+
.setMetadata(metadata);
89+
90+
// Show a success message.
91+
console.log(
92+
`Role '${role}' granted for entity '${entityId}' in dataset '${datasetId}'.`
93+
);
94+
95+
return updatedDataset.access;
96+
} catch (error) {
97+
if (error.code === HTTP_STATUS.PRECONDITION_FAILED) {
98+
console.error(
99+
`Dataset '${datasetId}' was modified remotely before this update. ` +
100+
'Fetch the latest version and retry.'
101+
);
102+
} else {
103+
throw error;
104+
}
105+
}
106+
// [END bigquery_grant_access_to_dataset]
107+
}
108+
109+
module.exports = {
110+
grantAccessToDataset,
111+
};
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
/**
18+
* Grants access to a BigQuery table or view for a specified principal.
19+
*
20+
* @param {string} projectId Google Cloud Platform project ID.
21+
* @param {string} datasetId Dataset where the table or view is.
22+
* @param {string} resourceName Table or view name to get the access policy.
23+
* @param {string} principalId The principal requesting access to the table or view.
24+
* @param {string} role Role to assign to the member.
25+
* @returns {Promise<object[]>} The updated policy bindings.
26+
*/
27+
async function grantAccessToTableOrView(
28+
projectId,
29+
datasetId,
30+
resourceName,
31+
principalId,
32+
role
33+
) {
34+
// [START bigquery_grant_access_to_table_or_view]
35+
const {BigQuery} = require('@google-cloud/bigquery');
36+
37+
// TODO(developer): Update and un-comment below lines.
38+
39+
// Google Cloud Platform project.
40+
// projectId = "my_project_id"
41+
42+
// Dataset where the table or view is.
43+
// datasetId = "my_dataset_id"
44+
45+
// Table or view name to get the access policy.
46+
// resourceName = "my_table_id"
47+
48+
// The principal requesting access to the table or view.
49+
// Find more details about principal identifiers here:
50+
// https://cloud.google.com/iam/docs/principal-identifiers
51+
// principalId = "user:[email protected]"
52+
53+
// Role to assign to the member.
54+
// role = "roles/bigquery.dataViewer"
55+
56+
// Instantiate a client.
57+
const client = new BigQuery();
58+
59+
// Get a reference to the dataset by datasetId.
60+
const dataset = client.dataset(datasetId);
61+
// Get a reference to the table by tableName.
62+
const table = dataset.table(resourceName);
63+
64+
// Get the IAM access policy for the table or view.
65+
const [policy] = await table.getIamPolicy();
66+
67+
// Initialize bindings array.
68+
if (!policy.bindings) {
69+
policy.bindings = [];
70+
}
71+
72+
// To grant access to a table or view
73+
// add bindings to the Table or View policy.
74+
//
75+
// Find more details about Policy and Binding objects here:
76+
// https://cloud.google.com/security-command-center/docs/reference/rest/Shared.Types/Policy
77+
// https://cloud.google.com/security-command-center/docs/reference/rest/Shared.Types/Binding
78+
const binding = {
79+
role: role,
80+
members: [principalId],
81+
};
82+
policy.bindings.push(binding);
83+
84+
// Set the IAM access policy with updated bindings.
85+
const [updatedPolicy] = await table.setIamPolicy(policy);
86+
87+
// Show a success message.
88+
console.log(
89+
`Role '${role}' granted for principal '${principalId}' on resource '${datasetId}.${resourceName}'.`
90+
);
91+
// [END bigquery_grant_access_to_table_or_view]
92+
return updatedPolicy.bindings;
93+
}
94+
95+
module.exports = {grantAccessToTableOrView};

bigquery/cloud-client/package.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"name": "bigquery-cloud-client",
3+
"description": "Big Query Cloud Client Node.js samples",
4+
"version": "0.0.1",
5+
"private": true,
6+
"license": "Apache Version 2.0",
7+
"author": "Google LLC",
8+
"engines": {
9+
"node": "20.x"
10+
},
11+
"scripts": {
12+
"deploy": "gcloud app deploy",
13+
"start": "node app.js",
14+
"unit-test": "c8 mocha -p -j 2 test/ --timeout=10000 --exit",
15+
"test": "npm run unit-test"
16+
},
17+
"dependencies": {
18+
"@google-cloud/bigquery": "7.9.2"
19+
},
20+
"devDependencies": {
21+
"c8": "^10.0.0",
22+
"chai": "^4.5.0",
23+
"mocha": "^10.0.0",
24+
"sinon": "^18.0.0"
25+
}
26+
}

0 commit comments

Comments
 (0)