Skip to content

Commit

Permalink
feat: implement instance and table level IAM policy (#584)
Browse files Browse the repository at this point in the history
* feat: add table level IAM policy controls

* lint: lint

* feat: add instance level IAM policy

* docs: update description

* docs: add document snippets

* lint: lint
  • Loading branch information
AVaksman authored and crwilcox committed Nov 26, 2019
1 parent c5ceaeb commit 5c22968
Show file tree
Hide file tree
Showing 7 changed files with 1,066 additions and 3 deletions.
61 changes: 61 additions & 0 deletions samples/document-snippets/instance.js
Expand Up @@ -204,6 +204,67 @@ const snippets = {
// [END bigtable_get_clusters]
},

getIamPolicy: instanceId => {
// [START bigtable_get_instance_Iam_policy]
const Bigtable = require('@google-cloud/bigtable');
const bigtable = new Bigtable();
const instance = bigtable.instance(instanceId);

instance
.getIamPolicy()
.then(result => {
const policy = result[0];
})
.catch(err => {
// Handle the error.
});
// [END bigtable_get_instance_Iam_policy]
},

setIamPolicy: instanceId => {
// [START bigtable_set_instance_Iam_policy]
const Bigtable = require('@google-cloud/bigtable');
const bigtable = new Bigtable();
const instance = bigtable.instance(instanceId);

const policy = {
bindings: [
{
role: 'roles/bigtable.viewer',
members: ['user:mike@example.com', 'group:admins@example.com'],
},
],
};

instance
.setIamPolicy(policy)
.then(result => {
const setPolicy = result[0];
})
.catch(err => {
// Handle the error
});
// [END bigtable_set_instance_Iam_policy]
},

testIamPermissions: instanceId => {
// [START bigtable_test_instance_Iam_permissions]
const Bigtable = require('@google-cloud/bigtable');
const bigtable = new Bigtable();
const instance = bigtable.instance(instanceId);

const permissions = ['bigtable.tables.get', 'bigtable.tables.readRows'];
instance
.testIamPermissions(permissions)
.then(result => {
const grantedPermissions = result[0];
})
.catch(err => {
// Handle the error
});
// [END bigtable_test_instance_Iam_permissions]
},

getAppProfiles: instanceId => {
// [START bigtable_get_app_profiles]
const Bigtable = require('@google-cloud/bigtable');
Expand Down
64 changes: 64 additions & 0 deletions samples/document-snippets/table.js
Expand Up @@ -295,6 +295,70 @@ const snippets = {
// [END bigtable_sample_row_keys]
},

getIamPolicy: (instanceId, tableId) => {
// [START bigtable_get_table_Iam_policy]
const Bigtable = require('@google-cloud/bigtable');
const bigtable = new Bigtable();
const instance = bigtable.instance(instanceId);
const table = instance.table(tableId);

table
.getIamPolicy()
.then(result => {
const policy = result[0];
})
.catch(err => {
// Handle the error.
});
// [END bigtable_get_table_Iam_policy]
},

setIamPolicy: (instanceId, tableId) => {
// [START bigtable_set_table_Iam_policy]
const Bigtable = require('@google-cloud/bigtable');
const bigtable = new Bigtable();
const instance = bigtable.instance(instanceId);
const table = instance.table(tableId);

const policy = {
bindings: [
{
role: 'roles/bigtable.viewer',
members: ['user:mike@example.com', 'group:admins@example.com'],
},
],
};

table
.setIamPolicy(policy)
.then(result => {
const setPolicy = result[0];
})
.catch(err => {
// Handle the error
});
// [END bigtable_set_table_Iam_policy]
},

testIamPermissions: (instanceId, tableId) => {
// [START bigtable_test_table_Iam_permissions]
const Bigtable = require('@google-cloud/bigtable');
const bigtable = new Bigtable();
const instance = bigtable.instance(instanceId);
const table = instance.table(tableId);

const permissions = ['bigtable.tables.get', 'bigtable.tables.readRows'];
table
.testIamPermissions(permissions)
.then(result => {
const grantedPermissions = result[0];
})
.catch(err => {
// Handle the error
});
// [END bigtable_test_table_Iam_permissions]
},

delRows: (instanceId, tableId) => {
const instance = bigtable.instance(instanceId);
const table = instance.table(tableId);
Expand Down
187 changes: 186 additions & 1 deletion src/instance.ts
Expand Up @@ -16,12 +16,24 @@

import {paginator} from '@google-cloud/paginator';
import {promisifyAll} from '@google-cloud/promisify';
import arrify = require('arrify');
import * as is from 'is';
import snakeCase = require('lodash.snakecase');
import {AppProfile} from './app-profile';
import {Cluster} from './cluster';
import {Family} from './family';
import {Table} from './table';
import {
GetIamPolicyCallback,
GetIamPolicyOptions,
GetIamPolicyResponse,
Policy,
SetIamPolicyCallback,
SetIamPolicyResponse,
Table,
TestIamPermissionsCallback,
TestIamPermissionsResponse,
} from './table';
import {CallOptions} from 'google-gax';

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

getIamPolicy(options?): Promise<[Policy]>;
getIamPolicy(options, callback): void;
/**
* @param {object} [options] Configuration object.
* @param {object} [options.gaxOptions] Request configuration options, outlined
* here: https://googleapis.github.io/gax-nodejs/CallSettings.html.
* @param {number} [options.requestedPolicyVersion] The policy format version
* to be returned. Valid values are 0, 1, and 3. Requests specifying an
* invalid value will be rejected. Requests for policies with any
* conditional bindings must specify version 3. Policies without any
* conditional bindings may specify any valid value or leave the field unset.
* @param {function} [callback] The callback function.
* @param {?error} callback.error An error returned while making this request.
* @param {Policy} policy The policy.
*
* @example <caption>include:samples/document-snippets/instance.js</caption>
* region_tag:bigtable_get_instance_Iam_policy
*/
getIamPolicy(
optionsOrCallback?: GetIamPolicyOptions | GetIamPolicyCallback,
callback?: GetIamPolicyCallback
): void | Promise<GetIamPolicyResponse> {
const options =
typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
callback =
typeof optionsOrCallback === 'function' ? optionsOrCallback : callback!;

const reqOpts: any = {
resource: this.name,
};

if (
options.requestedPolicyVersion !== null &&
options.requestedPolicyVersion !== undefined
) {
reqOpts.options = {
requestedPolicyVersion: options.requestedPolicyVersion,
};
}

this.bigtable.request(
{
client: 'BigtableInstanceAdminClient',
method: 'getIamPolicy',
reqOpts,
gaxOpts: options.gaxOptions,
},
(err, resp) => {
if (err) {
callback!(err);
return;
}
callback!(null, Table.decodePolicyEtag(resp));
}
);
}

/**
* Get the instance metadata.
*
Expand Down Expand Up @@ -650,6 +719,62 @@ Please use the format 'my-instance' or '${bigtable.projectName}/instances/my-ins
);
}

setIamPolicy(
policy: Policy,
gaxOptions?: CallOptions
): Promise<SetIamPolicyResponse>;
setIamPolicy(
policy: Policy,
gaxOptions: CallOptions,
callback: SetIamPolicyCallback
): void;
setIamPolicy(policy: Policy, callback: SetIamPolicyCallback): void;
/**
* @param {object} [gaxOptions] Request configuration options, outlined
* here: https://googleapis.github.io/gax-nodejs/CallSettings.html.
* @param {function} [callback] The callback function.
* @param {?error} callback.error An error returned while making this request.
* @param {Policy} policy The policy.
*
* @example <caption>include:samples/document-snippets/instance.js</caption>
* region_tag:bigtable_set_instance_Iam_policy
*/
setIamPolicy(
policy: Policy,
gaxOptionsOrCallback?: CallOptions | SetIamPolicyCallback,
callback?: SetIamPolicyCallback
): void | Promise<SetIamPolicyResponse> {
const gaxOptions =
typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {};
callback =
typeof gaxOptionsOrCallback === 'function'
? gaxOptionsOrCallback
: callback!;

if (policy.etag !== null && policy.etag !== undefined) {
((policy.etag as {}) as Buffer) = Buffer.from(policy.etag);
}
const reqOpts: any = {
resource: this.name,
policy,
};

this.bigtable.request(
{
client: 'BigtableInstanceAdminClient',
method: 'setIamPolicy',
reqOpts,
gaxOpts: gaxOptions,
},
(err, resp) => {
if (err) {
callback!(err);
}
callback!(null, Table.decodePolicyEtag(resp));
}
);
}

/**
* Set the instance metadata.
*
Expand Down Expand Up @@ -718,6 +843,66 @@ Please use the format 'my-instance' or '${bigtable.projectName}/instances/my-ins
table(id) {
return new Table(this, id);
}

testIamPermissions(
permissions: string | string[],
gaxOptions?: CallOptions
): Promise<TestIamPermissionsResponse>;
testIamPermissions(
permissions: string | string[],
callback: TestIamPermissionsCallback
): void;
testIamPermissions(
permissions: string | string[],
gaxOptions: CallOptions,
callback: TestIamPermissionsCallback
): void;
/**
*
* @param {string | string[]} permissions The permission(s) to test for.
* @param {object} [gaxOptions] Request configuration options, outlined
* here: https://googleapis.github.io/gax-nodejs/CallSettings.html.
* @param {function} [callback] The callback function.
* @param {?error} callback.error An error returned while making this request.
* @param {string[]} permissions A subset of permissions that the caller is
* allowed.
*
* @example <caption>include:samples/document-snippets/instance.js</caption>
* region_tag:bigtable_test_instance_Iam_permissions
*/
testIamPermissions(
permissions: string | string[],
gaxOptionsOrCallback?: CallOptions | TestIamPermissionsCallback,
callback?: TestIamPermissionsCallback
): void | Promise<TestIamPermissionsResponse> {
const gaxOptions =
typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {};
callback =
typeof gaxOptionsOrCallback === 'function'
? gaxOptionsOrCallback
: callback!;

const reqOpts: any = {
resource: this.name,
permissions: arrify(permissions),
};

this.bigtable.request(
{
client: 'BigtableInstanceAdminClient',
method: 'testIamPermissions',
reqOpts,
gaxOpts: gaxOptions,
},
(err, resp) => {
if (err) {
callback!(err);
return;
}
callback!(null, resp.permissions);
}
);
}
}

/**
Expand Down

0 comments on commit 5c22968

Please sign in to comment.