iam.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. "use strict";
  2. // Copyright 2019 Google LLC
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. Object.defineProperty(exports, "__esModule", { value: true });
  16. exports.Iam = exports.IAMExceptionMessages = void 0;
  17. const promisify_1 = require("@google-cloud/promisify");
  18. const util_js_1 = require("./util.js");
  19. var IAMExceptionMessages;
  20. (function (IAMExceptionMessages) {
  21. IAMExceptionMessages["POLICY_OBJECT_REQUIRED"] = "A policy object is required.";
  22. IAMExceptionMessages["PERMISSIONS_REQUIRED"] = "Permissions are required.";
  23. })(IAMExceptionMessages || (exports.IAMExceptionMessages = IAMExceptionMessages = {}));
  24. /**
  25. * Get and set IAM policies for your Cloud Storage bucket.
  26. *
  27. * See {@link https://cloud.google.com/storage/docs/access-control/iam#short_title_iam_management| Cloud Storage IAM Management}
  28. * See {@link https://cloud.google.com/iam/docs/granting-changing-revoking-access| Granting, Changing, and Revoking Access}
  29. * See {@link https://cloud.google.com/iam/docs/understanding-roles| IAM Roles}
  30. *
  31. * @constructor Iam
  32. *
  33. * @param {Bucket} bucket The parent instance.
  34. * @example
  35. * ```
  36. * const {Storage} = require('@google-cloud/storage');
  37. * const storage = new Storage();
  38. * const bucket = storage.bucket('my-bucket');
  39. * // bucket.iam
  40. * ```
  41. */
  42. class Iam {
  43. constructor(bucket) {
  44. this.request_ = bucket.request.bind(bucket);
  45. this.resourceId_ = 'buckets/' + bucket.getId();
  46. }
  47. /**
  48. * @typedef {object} GetPolicyOptions Requested options for IAM#getPolicy().
  49. * @property {number} [requestedPolicyVersion] The version of IAM policies to
  50. * request. If a policy with a condition is requested without setting
  51. * this, the server will return an error. This must be set to a value
  52. * of 3 to retrieve IAM policies containing conditions. This is to
  53. * prevent client code that isn't aware of IAM conditions from
  54. * interpreting and modifying policies incorrectly. The service might
  55. * return a policy with version lower than the one that was requested,
  56. * based on the feature syntax in the policy fetched.
  57. * See {@link https://cloud.google.com/iam/docs/policies#versions| IAM Policy versions}
  58. * @property {string} [userProject] The ID of the project which will be
  59. * billed for the request.
  60. */
  61. /**
  62. * @typedef {array} GetPolicyResponse
  63. * @property {Policy} 0 The policy.
  64. * @property {object} 1 The full API response.
  65. */
  66. /**
  67. * @typedef {object} Policy
  68. * @property {PolicyBinding[]} policy.bindings Bindings associate members with roles.
  69. * @property {string} [policy.etag] Etags are used to perform a read-modify-write.
  70. * @property {number} [policy.version] The syntax schema version of the Policy.
  71. * To set an IAM policy with conditional binding, this field must be set to
  72. * 3 or greater.
  73. * See {@link https://cloud.google.com/iam/docs/policies#versions| IAM Policy versions}
  74. */
  75. /**
  76. * @typedef {object} PolicyBinding
  77. * @property {string} role Role that is assigned to members.
  78. * @property {string[]} members Specifies the identities requesting access for the bucket.
  79. * @property {Expr} [condition] The condition that is associated with this binding.
  80. */
  81. /**
  82. * @typedef {object} Expr
  83. * @property {string} [title] An optional title for the expression, i.e. a
  84. * short string describing its purpose. This can be used e.g. in UIs
  85. * which allow to enter the expression.
  86. * @property {string} [description] An optional description of the
  87. * expression. This is a longer text which describes the expression,
  88. * e.g. when hovered over it in a UI.
  89. * @property {string} expression Textual representation of an expression in
  90. * Common Expression Language syntax. The application context of the
  91. * containing message determines which well-known feature set of CEL
  92. * is supported.The condition that is associated with this binding.
  93. *
  94. * @see [Condition] https://cloud.google.com/storage/docs/access-control/iam#conditions
  95. */
  96. /**
  97. * Get the IAM policy.
  98. *
  99. * @param {GetPolicyOptions} [options] Request options.
  100. * @param {GetPolicyCallback} [callback] Callback function.
  101. * @returns {Promise<GetPolicyResponse>}
  102. *
  103. * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/getIamPolicy| Buckets: setIamPolicy API Documentation}
  104. *
  105. * @example
  106. * ```
  107. * const {Storage} = require('@google-cloud/storage');
  108. * const storage = new Storage();
  109. * const bucket = storage.bucket('my-bucket');
  110. *
  111. * bucket.iam.getPolicy(
  112. * {requestedPolicyVersion: 3},
  113. * function(err, policy, apiResponse) {
  114. *
  115. * },
  116. * );
  117. *
  118. * //-
  119. * // If the callback is omitted, we'll return a Promise.
  120. * //-
  121. * bucket.iam.getPolicy({requestedPolicyVersion: 3})
  122. * .then(function(data) {
  123. * const policy = data[0];
  124. * const apiResponse = data[1];
  125. * });
  126. *
  127. * ```
  128. * @example <caption>include:samples/iam.js</caption>
  129. * region_tag:storage_view_bucket_iam_members
  130. * Example of retrieving a bucket's IAM policy:
  131. */
  132. getPolicy(optionsOrCallback, callback) {
  133. const { options, callback: cb } = (0, util_js_1.normalize)(optionsOrCallback, callback);
  134. const qs = {};
  135. if (options.userProject) {
  136. qs.userProject = options.userProject;
  137. }
  138. if (options.requestedPolicyVersion !== null &&
  139. options.requestedPolicyVersion !== undefined) {
  140. qs.optionsRequestedPolicyVersion = options.requestedPolicyVersion;
  141. }
  142. this.request_({
  143. uri: '/iam',
  144. qs,
  145. }, cb);
  146. }
  147. /**
  148. * Set the IAM policy.
  149. *
  150. * @throws {Error} If no policy is provided.
  151. *
  152. * @param {Policy} policy The policy.
  153. * @param {SetPolicyOptions} [options] Configuration options.
  154. * @param {SetPolicyCallback} callback Callback function.
  155. * @returns {Promise<SetPolicyResponse>}
  156. *
  157. * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/setIamPolicy| Buckets: setIamPolicy API Documentation}
  158. * See {@link https://cloud.google.com/iam/docs/understanding-roles| IAM Roles}
  159. *
  160. * @example
  161. * ```
  162. * const {Storage} = require('@google-cloud/storage');
  163. * const storage = new Storage();
  164. * const bucket = storage.bucket('my-bucket');
  165. *
  166. * const myPolicy = {
  167. * bindings: [
  168. * {
  169. * role: 'roles/storage.admin',
  170. * members:
  171. * ['serviceAccount:myotherproject@appspot.gserviceaccount.com']
  172. * }
  173. * ]
  174. * };
  175. *
  176. * bucket.iam.setPolicy(myPolicy, function(err, policy, apiResponse) {});
  177. *
  178. * //-
  179. * // If the callback is omitted, we'll return a Promise.
  180. * //-
  181. * bucket.iam.setPolicy(myPolicy).then(function(data) {
  182. * const policy = data[0];
  183. * const apiResponse = data[1];
  184. * });
  185. *
  186. * ```
  187. * @example <caption>include:samples/iam.js</caption>
  188. * region_tag:storage_add_bucket_iam_member
  189. * Example of adding to a bucket's IAM policy:
  190. *
  191. * @example <caption>include:samples/iam.js</caption>
  192. * region_tag:storage_remove_bucket_iam_member
  193. * Example of removing from a bucket's IAM policy:
  194. */
  195. setPolicy(policy, optionsOrCallback, callback) {
  196. if (policy === null || typeof policy !== 'object') {
  197. throw new Error(IAMExceptionMessages.POLICY_OBJECT_REQUIRED);
  198. }
  199. const { options, callback: cb } = (0, util_js_1.normalize)(optionsOrCallback, callback);
  200. let maxRetries;
  201. if (policy.etag === undefined) {
  202. maxRetries = 0;
  203. }
  204. this.request_({
  205. method: 'PUT',
  206. uri: '/iam',
  207. maxRetries,
  208. json: Object.assign({
  209. resourceId: this.resourceId_,
  210. }, policy),
  211. qs: options,
  212. }, cb);
  213. }
  214. /**
  215. * Test a set of permissions for a resource.
  216. *
  217. * @throws {Error} If permissions are not provided.
  218. *
  219. * @param {string|string[]} permissions The permission(s) to test for.
  220. * @param {TestIamPermissionsOptions} [options] Configuration object.
  221. * @param {TestIamPermissionsCallback} [callback] Callback function.
  222. * @returns {Promise<TestIamPermissionsResponse>}
  223. *
  224. * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/testIamPermissions| Buckets: testIamPermissions API Documentation}
  225. *
  226. * @example
  227. * ```
  228. * const {Storage} = require('@google-cloud/storage');
  229. * const storage = new Storage();
  230. * const bucket = storage.bucket('my-bucket');
  231. *
  232. * //-
  233. * // Test a single permission.
  234. * //-
  235. * const test = 'storage.buckets.delete';
  236. *
  237. * bucket.iam.testPermissions(test, function(err, permissions, apiResponse) {
  238. * console.log(permissions);
  239. * // {
  240. * // "storage.buckets.delete": true
  241. * // }
  242. * });
  243. *
  244. * //-
  245. * // Test several permissions at once.
  246. * //-
  247. * const tests = [
  248. * 'storage.buckets.delete',
  249. * 'storage.buckets.get'
  250. * ];
  251. *
  252. * bucket.iam.testPermissions(tests, function(err, permissions) {
  253. * console.log(permissions);
  254. * // {
  255. * // "storage.buckets.delete": false,
  256. * // "storage.buckets.get": true
  257. * // }
  258. * });
  259. *
  260. * //-
  261. * // If the callback is omitted, we'll return a Promise.
  262. * //-
  263. * bucket.iam.testPermissions(test).then(function(data) {
  264. * const permissions = data[0];
  265. * const apiResponse = data[1];
  266. * });
  267. * ```
  268. */
  269. testPermissions(permissions, optionsOrCallback, callback) {
  270. if (!Array.isArray(permissions) && typeof permissions !== 'string') {
  271. throw new Error(IAMExceptionMessages.PERMISSIONS_REQUIRED);
  272. }
  273. const { options, callback: cb } = (0, util_js_1.normalize)(optionsOrCallback, callback);
  274. const permissionsArray = Array.isArray(permissions)
  275. ? permissions
  276. : [permissions];
  277. const req = Object.assign({
  278. permissions: permissionsArray,
  279. }, options);
  280. this.request_({
  281. uri: '/iam/testPermissions',
  282. qs: req,
  283. useQuerystring: true,
  284. }, (err, resp) => {
  285. if (err) {
  286. cb(err, null, resp);
  287. return;
  288. }
  289. const availablePermissions = Array.isArray(resp.permissions)
  290. ? resp.permissions
  291. : [];
  292. const permissionsHash = permissionsArray.reduce((acc, permission) => {
  293. acc[permission] = availablePermissions.indexOf(permission) > -1;
  294. return acc;
  295. }, {});
  296. cb(null, permissionsHash, resp);
  297. });
  298. }
  299. }
  300. exports.Iam = Iam;
  301. /*! Developer Documentation
  302. *
  303. * All async methods (except for streams) will return a Promise in the event
  304. * that a callback is omitted.
  305. */
  306. (0, promisify_1.promisifyAll)(Iam);