diff --git a/.github/workflows/secret-manager.yaml b/.github/workflows/secret-manager.yaml new file mode 100644 index 0000000000..e4838f3af5 --- /dev/null +++ b/.github/workflows/secret-manager.yaml @@ -0,0 +1,68 @@ +name: secret-manager +on: + push: + branches: + - main + paths: + - 'secret-manager/**' + pull_request: + paths: + - 'secret-manager/**' + pull_request_target: + types: [labeled] + paths: + - 'secret-manager/**' + schedule: + - cron: '0 0 * * 0' +jobs: + test: + if: ${{ github.event.action != 'labeled' || github.event.label.name == 'actions:force-run' }} + runs-on: ubuntu-latest + timeout-minutes: 60 + permissions: + contents: 'write' + pull-requests: 'write' + id-token: 'write' + steps: + - uses: actions/checkout@v3.1.0 + with: + ref: ${{github.event.pull_request.head.sha}} + - uses: 'google-github-actions/auth@v1.0.0' + with: + workload_identity_provider: 'projects/1046198160504/locations/global/workloadIdentityPools/github-actions-pool/providers/github-actions-provider' + service_account: 'kokoro-system-test@long-door-651.iam.gserviceaccount.com' + create_credentials_file: 'true' + access_token_lifetime: 600s + - uses: actions/setup-node@v3.5.1 + with: + node-version: 16 + - run: npm install + working-directory: secret-manager + - run: npm test + working-directory: secret-manager + env: + MOCHA_REPORTER_SUITENAME: secret_manager + MOCHA_REPORTER_OUTPUT: secret_manager_sponge_log.xml + MOCHA_REPORTER: xunit + - if: ${{ github.event.action == 'labeled' && github.event.label.name == 'actions:force-run' }} + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + try { + await github.rest.issues.removeLabel({ + name: 'actions:force-run', + owner: 'GoogleCloudPlatform', + repo: 'nodejs-docs-samples', + issue_number: context.payload.pull_request.number + }); + } catch (e) { + if (!e.message.includes('Label does not exist')) { + throw e; + } + } + - if: ${{ github.event_name == 'schedule'}} + run: | + curl https://github.com/googleapis/repo-automation-bots/releases/download/flakybot-1.1.0/flakybot -o flakybot -s -L + chmod +x ./flakybot + ./flakybot --repo GoogleCloudPlatform/nodejs-docs-samples --commit_hash ${{github.sha}} --build_url https://github.com/${{github.repository}}/actions/runs/${{github.run_id}} diff --git a/.github/workflows/workflows.json b/.github/workflows/workflows.json index fa274e2139..93d89889a6 100644 --- a/.github/workflows/workflows.json +++ b/.github/workflows/workflows.json @@ -59,6 +59,7 @@ "datastore/functions", "service-directory/snippets", "scheduler", + "secret-manager", "speech", "talent", "texttospeech", diff --git a/secret-manager/accessSecretVersion.js b/secret-manager/accessSecretVersion.js new file mode 100644 index 0000000000..925918482b --- /dev/null +++ b/secret-manager/accessSecretVersion.js @@ -0,0 +1,49 @@ +// Copyright 2019 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/versions/1') { + // [START secretmanager_access_secret_version] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const name = 'projects/my-project/secrets/my-secret/versions/5'; + // const name = 'projects/my-project/secrets/my-secret/versions/latest'; + + // Imports the Secret Manager library + const {SecretManagerServiceClient} = require('@google-cloud/secret-manager'); + + // Instantiates a client + const client = new SecretManagerServiceClient(); + + async function accessSecretVersion() { + const [version] = await client.accessSecretVersion({ + name: name, + }); + + // Extract the payload as a string. + const payload = version.payload.data.toString(); + + // WARNING: Do not print the secret in a production environment - this + // snippet is showing how to access the secret material. + console.info(`Payload: ${payload}`); + } + + accessSecretVersion(); + // [END secretmanager_access_secret_version] +} + +const args = process.argv.slice(2); +main(...args).catch(console.error); diff --git a/secret-manager/addSecretVersion.js b/secret-manager/addSecretVersion.js new file mode 100644 index 0000000000..f3077d5e1c --- /dev/null +++ b/secret-manager/addSecretVersion.js @@ -0,0 +1,49 @@ +// Copyright 2019 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(parent = 'projects/my-project/secrets/my-secret') { + // [START secretmanager_add_secret_version] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const parent = 'projects/my-project/secrets/my-secret'; + + // Imports the Secret Manager library + const {SecretManagerServiceClient} = require('@google-cloud/secret-manager'); + + // Instantiates a client + const client = new SecretManagerServiceClient(); + + // Payload is the plaintext data to store in the secret + const payload = Buffer.from('my super secret data', 'utf8'); + + async function addSecretVersion() { + const [version] = await client.addSecretVersion({ + parent: parent, + payload: { + data: payload, + }, + }); + + console.log(`Added secret version ${version.name}`); + } + + addSecretVersion(); + // [END secretmanager_add_secret_version] +} + +const args = process.argv.slice(2); +main(...args).catch(console.error); diff --git a/secret-manager/createSecret.js b/secret-manager/createSecret.js new file mode 100644 index 0000000000..939462104b --- /dev/null +++ b/secret-manager/createSecret.js @@ -0,0 +1,50 @@ +// Copyright 2019 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(parent = 'projects/my-project', secretId = 'my-secret') { + // [START secretmanager_create_secret] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const parent = 'projects/my-project'; + // const secretId = 'my-secret'; + + // Imports the Secret Manager library + const {SecretManagerServiceClient} = require('@google-cloud/secret-manager'); + + // Instantiates a client + const client = new SecretManagerServiceClient(); + + async function createSecret() { + const [secret] = await client.createSecret({ + parent: parent, + secretId: secretId, + secret: { + replication: { + automatic: {}, + }, + }, + }); + + console.log(`Created secret ${secret.name}`); + } + + createSecret(); + // [END secretmanager_create_secret] +} + +const args = process.argv.slice(2); +main(...args).catch(console.error); diff --git a/secret-manager/createUmmrSecret.js b/secret-manager/createUmmrSecret.js new file mode 100644 index 0000000000..f6aaa8c873 --- /dev/null +++ b/secret-manager/createUmmrSecret.js @@ -0,0 +1,57 @@ +// Copyright 2022 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( + parent = 'projects/my-project', + secretId = 'my-secret', + ...locations +) { + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const parent = 'projects/my-project'; + // const secretId = 'my-secret'; + // const locations = ['us-east1', 'us-east4', 'us-west1']; + + // Imports the Secret Manager library + const {SecretManagerServiceClient} = require('@google-cloud/secret-manager'); + + // Instantiates a client + const client = new SecretManagerServiceClient(); + + async function createSecret() { + const [secret] = await client.createSecret({ + parent: parent, + secretId: secretId, + secret: { + replication: { + userManaged: { + replicas: locations.map(x => { + return {location: x}; + }), + }, + }, + }, + }); + + console.log(`Created secret ${secret.name}`); + } + + createSecret(); +} + +const args = process.argv.slice(2); +main(...args).catch(console.error); diff --git a/secret-manager/deleteSecret.js b/secret-manager/deleteSecret.js new file mode 100644 index 0000000000..3aad7ceb51 --- /dev/null +++ b/secret-manager/deleteSecret.js @@ -0,0 +1,43 @@ +// Copyright 2019 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') { + // [START secretmanager_delete_secret] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const name = 'projects/my-project/secrets/my-secret'; + + // Imports the Secret Manager library + const {SecretManagerServiceClient} = require('@google-cloud/secret-manager'); + + // Instantiates a client + const client = new SecretManagerServiceClient(); + + async function deleteSecret() { + await client.deleteSecret({ + name: name, + }); + + console.log(`Deleted secret ${name}`); + } + + deleteSecret(); + // [END secretmanager_delete_secret] +} + +const args = process.argv.slice(2); +main(...args).catch(console.error); diff --git a/secret-manager/destroySecretVersion.js b/secret-manager/destroySecretVersion.js new file mode 100644 index 0000000000..ca6b832155 --- /dev/null +++ b/secret-manager/destroySecretVersion.js @@ -0,0 +1,43 @@ +// Copyright 2019 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/versions/1') { + // [START secretmanager_destroy_secret_version] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const name = 'projects/my-project/secrets/my-secret/versions/5'; + + // Imports the Secret Manager library + const {SecretManagerServiceClient} = require('@google-cloud/secret-manager'); + + // Instantiates a client + const client = new SecretManagerServiceClient(); + + async function destroySecretVersion() { + const [version] = await client.destroySecretVersion({ + name: name, + }); + + console.info(`Destroyed ${version.name}`); + } + + destroySecretVersion(); + // [END secretmanager_destroy_secret_version] +} + +const args = process.argv.slice(2); +main(...args).catch(console.error); diff --git a/secret-manager/disableSecretVersion.js b/secret-manager/disableSecretVersion.js new file mode 100644 index 0000000000..f072a94405 --- /dev/null +++ b/secret-manager/disableSecretVersion.js @@ -0,0 +1,43 @@ +// Copyright 2019 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/versions/1') { + // [START secretmanager_disable_secret_version] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const name = 'projects/my-project/secrets/my-secret/versions/5'; + + // Imports the Secret Manager library + const {SecretManagerServiceClient} = require('@google-cloud/secret-manager'); + + // Instantiates a client + const client = new SecretManagerServiceClient(); + + async function disableSecretVersion() { + const [version] = await client.disableSecretVersion({ + name: name, + }); + + console.info(`Disabled ${version.name}`); + } + + disableSecretVersion(); + // [END secretmanager_disable_secret_version] +} + +const args = process.argv.slice(2); +main(...args).catch(console.error); diff --git a/secret-manager/enableSecretVersion.js b/secret-manager/enableSecretVersion.js new file mode 100644 index 0000000000..1fdfdb57b0 --- /dev/null +++ b/secret-manager/enableSecretVersion.js @@ -0,0 +1,43 @@ +// Copyright 2019 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/versions/1') { + // [START secretmanager_enable_secret_version] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const name = 'projects/my-project/secrets/my-secret/versions/5'; + + // Imports the Secret Manager library + const {SecretManagerServiceClient} = require('@google-cloud/secret-manager'); + + // Instantiates a client + const client = new SecretManagerServiceClient(); + + async function enableSecretVersion() { + const [version] = await client.enableSecretVersion({ + name: name, + }); + + console.info(`Enabled ${version.name}`); + } + + enableSecretVersion(); + // [END secretmanager_enable_secret_version] +} + +const args = process.argv.slice(2); +main(...args).catch(console.error); diff --git a/secret-manager/getSecret.js b/secret-manager/getSecret.js new file mode 100644 index 0000000000..55b1acd6a4 --- /dev/null +++ b/secret-manager/getSecret.js @@ -0,0 +1,45 @@ +// Copyright 2019 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') { + // [START secretmanager_get_secret] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const name = 'projects/my-project/secrets/my-secret'; + + // Imports the Secret Manager library + const {SecretManagerServiceClient} = require('@google-cloud/secret-manager'); + + // Instantiates a client + const client = new SecretManagerServiceClient(); + + async function getSecret() { + const [secret] = await client.getSecret({ + name: name, + }); + + const policy = secret.replication.replication; + + console.info(`Found secret ${secret.name} (${policy})`); + } + + getSecret(); + // [END secretmanager_get_secret] +} + +const args = process.argv.slice(2); +main(...args).catch(console.error); diff --git a/secret-manager/getSecretVersion.js b/secret-manager/getSecretVersion.js new file mode 100644 index 0000000000..4cb6a247cd --- /dev/null +++ b/secret-manager/getSecretVersion.js @@ -0,0 +1,44 @@ +// Copyright 2019 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/versions/1') { + // [START secretmanager_get_secret_version] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const name = 'projects/my-project/secrets/my-secret/versions/5'; + // const name = 'projects/my-project/secrets/my-secret/versions/latest'; + + // Imports the Secret Manager library + const {SecretManagerServiceClient} = require('@google-cloud/secret-manager'); + + // Instantiates a client + const client = new SecretManagerServiceClient(); + + async function getSecretVersion() { + const [version] = await client.getSecretVersion({ + name: name, + }); + + console.info(`Found secret ${version.name} with state ${version.state}`); + } + + getSecretVersion(); + // [END secretmanager_get_secret_version] +} + +const args = process.argv.slice(2); +main(...args).catch(console.error); 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/listSecretVersions.js b/secret-manager/listSecretVersions.js new file mode 100644 index 0000000000..deec4f8a85 --- /dev/null +++ b/secret-manager/listSecretVersions.js @@ -0,0 +1,45 @@ +// Copyright 2019 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(parent = 'projects/my-project/secrets/my-secret') { + // [START secretmanager_list_secret_versions] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const parent = 'projects/my-project/secrets/my-secret'; + + // Imports the Secret Manager library + const {SecretManagerServiceClient} = require('@google-cloud/secret-manager'); + + // Instantiates a client + const client = new SecretManagerServiceClient(); + + async function listSecretVersions() { + const [versions] = await client.listSecretVersions({ + parent: parent, + }); + + versions.forEach(version => { + console.log(`${version.name}: ${version.state}`); + }); + } + + listSecretVersions(); + // [END secretmanager_list_secret_versions] +} + +const args = process.argv.slice(2); +main(...args).catch(console.error); diff --git a/secret-manager/listSecrets.js b/secret-manager/listSecrets.js new file mode 100644 index 0000000000..b36da6c14f --- /dev/null +++ b/secret-manager/listSecrets.js @@ -0,0 +1,48 @@ +// Copyright 2019 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(parent = 'projects/my-project') { + // [START secretmanager_list_secrets] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const parent = 'projects/my-project'; + + // Imports the Secret Manager library + const {SecretManagerServiceClient} = require('@google-cloud/secret-manager'); + + // Instantiates a client + const client = new SecretManagerServiceClient(); + + async function listSecrets() { + const [secrets] = await client.listSecrets({ + parent: parent, + }); + + secrets.forEach(secret => { + const policy = secret.replication.userManaged + ? secret.replication.userManaged + : secret.replication.automatic; + console.log(`${secret.name} (${policy})`); + }); + } + + listSecrets(); + // [END secretmanager_list_secrets] +} + +const args = process.argv.slice(2); +main(...args).catch(console.error); diff --git a/secret-manager/package.json b/secret-manager/package.json new file mode 100644 index 0000000000..84a1101323 --- /dev/null +++ b/secret-manager/package.json @@ -0,0 +1,25 @@ +{ + "name": "nodejs-secret-manager-samples", + "private": true, + "license": "Apache-2.0", + "files": [ + "*.js" + ], + "author": "Google LLC", + "repository": "googleapis/nodejs-secret-manager", + "engines": { + "node": ">=12.0.0" + }, + "scripts": { + "test": "c8 mocha --recursive test/ --timeout=800000" + }, + "dependencies": { + "@google-cloud/secret-manager": "^4.1.4" + }, + "devDependencies": { + "c8": "^7.0.0", + "chai": "^4.2.0", + "mocha": "^8.0.0", + "uuid": "^9.0.0" + } +} \ No newline at end of file diff --git a/secret-manager/quickstart.js b/secret-manager/quickstart.js new file mode 100644 index 0000000000..c6b7cef59d --- /dev/null +++ b/secret-manager/quickstart.js @@ -0,0 +1,72 @@ +// Copyright 2019 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( + parent = 'projects/my-project', // Project for which to manage secrets. + secretId = 'foo', // Secret ID. + payload = 'hello world!' // String or buffer source data. +) { + // [START secretmanager_quickstart] + // Import the Secret Manager client and instantiate it: + const {SecretManagerServiceClient} = require('@google-cloud/secret-manager'); + const client = new SecretManagerServiceClient(); + + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // parent = 'projects/my-project', // Project for which to manage secrets. + // secretId = 'foo', // Secret ID. + // payload = 'hello world!' // String source data. + + async function createAndAccessSecret() { + // Create the secret with automation replication. + const [secret] = await client.createSecret({ + parent: parent, + secret: { + name: secretId, + replication: { + automatic: {}, + }, + }, + secretId, + }); + + console.info(`Created secret ${secret.name}`); + + // Add a version with a payload onto the secret. + const [version] = await client.addSecretVersion({ + parent: secret.name, + payload: { + data: Buffer.from(payload, 'utf8'), + }, + }); + + console.info(`Added secret version ${version.name}`); + + // Access the secret. + const [accessResponse] = await client.accessSecretVersion({ + name: version.name, + }); + + const responsePayload = accessResponse.payload.data.toString('utf8'); + console.info(`Payload: ${responsePayload}`); + } + createAndAccessSecret(); + // [END secretmanager_quickstart] +} + +const args = process.argv.slice(2); +main(...args).catch(console.error); diff --git a/secret-manager/test/.eslintrc.yml b/secret-manager/test/.eslintrc.yml new file mode 100644 index 0000000000..e28757c0a5 --- /dev/null +++ b/secret-manager/test/.eslintrc.yml @@ -0,0 +1,3 @@ +--- +env: + mocha: true \ No newline at end of file diff --git a/secret-manager/test/secretmanager.test.js b/secret-manager/test/secretmanager.test.js new file mode 100644 index 0000000000..6a2f8444cd --- /dev/null +++ b/secret-manager/test/secretmanager.test.js @@ -0,0 +1,192 @@ +// Copyright 2019 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'; + +const {assert} = require('chai'); +const cp = require('child_process'); +const {v4} = require('uuid'); + +const {SecretManagerServiceClient} = require('@google-cloud/secret-manager'); +const client = new SecretManagerServiceClient(); + +const projectId = process.env.GCLOUD_PROJECT; +const secretId = v4(); +const payload = 'my super secret data'; +const iamUser = 'user:sethvargo@google.com'; + +let secret; +let version; + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +describe('Secret Manager samples', () => { + before(async () => { + [secret] = await client.createSecret({ + parent: `projects/${projectId}`, + secretId: secretId, + secret: { + replication: { + automatic: {}, + }, + }, + }); + + [version] = await client.addSecretVersion({ + parent: secret.name, + payload: { + data: Buffer.from(payload), + }, + }); + }); + + after(async () => { + try { + await client.deleteSecret({ + name: secret.name, + }); + } catch (err) { + if (!err.message.includes('NOT_FOUND')) { + throw err; + } + } + + try { + await client.deleteSecret({ + name: `${secret.name}-quickstart`, + }); + } catch (err) { + if (!err.message.includes('NOT_FOUND')) { + throw err; + } + } + + try { + await client.deleteSecret({ + name: `${secret.name}-2`, + }); + } catch (err) { + if (!err.message.includes('NOT_FOUND')) { + throw err; + } + } + + try { + await client.deleteSecret({ + name: `${secret.name}-3`, + }); + } catch (err) { + if (!err.message.includes('NOT_FOUND')) { + throw err; + } + } + }); + + it('runs the quickstart', async () => { + const stdout = execSync( + `node quickstart.js projects/${projectId} ${secretId}-quickstart bar` + ); + assert.match(stdout, new RegExp('Created secret')); + assert.match(stdout, new RegExp('Added secret version')); + assert.match(stdout, new RegExp('Payload: bar')); + }); + + it('creates a secret', async () => { + const output = execSync( + `node createSecret.js projects/${projectId} ${secretId}-2` + ); + assert.match(output, new RegExp('Created secret')); + }); + + it('creates a secret with userManaged replication', async () => { + const output = execSync( + `node createUmmrSecret.js projects/${projectId} ${secretId}-3 us-east1 us-east4` + ); + assert.match(output, new RegExp('Created secret')); + }); + + it('lists secrets', async () => { + const output = execSync(`node listSecrets.js projects/${projectId}`); + assert.match(output, new RegExp(`${secret.name}`)); + }); + + it('gets a secret', async () => { + const output = execSync(`node getSecret.js ${secret.name}`); + assert.match(output, new RegExp(`Found secret ${secret.name}`)); + }); + + it('updates a secret', async () => { + const output = execSync(`node updateSecret.js ${secret.name}`); + assert.match(output, new RegExp(`Updated secret ${secret.name}`)); + }); + + it('updates a secret with an alias', async () => { + const output = execSync(`node updateSecretWithAlias.js ${secret.name}`); + assert.match(output, new RegExp(`Updated secret ${secret.name}`)); + }); + + it('deletes a secret', async () => { + const output = execSync( + `node deleteSecret.js projects/${projectId}/secrets/${secretId}-2` + ); + assert.match(output, new RegExp('Deleted secret')); + }); + + it('accesses secret versions', async () => { + const output = execSync(`node accessSecretVersion.js ${version.name}`); + assert.match(output, new RegExp(payload)); + }); + + it('adds secret versions', async () => { + const output = execSync(`node addSecretVersion.js ${secret.name}`); + assert.match(output, new RegExp('Added secret version')); + }); + + it('list secret versions', async () => { + const output = execSync(`node listSecretVersions.js ${secret.name}`); + assert.match(output, new RegExp(`${version.name}`)); + }); + + 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}`)); + }); + + it('disables secret versions', async () => { + const output = execSync(`node disableSecretVersion.js ${version.name}`); + assert.match(output, new RegExp(`Disabled ${version.name}`)); + }); + + it('enables secret versions', async () => { + const output = execSync(`node enableSecretVersion.js ${version.name}`); + assert.match(output, new RegExp(`Enabled ${version.name}`)); + }); + + it('destroys secret versions', async () => { + const output = execSync(`node destroySecretVersion.js ${version.name}`); + assert.match(output, new RegExp(`Destroyed ${version.name}`)); + }); +}); diff --git a/secret-manager/updateSecret.js b/secret-manager/updateSecret.js new file mode 100644 index 0000000000..6f55048809 --- /dev/null +++ b/secret-manager/updateSecret.js @@ -0,0 +1,51 @@ +// Copyright 2019 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') { + // [START secretmanager_update_secret] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const name = 'projects/my-project/secrets/my-secret'; + + // Imports the Secret Manager library + const {SecretManagerServiceClient} = require('@google-cloud/secret-manager'); + + // Instantiates a client + const client = new SecretManagerServiceClient(); + + async function updateSecret() { + const [secret] = await client.updateSecret({ + secret: { + name: name, + labels: { + secretmanager: 'rocks', + }, + }, + updateMask: { + paths: ['labels'], + }, + }); + + console.info(`Updated secret ${secret.name}`); + } + + updateSecret(); + // [END secretmanager_update_secret] +} + +const args = process.argv.slice(2); +main(...args).catch(console.error); diff --git a/secret-manager/updateSecretWithAlias.js b/secret-manager/updateSecretWithAlias.js new file mode 100644 index 0000000000..7f96aa4f7c --- /dev/null +++ b/secret-manager/updateSecretWithAlias.js @@ -0,0 +1,51 @@ +// Copyright 2022 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') { + // [START secretmanager_update_secret_with_alias] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const name = 'projects/my-project/secrets/my-secret'; + + // Imports the Secret Manager library + const {SecretManagerServiceClient} = require('@google-cloud/secret-manager'); + + // Instantiates a client + const client = new SecretManagerServiceClient(); + + async function updateSecret() { + const [secret] = await client.updateSecret({ + secret: { + name: name, + versionAliases: { + test: 1, + }, + }, + updateMask: { + paths: ['version_aliases'], + }, + }); + + console.info(`Updated secret ${secret.name}`); + } + + updateSecret(); + // [END secretmanager_update_secret_with_alias] +} + +const args = process.argv.slice(2); +main(...args).catch(console.error);