Skip to content

Commit 5c22968

Browse files
AVaksmancrwilcox
authored andcommitted
feat: implement instance and table level IAM policy (#584)
* feat: add table level IAM policy controls * lint: lint * feat: add instance level IAM policy * docs: update description * docs: add document snippets * lint: lint
1 parent c5ceaeb commit 5c22968

File tree

7 files changed

+1066
-3
lines changed

7 files changed

+1066
-3
lines changed

samples/document-snippets/instance.js

+61
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,67 @@ const snippets = {
204204
// [END bigtable_get_clusters]
205205
},
206206

207+
getIamPolicy: instanceId => {
208+
// [START bigtable_get_instance_Iam_policy]
209+
const Bigtable = require('@google-cloud/bigtable');
210+
const bigtable = new Bigtable();
211+
const instance = bigtable.instance(instanceId);
212+
213+
instance
214+
.getIamPolicy()
215+
.then(result => {
216+
const policy = result[0];
217+
})
218+
.catch(err => {
219+
// Handle the error.
220+
});
221+
// [END bigtable_get_instance_Iam_policy]
222+
},
223+
224+
setIamPolicy: instanceId => {
225+
// [START bigtable_set_instance_Iam_policy]
226+
const Bigtable = require('@google-cloud/bigtable');
227+
const bigtable = new Bigtable();
228+
const instance = bigtable.instance(instanceId);
229+
230+
const policy = {
231+
bindings: [
232+
{
233+
role: 'roles/bigtable.viewer',
234+
members: ['user:mike@example.com', 'group:admins@example.com'],
235+
},
236+
],
237+
};
238+
239+
instance
240+
.setIamPolicy(policy)
241+
.then(result => {
242+
const setPolicy = result[0];
243+
})
244+
.catch(err => {
245+
// Handle the error
246+
});
247+
// [END bigtable_set_instance_Iam_policy]
248+
},
249+
250+
testIamPermissions: instanceId => {
251+
// [START bigtable_test_instance_Iam_permissions]
252+
const Bigtable = require('@google-cloud/bigtable');
253+
const bigtable = new Bigtable();
254+
const instance = bigtable.instance(instanceId);
255+
256+
const permissions = ['bigtable.tables.get', 'bigtable.tables.readRows'];
257+
instance
258+
.testIamPermissions(permissions)
259+
.then(result => {
260+
const grantedPermissions = result[0];
261+
})
262+
.catch(err => {
263+
// Handle the error
264+
});
265+
// [END bigtable_test_instance_Iam_permissions]
266+
},
267+
207268
getAppProfiles: instanceId => {
208269
// [START bigtable_get_app_profiles]
209270
const Bigtable = require('@google-cloud/bigtable');

samples/document-snippets/table.js

+64
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,70 @@ const snippets = {
295295
// [END bigtable_sample_row_keys]
296296
},
297297

298+
getIamPolicy: (instanceId, tableId) => {
299+
// [START bigtable_get_table_Iam_policy]
300+
const Bigtable = require('@google-cloud/bigtable');
301+
const bigtable = new Bigtable();
302+
const instance = bigtable.instance(instanceId);
303+
const table = instance.table(tableId);
304+
305+
table
306+
.getIamPolicy()
307+
.then(result => {
308+
const policy = result[0];
309+
})
310+
.catch(err => {
311+
// Handle the error.
312+
});
313+
// [END bigtable_get_table_Iam_policy]
314+
},
315+
316+
setIamPolicy: (instanceId, tableId) => {
317+
// [START bigtable_set_table_Iam_policy]
318+
const Bigtable = require('@google-cloud/bigtable');
319+
const bigtable = new Bigtable();
320+
const instance = bigtable.instance(instanceId);
321+
const table = instance.table(tableId);
322+
323+
const policy = {
324+
bindings: [
325+
{
326+
role: 'roles/bigtable.viewer',
327+
members: ['user:mike@example.com', 'group:admins@example.com'],
328+
},
329+
],
330+
};
331+
332+
table
333+
.setIamPolicy(policy)
334+
.then(result => {
335+
const setPolicy = result[0];
336+
})
337+
.catch(err => {
338+
// Handle the error
339+
});
340+
// [END bigtable_set_table_Iam_policy]
341+
},
342+
343+
testIamPermissions: (instanceId, tableId) => {
344+
// [START bigtable_test_table_Iam_permissions]
345+
const Bigtable = require('@google-cloud/bigtable');
346+
const bigtable = new Bigtable();
347+
const instance = bigtable.instance(instanceId);
348+
const table = instance.table(tableId);
349+
350+
const permissions = ['bigtable.tables.get', 'bigtable.tables.readRows'];
351+
table
352+
.testIamPermissions(permissions)
353+
.then(result => {
354+
const grantedPermissions = result[0];
355+
})
356+
.catch(err => {
357+
// Handle the error
358+
});
359+
// [END bigtable_test_table_Iam_permissions]
360+
},
361+
298362
delRows: (instanceId, tableId) => {
299363
const instance = bigtable.instance(instanceId);
300364
const table = instance.table(tableId);

src/instance.ts

+186-1
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,24 @@
1616

1717
import {paginator} from '@google-cloud/paginator';
1818
import {promisifyAll} from '@google-cloud/promisify';
19+
import arrify = require('arrify');
1920
import * as is from 'is';
2021
import snakeCase = require('lodash.snakecase');
2122
import {AppProfile} from './app-profile';
2223
import {Cluster} from './cluster';
2324
import {Family} from './family';
24-
import {Table} from './table';
25+
import {
26+
GetIamPolicyCallback,
27+
GetIamPolicyOptions,
28+
GetIamPolicyResponse,
29+
Policy,
30+
SetIamPolicyCallback,
31+
SetIamPolicyResponse,
32+
Table,
33+
TestIamPermissionsCallback,
34+
TestIamPermissionsResponse,
35+
} from './table';
36+
import {CallOptions} from 'google-gax';
2537

2638
/**
2739
* Create an Instance object to interact with a Cloud Bigtable instance.
@@ -555,6 +567,63 @@ Please use the format 'my-instance' or '${bigtable.projectName}/instances/my-ins
555567
);
556568
}
557569

570+
getIamPolicy(options?): Promise<[Policy]>;
571+
getIamPolicy(options, callback): void;
572+
/**
573+
* @param {object} [options] Configuration object.
574+
* @param {object} [options.gaxOptions] Request configuration options, outlined
575+
* here: https://googleapis.github.io/gax-nodejs/CallSettings.html.
576+
* @param {number} [options.requestedPolicyVersion] The policy format version
577+
* to be returned. Valid values are 0, 1, and 3. Requests specifying an
578+
* invalid value will be rejected. Requests for policies with any
579+
* conditional bindings must specify version 3. Policies without any
580+
* conditional bindings may specify any valid value or leave the field unset.
581+
* @param {function} [callback] The callback function.
582+
* @param {?error} callback.error An error returned while making this request.
583+
* @param {Policy} policy The policy.
584+
*
585+
* @example <caption>include:samples/document-snippets/instance.js</caption>
586+
* region_tag:bigtable_get_instance_Iam_policy
587+
*/
588+
getIamPolicy(
589+
optionsOrCallback?: GetIamPolicyOptions | GetIamPolicyCallback,
590+
callback?: GetIamPolicyCallback
591+
): void | Promise<GetIamPolicyResponse> {
592+
const options =
593+
typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
594+
callback =
595+
typeof optionsOrCallback === 'function' ? optionsOrCallback : callback!;
596+
597+
const reqOpts: any = {
598+
resource: this.name,
599+
};
600+
601+
if (
602+
options.requestedPolicyVersion !== null &&
603+
options.requestedPolicyVersion !== undefined
604+
) {
605+
reqOpts.options = {
606+
requestedPolicyVersion: options.requestedPolicyVersion,
607+
};
608+
}
609+
610+
this.bigtable.request(
611+
{
612+
client: 'BigtableInstanceAdminClient',
613+
method: 'getIamPolicy',
614+
reqOpts,
615+
gaxOpts: options.gaxOptions,
616+
},
617+
(err, resp) => {
618+
if (err) {
619+
callback!(err);
620+
return;
621+
}
622+
callback!(null, Table.decodePolicyEtag(resp));
623+
}
624+
);
625+
}
626+
558627
/**
559628
* Get the instance metadata.
560629
*
@@ -650,6 +719,62 @@ Please use the format 'my-instance' or '${bigtable.projectName}/instances/my-ins
650719
);
651720
}
652721

722+
setIamPolicy(
723+
policy: Policy,
724+
gaxOptions?: CallOptions
725+
): Promise<SetIamPolicyResponse>;
726+
setIamPolicy(
727+
policy: Policy,
728+
gaxOptions: CallOptions,
729+
callback: SetIamPolicyCallback
730+
): void;
731+
setIamPolicy(policy: Policy, callback: SetIamPolicyCallback): void;
732+
/**
733+
* @param {object} [gaxOptions] Request configuration options, outlined
734+
* here: https://googleapis.github.io/gax-nodejs/CallSettings.html.
735+
* @param {function} [callback] The callback function.
736+
* @param {?error} callback.error An error returned while making this request.
737+
* @param {Policy} policy The policy.
738+
*
739+
* @example <caption>include:samples/document-snippets/instance.js</caption>
740+
* region_tag:bigtable_set_instance_Iam_policy
741+
*/
742+
setIamPolicy(
743+
policy: Policy,
744+
gaxOptionsOrCallback?: CallOptions | SetIamPolicyCallback,
745+
callback?: SetIamPolicyCallback
746+
): void | Promise<SetIamPolicyResponse> {
747+
const gaxOptions =
748+
typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {};
749+
callback =
750+
typeof gaxOptionsOrCallback === 'function'
751+
? gaxOptionsOrCallback
752+
: callback!;
753+
754+
if (policy.etag !== null && policy.etag !== undefined) {
755+
((policy.etag as {}) as Buffer) = Buffer.from(policy.etag);
756+
}
757+
const reqOpts: any = {
758+
resource: this.name,
759+
policy,
760+
};
761+
762+
this.bigtable.request(
763+
{
764+
client: 'BigtableInstanceAdminClient',
765+
method: 'setIamPolicy',
766+
reqOpts,
767+
gaxOpts: gaxOptions,
768+
},
769+
(err, resp) => {
770+
if (err) {
771+
callback!(err);
772+
}
773+
callback!(null, Table.decodePolicyEtag(resp));
774+
}
775+
);
776+
}
777+
653778
/**
654779
* Set the instance metadata.
655780
*
@@ -718,6 +843,66 @@ Please use the format 'my-instance' or '${bigtable.projectName}/instances/my-ins
718843
table(id) {
719844
return new Table(this, id);
720845
}
846+
847+
testIamPermissions(
848+
permissions: string | string[],
849+
gaxOptions?: CallOptions
850+
): Promise<TestIamPermissionsResponse>;
851+
testIamPermissions(
852+
permissions: string | string[],
853+
callback: TestIamPermissionsCallback
854+
): void;
855+
testIamPermissions(
856+
permissions: string | string[],
857+
gaxOptions: CallOptions,
858+
callback: TestIamPermissionsCallback
859+
): void;
860+
/**
861+
*
862+
* @param {string | string[]} permissions The permission(s) to test for.
863+
* @param {object} [gaxOptions] Request configuration options, outlined
864+
* here: https://googleapis.github.io/gax-nodejs/CallSettings.html.
865+
* @param {function} [callback] The callback function.
866+
* @param {?error} callback.error An error returned while making this request.
867+
* @param {string[]} permissions A subset of permissions that the caller is
868+
* allowed.
869+
*
870+
* @example <caption>include:samples/document-snippets/instance.js</caption>
871+
* region_tag:bigtable_test_instance_Iam_permissions
872+
*/
873+
testIamPermissions(
874+
permissions: string | string[],
875+
gaxOptionsOrCallback?: CallOptions | TestIamPermissionsCallback,
876+
callback?: TestIamPermissionsCallback
877+
): void | Promise<TestIamPermissionsResponse> {
878+
const gaxOptions =
879+
typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {};
880+
callback =
881+
typeof gaxOptionsOrCallback === 'function'
882+
? gaxOptionsOrCallback
883+
: callback!;
884+
885+
const reqOpts: any = {
886+
resource: this.name,
887+
permissions: arrify(permissions),
888+
};
889+
890+
this.bigtable.request(
891+
{
892+
client: 'BigtableInstanceAdminClient',
893+
method: 'testIamPermissions',
894+
reqOpts,
895+
gaxOpts: gaxOptions,
896+
},
897+
(err, resp) => {
898+
if (err) {
899+
callback!(err);
900+
return;
901+
}
902+
callback!(null, resp.permissions);
903+
}
904+
);
905+
}
721906
}
722907

723908
/**

0 commit comments

Comments
 (0)