Skip to content

pubsub: implemented iam methods #767

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 14, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
235 changes: 235 additions & 0 deletions lib/pubsub/iam.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
/*!
* Copyright 2014 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/*!
* @module pubsub/iam
*/

'use strict';

var is = require('is');
var arrify = require('arrify');

/*! Developer Documentation
*
* @param {module:pubsub} pubsub - PubSub Object
* @param {string} resource - topic or subscription name
*/
/**
* [IAM (Identity and Access Management)](https://cloud.google.com/pubsub/access_control)
* allows you to set permissions on invidual resources and offers a wider range
* of roles: editor, owner, publisher, subscriber, and viewer. This gives you
* greater flexibility and allows you to set more fine-grained access control.
*
* For example:
* * Grant access on a per-topic or per-subscription basis, rather than for
* the whole Cloud project.
* * Grant access with limited capabilities, such as to only publish messages
* to a topic, or to only to consume messages from a subscription, but not
* to delete the topic or subscription.
*
*
* *The IAM access control features described in this document are Beta,
* including the API methods to get and set IAM policies, and to test IAM
* permissions. Google Cloud Pub/Sub's use of IAM features is not covered by any
* SLA or deprecation policy, and may be subject to backward-incompatible
* changes.*
*
* @constructor
* @alias module:pubsub/iam
*
* @resource [Access Control Overview]{@link https://cloud.google.com/pubsub/access_control}
* @resource [What is Cloud IAM?]{@link https://cloud.google.com/iam/}
*
* @example
* var pubsub = gcloud.pubsub({
* projectId: 'grape-spaceship-123',
* keyFilename: '/path/to/keyfile.json'
* });
*
* var topic = pubsub.topic('my-topic');
* // topic.iam
*
* var subscription = pubsub.subscription('my-subscription');
* // subscription.iam
*/
function IAM(pubsub, resource) {
this.resource = resource;
this.makeReq_ = pubsub.makeReq_.bind(pubsub);
}

/**
* Get the IAM policy
*
* @param {function} callback - The callback function.
* @param {?error} callback.err - An error returned while making this request.
* @param {object} callback.policy - The [policy](https://cloud.google.com/pubsub/reference/rest/Shared.Types/Policy).
* @param {object} callback.apiResponse - The full API response.
*
* @alias iam.getPolicy
*
* @resource [Topics: getIamPolicy API Documentation]{@link https://cloud.google.com/pubsub/reference/rest/v1/projects.topics/getIamPolicy}
* @resource [Subscriptions: getIamPolicy API Documentation]{@link https://cloud.google.com/pubsub/reference/rest/v1/projects.subscriptions/getIamPolicy}
*
* @example
* topic.iam.getPolicy(function(err, policy, apiResponse) {});
*
* subscription.iam.getPolicy(function(err, policy, apiResponse) {});
*/
IAM.prototype.getPolicy = function(callback) {
var path = this.resource + ':getIamPolicy';

this.makeReq_('GET', path, null, null, function(err, resp) {
if (err) {
callback(err, null, resp);
return;
}

callback(null, resp, resp);
});
};

/**
* Set the IAM policy
*
* @throws {Error} If no policy is provided.
*
* @param {object} policy - The [policy](https://cloud.google.com/pubsub/reference/rest/Shared.Types/Policy).
* @param {array=} policy.bindings - Bindings associate members with roles.
* @param {object[]=} policy.rules - Rules to be applied to the policy.
* @param {string=} policy.etag - Etags are used to perform a read-modify-write.
* @param {function} callback - The callback function.
* @param {?error} callback.err - An error returned while making this request.
* @param {object} callback.policy - The updated policy.
* @param {object} callback.apiResponse - The full API response.
*
* @alias iam.setPolicy
*
* @resource [Topics: setIamPolicy API Documentation]{@link https://cloud.google.com/pubsub/reference/rest/v1/projects.topics/setIamPolicy}
* @resource [Subscriptions: setIamPolicy API Documentation]{@link https://cloud.google.com/pubsub/reference/rest/v1/projects.subscriptions/setIamPolicy}
* @resource [Policy]{@link https://cloud.google.com/pubsub/reference/rest/Shared.Types/Policy}
*
* @example
* var myPolicy = {
* bindings: [
* {
* role: 'roles/pubsub.subscriber',
* members: ['serviceAccount:[email protected]']
* }
* ]
* };
*
* topic.iam.setPolicy(myPolicy, function(err, policy, apiResponse) {});
*
* subscription.iam.setPolicy(myPolicy, function(err, policy, apiResponse) {});
*/
IAM.prototype.setPolicy = function(policy, callback) {
if (!is.object(policy)) {
throw new Error('A policy is required');
}

var path = this.resource + ':setIamPolicy';
var body = {
policy: policy
};

this.makeReq_('POST', path, null, body, function(err, resp) {
if (err) {
callback(err, null, resp);
return;
}

callback(null, resp, resp);
});
};

/**
* Test a set of permissions for a resource.
*
* Permissions with wildcards such as `*` or `storage.*` are not allowed.
*
* @throws {Error} If permissions are not provided.
*
* @param {string|string[]} permissions - The permission(s) to test for.
* @param {function} callback - The callback function.
* @param {?error} callback.err - An error returned while making this request.
* @param {array} callback.permissions - A subset of permissions that the caller
* is allowed
* @param {object} callback.apiResponse - The full API response.
*
* @alias iam.testPermissions
*
* @resource [Topics: testIamPermissions API Documentation]{@link https://cloud.google.com/pubsub/reference/rest/v1/projects.topics/testIamPermissions}
* @resource [Subscriptions: testIamPermissions API Documentation]{@link https://cloud.google.com/pubsub/reference/rest/v1/projects.subscriptions/testIamPermissions}
* @resource [Permissions Reference]{@link https://cloud.google.com/pubsub/access_control#permissions}
*
* @example
* //-
* // Test a single permission.
* //-
* var test = 'pubsub.topics.update';
*
* topic.iam.testPermissions(test, function(err, permissions, apiResponse) {
* console.log(permissions);
* // {
* // "pubsub.topics.update": true
* // }
* });
*
* //-
* // Test several permissions at once.
* //-
* var tests = [
* 'pubsub.subscriptions.consume',
* 'pubsub.subscriptions.update'
* ];
*
* subscription.iam.testPermissions(tests, function(err, permissions) {
* console.log(permissions);
* // {
* // "pubsub.subscriptions.consume": true,
* // "pubsub.subscriptions.update": false
* // }
* });
*/
IAM.prototype.testPermissions = function(permissions, callback) {
if (!is.array(permissions) && !is.string(permissions)) {
throw new Error('Permissions are required');
}

var path = this.resource + ':testIamPermissions';
var body = {
permissions: arrify(permissions)
};

this.makeReq_('POST', path, null, body, function(err, resp) {
if (err) {
callback(err, null, resp);
return;
}

var availablePermissions = resp.permissions || [];

var permissionsHash = body.permissions.reduce(function(acc, permission) {
acc[permission] = availablePermissions.indexOf(permission) > -1;
return acc;
}, {});

callback(null, permissionsHash, resp);
});
};

module.exports = IAM;
34 changes: 34 additions & 0 deletions lib/pubsub/subscription.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ var nodeutil = require('util');
*/
var util = require('../common/util.js');

/**
* @type {module:pubsub/iam}
* @private
*/
var IAM = require('./iam');

/*! Developer Documentation
*
* @param {module:pubsub} pubsub - PubSub object.
Expand Down Expand Up @@ -144,6 +150,34 @@ function Subscription(pubsub, options) {
this.messageListeners = 0;
this.paused = false;

/**
* [IAM (Identity and Access Management)](https://cloud.google.com/pubsub/access_control)
* allows you to set permissions on invidual resources and offers a wider
* range of roles: editor, owner, publisher, subscriber, and viewer. This
* gives you greater flexibility and allows you to set more fine-grained
* access control.
*
* *The IAM access control features described in this document are Beta,
* including the API methods to get and set IAM policies, and to test IAM
* permissions. Google Cloud Pub/Sub's use of IAM features is not covered by
* any SLA or deprecation policy, and may be subject to backward-incompatible
* changes.*
*
* @mixes module:pubsub/iam
*
* @resource [Access Control Overview]{@link https://cloud.google.com/pubsub/access_control}
* @resource [What is Cloud IAM?]{@link https://cloud.google.com/iam/}
*
* @example
* //-
* // Get the IAM policy for your subscription.
* //-
* subscription.iam.getPolicy(function(err, policy) {
* console.log(policy);
* });
*/
this.iam = new IAM(pubsub, this.name);

this.listenForEvents_();
}

Expand Down
34 changes: 34 additions & 0 deletions lib/pubsub/topic.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ var prop = require('propprop');
*/
var util = require('../common/util.js');

/**
* @type {module:pubsub/iam}
* @private
*/
var IAM = require('./iam');

/*! Developer Documentation
*
* @param {module:pubsub} pubsub - PubSub object.
Expand All @@ -56,6 +62,34 @@ function Topic(pubsub, name) {
this.unformattedName = name;

this.makeReq_ = this.pubsub.makeReq_.bind(this.pubsub);

/**
* [IAM (Identity and Access Management)](https://cloud.google.com/pubsub/access_control)
* allows you to set permissions on invidual resources and offers a wider
* range of roles: editor, owner, publisher, subscriber, and viewer. This
* gives you greater flexibility and allows you to set more fine-grained
* access control.
*
* *The IAM access control features described in this document are Beta,
* including the API methods to get and set IAM policies, and to test IAM
* permissions. Google Cloud Pub/Sub's use of IAM features is not covered by
* any SLA or deprecation policy, and may be subject to backward-incompatible
* changes.*
*
* @mixes module:pubsub/iam
*
* @resource [Access Control Overview]{@link https://cloud.google.com/pubsub/access_control}
* @resource [What is Cloud IAM?]{@link https://cloud.google.com/iam/}
*
* @example
* //-
* // Get the IAM policy for your topic.
* //-
* topic.iam.getPolicy(function(err, policy) {
* console.log(policy);
* });
*/
this.iam = new IAM(pubsub, this.name);
}

/**
Expand Down
1 change: 1 addition & 0 deletions scripts/docs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
./node_modules/.bin/dox < lib/pubsub/index.js > docs/json/master/pubsub/index.json &
./node_modules/.bin/dox < lib/pubsub/subscription.js > docs/json/master/pubsub/subscription.json &
./node_modules/.bin/dox < lib/pubsub/topic.js > docs/json/master/pubsub/topic.json &
./node_modules/.bin/dox < lib/pubsub/iam.js > docs/json/master/pubsub/iam.json &

./node_modules/.bin/dox < lib/search/index.js > docs/json/master/search/index.json &
./node_modules/.bin/dox < lib/search/index-class.js > docs/json/master/search/index-class.json &
Expand Down
47 changes: 47 additions & 0 deletions system-test/pubsub.js
Original file line number Diff line number Diff line change
Expand Up @@ -320,4 +320,51 @@ describe('pubsub', function() {
});
});
});

describe('IAM', function() {

it('should get a policy', function(done) {
var topic = pubsub.topic(TOPIC_NAMES[0]);

topic.iam.getPolicy(function(err, policy) {
assert.ifError(err);
assert.deepEqual(policy, { etag: 'ACAB' });
done();
});
});

it('should set a policy', function(done) {
var topic = pubsub.topic(TOPIC_NAMES[0]);
var policy = {
bindings: [{
role: 'roles/pubsub.publisher',
members: ['serviceAccount:[email protected]']
}]
};

topic.iam.setPolicy(policy, function(err, newPolicy) {
assert.ifError(err);
assert.deepEqual(newPolicy.bindings, policy.bindings);
done();
});
});

it('should test the iam permissions', function(done) {
var topic = pubsub.topic(TOPIC_NAMES[0]);
var testPermissions = [
'pubsub.topics.get',
'pubsub.topics.update'
];

topic.iam.testPermissions(testPermissions, function(err, permissions) {
assert.ifError(err);
assert.deepEqual(permissions, {
'pubsub.topics.get': true,
'pubsub.topics.update': true
});
done();
});
});

});
});
Loading