From 4a15284408c44b7646ec5e049a271fb1116d40df Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Wed, 29 Jan 2020 20:11:05 -0500 Subject: [PATCH] feat: add IAM samples (#34) --- secret-manager/iamGrantAccess.js | 63 ++++++++++++++++++++ secret-manager/iamRevokeAccess.js | 70 +++++++++++++++++++++++ secret-manager/test/secretmanager.test.js | 15 ++++- 3 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 secret-manager/iamGrantAccess.js create mode 100644 secret-manager/iamRevokeAccess.js diff --git a/secret-manager/iamGrantAccess.js b/secret-manager/iamGrantAccess.js new file mode 100644 index 0000000000..630c80b6c6 --- /dev/null +++ b/secret-manager/iamGrantAccess.js @@ -0,0 +1,63 @@ +// Copyright 2020 Google LLC +// +// 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 +// +// https://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. + +'use strict'; + +async function main( + name = 'projects/my-project/secrets/my-secret', + member = 'user:you@example.com' +) { + // [START secretmanager_iam_grant_access] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const name = 'projects/my-project/secrets/my-secret'; + // const member = 'user:you@example.com'; + // + // NOTE: Each member must be prefixed with its type. See the IAM documentation + // for more information: https://cloud.google.com/iam/docs/overview. + + // Imports the Secret Manager library + const {SecretManagerServiceClient} = require('@google-cloud/secret-manager'); + + // Instantiates a client + const client = new SecretManagerServiceClient(); + + async function grantAccess() { + // Get the current IAM policy. + const [policy] = await client.getIamPolicy({ + resource: name, + }); + + // Add the user with accessor permissions to the bindings list. + policy.bindings.push({ + role: 'roles/secretmanager.secretAccessor', + members: [member], + }); + + // Save the updated IAM policy. + await client.setIamPolicy({ + resource: name, + policy: policy, + }); + + console.log(`Updated IAM policy for ${name}`); + } + + grantAccess(); + // [END secretmanager_iam_grant_access] +} + +const args = process.argv.slice(2); +main(...args).catch(console.error); diff --git a/secret-manager/iamRevokeAccess.js b/secret-manager/iamRevokeAccess.js new file mode 100644 index 0000000000..457ea45e00 --- /dev/null +++ b/secret-manager/iamRevokeAccess.js @@ -0,0 +1,70 @@ +// Copyright 2020 Google LLC +// +// 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 +// +// https://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. + +'use strict'; + +async function main( + name = 'projects/my-project/secrets/my-secret', + member = 'user:you@example.com' +) { + // [START secretmanager_iam_revoke_access] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const name = 'projects/my-project/secrets/my-secret'; + // const member = 'user:you@example.com'; + // + // NOTE: Each member must be prefixed with its type. See the IAM documentation + // for more information: https://cloud.google.com/iam/docs/overview. + + // Imports the Secret Manager library + const {SecretManagerServiceClient} = require('@google-cloud/secret-manager'); + + // Instantiates a client + const client = new SecretManagerServiceClient(); + + async function grantAccess() { + // Get the current IAM policy. + const [policy] = await client.getIamPolicy({ + resource: name, + }); + + // Build a new list of policy bindings with the user excluded. + for (const i in policy.bindings) { + const binding = policy.bindings[i]; + if (binding.role !== 'roles/secretmanager.secretAccessor') { + continue; + } + + const idx = binding.members.indexOf(member); + if (idx !== -1) { + binding.members.splice(idx, 1); + } + } + + // Save the updated IAM policy. + await client.setIamPolicy({ + resource: name, + policy: policy, + }); + + console.log(`Updated IAM policy for ${name}`); + } + + grantAccess(); + // [END secretmanager_iam_revoke_access] +} + +const args = process.argv.slice(2); +main(...args).catch(console.error); diff --git a/secret-manager/test/secretmanager.test.js b/secret-manager/test/secretmanager.test.js index 44087fcfe8..476eccb8b6 100644 --- a/secret-manager/test/secretmanager.test.js +++ b/secret-manager/test/secretmanager.test.js @@ -23,7 +23,8 @@ const client = new SecretManagerServiceClient(); const projectId = process.env.GCLOUD_PROJECT; const secretId = uuidv4(); -const payload = `my super secret data`; +const payload = 'my super secret data'; +const iamUser = 'user:sethvargo@google.com'; let secret; let version; @@ -136,6 +137,18 @@ describe(`Secret Manager samples`, () => { }); it(`gets secret versions`, async () => { + const output = execSync(`node iamGrantAccess.js ${secret.name} ${iamUser}`); + assert.match(output, new RegExp(`Updated IAM policy`)); + }); + + it(`revokes access permissions`, async () => { + const output = execSync( + `node iamRevokeAccess.js ${secret.name} ${iamUser}` + ); + assert.match(output, new RegExp(`Updated IAM policy`)); + }); + + it(`grants access permissions`, async () => { const output = execSync(`node getSecretVersion.js ${version.name}`); assert.match(output, new RegExp(`Found secret ${version.name}`)); });