From 9af3f5d82d6704222a6d4fcc06913e8aa4c23ecd Mon Sep 17 00:00:00 2001 From: Rafael Murata Date: Wed, 14 Aug 2024 13:49:59 -0300 Subject: [PATCH] feat: Adding API v2 IAM+Notifications samples (#3717) * feat: Adding API v2 Source Finding sample * feat: Adding API v2 Source Finding Mute sample * improving readability * add workflow scc * add notifications samples * add IAM samples * feat: Adding API v2 IAM Notifications samples * improve lint * trying to get projectId * trying to get projectId v2 * fix security error and remove IAM samples * fix: add missing test topic * fix: ensure topic doesn't exist before trying to create it * chore: update project vars * refactor: clean up async code, catch unhandled promise * refactor: security center project vars * debug: test v1 only * debug: test v2 only * debug: resume testing v1 and v2 * chore: roll up updates for v1 and v2 --------- Co-authored-by: Rafael Rodrigues Co-authored-by: Jennifer Davis Co-authored-by: Adam Ross Co-authored-by: Tony Pujals Co-authored-by: Tony Pujals --- .github/workflows/utils/workflows.json | 3 +- .../system-test/v1/assetSecurityMarks.test.js | 3 +- .../snippets/system-test/v1/findings.test.js | 3 +- .../system-test/v1/listAllAssets.test.js | 5 +- .../v1/listAssetsAndChanges.test.js | 5 +- .../system-test/v1/listAssetsAtTime.test.js | 5 +- .../system-test/v1/listFilteredAssets.test.js | 5 +- .../system-test/v1/notifications.test.js | 3 +- .../system-test/v1/orgSettings.test.js | 3 +- .../system-test/v2/notifications.test.js | 131 ++++++++++++++++++ .../snippets/v2/createNotificationConfig.js | 81 +++++++++++ .../snippets/v2/deleteNotificationConfig.js | 54 ++++++++ .../snippets/v2/getNotificationConfig.js | 54 ++++++++ .../snippets/v2/listNotificationConfigs.js | 50 +++++++ .../snippets/v2/receiveNotifications.js | 66 +++++++++ .../snippets/v2/updateNotificationConfig.js | 81 +++++++++++ 16 files changed, 539 insertions(+), 13 deletions(-) create mode 100644 security-center/snippets/system-test/v2/notifications.test.js create mode 100644 security-center/snippets/v2/createNotificationConfig.js create mode 100644 security-center/snippets/v2/deleteNotificationConfig.js create mode 100644 security-center/snippets/v2/getNotificationConfig.js create mode 100644 security-center/snippets/v2/listNotificationConfigs.js create mode 100644 security-center/snippets/v2/receiveNotifications.js create mode 100644 security-center/snippets/v2/updateNotificationConfig.js diff --git a/.github/workflows/utils/workflows.json b/.github/workflows/utils/workflows.json index ff954978f8..e1448a2028 100644 --- a/.github/workflows/utils/workflows.json +++ b/.github/workflows/utils/workflows.json @@ -94,5 +94,6 @@ "video-intelligence", "vision/productSearch", "workflows", - "workflows/invoke-private-endpoint" + "workflows/invoke-private-endpoint", + "security-center/snippets/v2" ] diff --git a/security-center/snippets/system-test/v1/assetSecurityMarks.test.js b/security-center/snippets/system-test/v1/assetSecurityMarks.test.js index 77c417535f..69c5666aa3 100644 --- a/security-center/snippets/system-test/v1/assetSecurityMarks.test.js +++ b/security-center/snippets/system-test/v1/assetSecurityMarks.test.js @@ -20,7 +20,8 @@ const {describe, it, before} = require('mocha'); const {execSync} = require('child_process'); const exec = cmd => execSync(cmd, {encoding: 'utf8'}); -const organizationId = process.env['GCLOUD_ORGANIZATION']; +// TODO(developers): update for your own environment +const organizationId = '1081635000895'; describe('client with security marks for assets', async () => { let data; diff --git a/security-center/snippets/system-test/v1/findings.test.js b/security-center/snippets/system-test/v1/findings.test.js index 683aae5abb..2ddd9d818d 100644 --- a/security-center/snippets/system-test/v1/findings.test.js +++ b/security-center/snippets/system-test/v1/findings.test.js @@ -20,7 +20,8 @@ const {describe, it, before} = require('mocha'); const {execSync} = require('child_process'); const exec = cmd => execSync(cmd, {encoding: 'utf8'}); -const organizationId = process.env['GCLOUD_ORGANIZATION']; +// TODO(developers): update for your own environment +const organizationId = '1081635000895'; describe('Client with SourcesAndFindings', async () => { let data; diff --git a/security-center/snippets/system-test/v1/listAllAssets.test.js b/security-center/snippets/system-test/v1/listAllAssets.test.js index 516c8c8a84..c929cf27d1 100644 --- a/security-center/snippets/system-test/v1/listAllAssets.test.js +++ b/security-center/snippets/system-test/v1/listAllAssets.test.js @@ -19,11 +19,12 @@ const {describe, it} = require('mocha'); const {execSync} = require('child_process'); const exec = cmd => execSync(cmd, {encoding: 'utf8'}); -const organization_id = process.env['GCLOUD_ORGANIZATION']; +// TODO(developers): update for your own environment +const organizationId = '1081635000895'; describe('listAllAssets', () => { it('should print all assets in org', () => { - const output = exec(`node v1/listAllAssets.js ${organization_id}`); + const output = exec(`node v1/listAllAssets.js ${organizationId}`); assert.isAtLeast(output.match(/\n/g).length + 1, 62); assert.notMatch(output, /undefined/); }); diff --git a/security-center/snippets/system-test/v1/listAssetsAndChanges.test.js b/security-center/snippets/system-test/v1/listAssetsAndChanges.test.js index c8975d9d15..7c54275850 100644 --- a/security-center/snippets/system-test/v1/listAssetsAndChanges.test.js +++ b/security-center/snippets/system-test/v1/listAssetsAndChanges.test.js @@ -19,11 +19,12 @@ const {describe, it} = require('mocha'); const {execSync} = require('child_process'); const exec = cmd => execSync(cmd, {encoding: 'utf8'}); -const organization_id = process.env['GCLOUD_ORGANIZATION']; +// TODO(developers): update for your own environment +const organizationId = '1081635000895'; describe('listAssetsandChanges', () => { it('should print projects with state changes', () => { - const output = exec(`node v1/listAssetsAndChanges.js ${organization_id}`); + const output = exec(`node v1/listAssetsAndChanges.js ${organizationId}`); assert.match(output, /(ADDED|ACTIVE)/); assert.equal(4, output.match(/\n/g).length + 1, '== number of projects'); assert.notMatch(output, /undefined/); diff --git a/security-center/snippets/system-test/v1/listAssetsAtTime.test.js b/security-center/snippets/system-test/v1/listAssetsAtTime.test.js index cad70cb513..949c3c69ab 100644 --- a/security-center/snippets/system-test/v1/listAssetsAtTime.test.js +++ b/security-center/snippets/system-test/v1/listAssetsAtTime.test.js @@ -19,11 +19,12 @@ const {describe, it} = require('mocha'); const {execSync} = require('child_process'); const exec = cmd => execSync(cmd, {encoding: 'utf8'}); -const organization_id = process.env['GCLOUD_ORGANIZATION']; +// TODO(developers): update for your own environment +const organizationId = '1081635000895'; describe('listAssetsAttime', () => { it('should print projects', () => { - const output = exec(`node v1/listAssetsAtTime.js ${organization_id}`); + const output = exec(`node v1/listAssetsAtTime.js ${organizationId}`); assert.equal(4, output.match(/\n/g).length + 1, '== number of projects'); assert.notMatch(output, /undefined/); }); diff --git a/security-center/snippets/system-test/v1/listFilteredAssets.test.js b/security-center/snippets/system-test/v1/listFilteredAssets.test.js index ef544da721..eff6b44ecb 100644 --- a/security-center/snippets/system-test/v1/listFilteredAssets.test.js +++ b/security-center/snippets/system-test/v1/listFilteredAssets.test.js @@ -19,11 +19,12 @@ const {describe, it} = require('mocha'); const {execSync} = require('child_process'); const exec = cmd => execSync(cmd, {encoding: 'utf8'}); -const organization_id = process.env['GCLOUD_ORGANIZATION']; +// TODO(developers): update for your own environment +const organizationId = '1081635000895'; describe('listAllAssets', () => { it('should print all assets in org', () => { - const output = exec(`node v1/listFilteredAssets.js ${organization_id}`); + const output = exec(`node v1/listFilteredAssets.js ${organizationId}`); assert.isAtLeast(4, output.match(/\n/g).length + 1); assert.notMatch(output, /undefined/); }); diff --git a/security-center/snippets/system-test/v1/notifications.test.js b/security-center/snippets/system-test/v1/notifications.test.js index 26e37c5a85..d20e6d0371 100644 --- a/security-center/snippets/system-test/v1/notifications.test.js +++ b/security-center/snippets/system-test/v1/notifications.test.js @@ -21,7 +21,8 @@ const {describe, it, before, after} = require('mocha'); const {execSync} = require('child_process'); const exec = cmd => execSync(cmd, {encoding: 'utf8'}); -const organizationId = process.env['GCLOUD_ORGANIZATION']; +// TODO(developers): update for your own environment +const organizationId = '1081635000895'; const orgName = 'organizations/' + organizationId; const pubsubTopic = 'projects/project-a-id/topics/notifications-sample-topic'; diff --git a/security-center/snippets/system-test/v1/orgSettings.test.js b/security-center/snippets/system-test/v1/orgSettings.test.js index a3fc8498fc..c855697cb2 100644 --- a/security-center/snippets/system-test/v1/orgSettings.test.js +++ b/security-center/snippets/system-test/v1/orgSettings.test.js @@ -19,7 +19,8 @@ const {describe, it} = require('mocha'); const {execSync} = require('child_process'); const exec = cmd => execSync(cmd, {encoding: 'utf8'}); -const organizationId = process.env['GCLOUD_ORGANIZATION']; +// TODO(developers): update for your own environment +const organizationId = '1081635000895'; describe('client with organization settings', () => { it('client can enable asset discovery', () => { diff --git a/security-center/snippets/system-test/v2/notifications.test.js b/security-center/snippets/system-test/v2/notifications.test.js new file mode 100644 index 0000000000..44ce94cb63 --- /dev/null +++ b/security-center/snippets/system-test/v2/notifications.test.js @@ -0,0 +1,131 @@ +/* + * Copyright 2024 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 + * + * 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. + */ +'use strict'; + +const {execSync} = require('node:child_process'); + +const {assert} = require('chai'); +const {describe, it, before, after} = require('mocha'); +const uuidv1 = require('uuid').v1; + +const {SecurityCenterClient} = require('@google-cloud/security-center').v2; +const {PubSub} = require('@google-cloud/pubsub'); + +const exec = cmd => execSync(cmd, {encoding: 'utf8'}); + +// TODO(developers): update for your own environment +const organizationId = '1081635000895'; +const projectId = 'long-door-651'; +const location = 'global'; + +describe('Client with Notifications v2', async () => { + let client; + let pubSubClient; + let topicName; + let parent; + let pubsubTopic; + + let data; + + before(async () => { + const configId = 'notif-config-test-node-create-' + uuidv1(); + topicName = 'test_topic'; + parent = `projects/${projectId}/locations/${location}`; + pubsubTopic = `projects/${projectId}/topics/${topicName}`; + + client = new SecurityCenterClient(); + + pubSubClient = new PubSub(); + // A previous test failure can result the topic hanging around + try { + await pubSubClient.topic(topicName).delete(); + } catch { + // Ignore if the topic doesn't already exist + } + await pubSubClient.createTopic(topicName); + + const notificationConfig = { + description: 'Sample config for node v2', + pubsubTopic: pubsubTopic, + streamingConfig: {filter: 'state = "ACTIVE"'}, + }; + + const [notificationResponse] = await client.createNotificationConfig({ + parent: parent, + configId: configId, + notificationConfig: notificationConfig, + }); + + const notificationConfigs = notificationResponse.name.split('/')[5]; + data = { + orgId: organizationId, + projectId: projectId, + notificationName: notificationResponse.name, + notificationConfigs: notificationConfigs, + topicName: topicName, + }; + console.log('my data notification %j', data); + }); + + after(async () => { + try { + await pubSubClient.topic(topicName).delete(); + } catch { + // Ignore if the topic doesn't exist + } + }); + + it('client can create config v2', () => { + const output = exec( + `node v2/createNotificationConfig.js ${data.projectId} ${data.topicName}` + ); + assert(output.includes(data.projectId)); + assert.match(output, /Notification configuration creation successful/); + assert.notMatch(output, /undefined/); + }); + + it('client can get config v2', () => { + const output = exec( + `node v2/getNotificationConfig.js ${data.projectId} ${data.notificationConfigs}` + ); + assert(output.includes(data.notificationName)); + assert.match(output, /Notification config/); + assert.notMatch(output, /undefined/); + }); + + it('client can list configs v2', () => { + const output = exec(`node v2/listNotificationConfigs.js ${data.projectId}`); + assert(output.includes(data.projectId)); + assert.notMatch(output, /undefined/); + }); + + it('client can update configs v2', () => { + const output = exec( + `node v2/updateNotificationConfig.js ${data.projectId} ${data.notificationConfigs} ${data.topicName}` + ); + assert(output.includes(data.notificationName)); + assert.match(output, /Notification configuration update successful/); + assert.notMatch(output, /undefined/); + }); + + it('client can delete config v2', () => { + const output = exec( + `node v2/deleteNotificationConfig.js ${data.projectId} ${data.notificationConfigs}` + ); + assert.include(output, 'Deleted Notification config'); + assert.notMatch(output, /undefined/); + }); +}); diff --git a/security-center/snippets/v2/createNotificationConfig.js b/security-center/snippets/v2/createNotificationConfig.js new file mode 100644 index 0000000000..6a2ec3c97b --- /dev/null +++ b/security-center/snippets/v2/createNotificationConfig.js @@ -0,0 +1,81 @@ +/* + * Copyright 2024 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 + * + * 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. + */ + +'use strict'; + +/** + * Creates a notification config in a project under a given location. + * Ensure the ServiceAccount has the "pubsub.topics.setIamPolicy" permission on the new topic. + */ +async function main(projectId, topicName, location = 'global') { + // [START securitycenter_create_notification_config_v2] + // npm install '@google-cloud/security-center' + const {SecurityCenterClient} = require('@google-cloud/security-center').v2; + const uuidv1 = require('uuid').v1; + + const client = new SecurityCenterClient(); + /* + * Required. Resource name of the new notification config's parent. Its format + * is "organizations/[organization_id]/locations/[location_id]", + * "folders/[folder_id]/locations/[location_id]", or + * "projects/[project_id]/locations/[location_id]". + */ + const parent = `projects/${projectId}/locations/${location}`; + + /** + * Required. + * Unique identifier provided by the client within the parent scope. + * It must be between 1 and 128 characters and contain alphanumeric + * characters, underscores, or hyphens only. + */ + const configId = 'notif-config-test-node-create-' + uuidv1(); + + // pubsubTopic = "projects/{your-project}/topics/{your-topic}"; + const pubsubTopic = `projects/${projectId}/topics/${topicName}`; + + /** + * Required. The notification config being created. The name and the service + * account will be ignored as they are both output only fields on this + * resource. + */ + const notificationConfig = { + description: 'Sample config for node v2', + pubsubTopic: pubsubTopic, + streamingConfig: {filter: 'state = "ACTIVE"'}, + }; + + // Build the request. + const createNotificationRequest = { + parent: parent, + configId: configId, + notificationConfig: notificationConfig, + }; + + async function createNotificationConfig() { + const [response] = await client.createNotificationConfig( + createNotificationRequest + ); + console.log('Notification configuration creation successful: %j', response); + } + + await createNotificationConfig(); + // [END securitycenter_create_notification_config_v2] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/security-center/snippets/v2/deleteNotificationConfig.js b/security-center/snippets/v2/deleteNotificationConfig.js new file mode 100644 index 0000000000..e565bdb13c --- /dev/null +++ b/security-center/snippets/v2/deleteNotificationConfig.js @@ -0,0 +1,54 @@ +/* + * Copyright 2024 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 + * + * 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. + */ + +'use strict'; + +//Delete a notification config. +async function main(projectId, notificationId, location = 'global') { + // [START securitycenter_delete_notification_config_v2] + // npm install '@google-cloud/security-center' + const {SecurityCenterClient} = require('@google-cloud/security-center').v2; + + const client = new SecurityCenterClient(); + /** + * Required. Name of the notification config to delete. The following list + * shows some examples of the format: + * `organizations/[organization_id]/locations/[location_id]/notificationConfigs/[config_id]` + * `folders/[folder_id]/locations/[location_id]notificationConfigs/[config_id]` + * `projects/[project_id]/locations/[location_id]notificationConfigs/[config_id]` + */ + const name = `projects/${projectId}/locations/${location}/notificationConfigs/${notificationId}`; + + // Build the request. + const deleteNotificationConfigRequest = { + name: name, + }; + + async function deleteNotificationConfig() { + const [response] = await client.deleteNotificationConfig( + deleteNotificationConfigRequest + ); + console.log('Deleted Notification config: %j', response); + } + + await deleteNotificationConfig(); + // [END securitycenter_delete_notification_config_v2] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/security-center/snippets/v2/getNotificationConfig.js b/security-center/snippets/v2/getNotificationConfig.js new file mode 100644 index 0000000000..f4164641d9 --- /dev/null +++ b/security-center/snippets/v2/getNotificationConfig.js @@ -0,0 +1,54 @@ +/* + * Copyright 2024 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 + * + * 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. + */ + +'use strict'; + +//Retrieve an existing notification config. +async function main(projectId, notificationId, location = 'global') { + // [START securitycenter_get_notification_config_v2] + // npm install '@google-cloud/security-center' + const {SecurityCenterClient} = require('@google-cloud/security-center').v2; + + const client = new SecurityCenterClient(); + /** + * Required. Name of the notification config to get. The following list shows + * some examples of the format: + * `organizations/[organization_id]/locations/[location_id]/notificationConfigs/[config_id]` + * `folders/[folder_id]/locations/[location_id]/notificationConfigs/[config_id]` + * `projects/[project_id]/locations/[location_id]/notificationConfigs/[config_id]` + */ + const name = `projects/${projectId}/locations/${location}/notificationConfigs/${notificationId}`; + + // Build the request. + const getNotificationConfigRequest = { + name: name, + }; + + async function getNotificationConfig() { + const [response] = await client.getNotificationConfig( + getNotificationConfigRequest + ); + console.log('Notification config: %j', response); + } + + await getNotificationConfig(); + // [END securitycenter_get_notification_config_v2] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/security-center/snippets/v2/listNotificationConfigs.js b/security-center/snippets/v2/listNotificationConfigs.js new file mode 100644 index 0000000000..03c82103f3 --- /dev/null +++ b/security-center/snippets/v2/listNotificationConfigs.js @@ -0,0 +1,50 @@ +/* + * Copyright 2024 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 + * + * 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. + */ + +'use strict'; + +async function main(projectId, location = 'global') { + // [START securitycenter_list_notification_configs_v2] + // npm install @google-cloud/security-center/ + const {SecurityCenterClient} = require('@google-cloud/security-center').v2; + + const client = new SecurityCenterClient(); + + /** + * Required. The name of the parent in which to list the notification + * configurations. Its format is + * "organizations/[organization_id]/locations/[location_id]", + * "folders/[folder_id]/locations/[location_id]", or + * "projects/[project_id]/locations/[location_id]". + */ + const parent = `projects/${projectId}/locations/${location}`; + + async function listNotificationConfigs() { + const iterable = client.listNotificationConfigsAsync({parent: parent}); + console.log('Received Notification configs: %j'); + for await (const response of iterable) { + console.log(response); + } + } + + await listNotificationConfigs(); + // [END securitycenter_list_notification_configs_v2] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/security-center/snippets/v2/receiveNotifications.js b/security-center/snippets/v2/receiveNotifications.js new file mode 100644 index 0000000000..cd2e93a6d0 --- /dev/null +++ b/security-center/snippets/v2/receiveNotifications.js @@ -0,0 +1,66 @@ +/* + * Copyright 2024 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 + * + * 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. + */ + +'use strict'; + +async function main( + projectId = 'your-project-id', + subscriptionId = 'your-subscription-id' +) { + // [START securitycenter_receive_notifications] + const {PubSub} = require('@google-cloud/pubsub'); + const {StringDecoder} = require('string_decoder'); + + // projectId = 'your-project-id' + // subscriptionId = 'your-subscription-id' + + const subscriptionName = + 'projects/' + projectId + '/subscriptions/' + subscriptionId; + const pubSubClient = new PubSub(); + + function listenForMessages() { + const subscription = pubSubClient.subscription(subscriptionName); + + // message.data is a buffer array of json + // 1. Convert buffer to normal string + // 2. Convert json to NotificationMessage object + const messageHandler = message => { + const jsonString = new StringDecoder('utf-8').write(message.data); + const parsedNotificationMessage = JSON.parse(jsonString); + + console.log(parsedNotificationMessage); + console.log(parsedNotificationMessage.finding); + + // ACK when done with message + message.ack(); + }; + + subscription.on('message', messageHandler); + + // Set timeout to 10 seconds + setTimeout(() => { + subscription.removeListener('message', messageHandler); + }, 10000); + } + + await listenForMessages(); + // [END securitycenter_receive_notifications] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/security-center/snippets/v2/updateNotificationConfig.js b/security-center/snippets/v2/updateNotificationConfig.js new file mode 100644 index 0000000000..baef5fd585 --- /dev/null +++ b/security-center/snippets/v2/updateNotificationConfig.js @@ -0,0 +1,81 @@ +/* + * Copyright 2024 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 + * + * 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. + */ + +'use strict'; + +/** + * Update an existing notification config. + * If updating a Pubsub Topic, ensure the ServiceAccount has the + * "pubsub.topics.setIamPolicy" permission on the new topic. + */ +async function main(projectId, notificationId, topicName, location = 'global') { + // [START securitycenter_update_notification_config_v2] + // npm install '@google-cloud/security-center' + const {SecurityCenterClient} = require('@google-cloud/security-center').v2; + // Instantiates a client + const client = new SecurityCenterClient(); + + /** + * Required. Name of the notification config to update. The following list shows + * some examples of the format: + * `organizations/[organization_id]/locations/[location_id]/notificationConfigs/[config_id]` + * `folders/[folder_id]/locations/[location_id]/notificationConfigs/[config_id]` + * `projects/[project_id]/locations/[location_id]/notificationConfigs/[config_id]` + */ + const name = `projects/${projectId}/locations/${location}/notificationConfigs/${notificationId}`; + + // pubsubTopic = "projects/{your-project}/topics/{your-topic}"; + const pubsubTopic = `projects/${projectId}/topics/${topicName}`; + + /** + * Required. The notification config to update. + */ + const notificationConfig = { + name: name, + description: 'updated description', + pubsubTopic: pubsubTopic, + streamingConfig: {filter: 'state = "ACTIVE"'}, + }; + + /** + * The FieldMask to use when updating the notification config. + * If empty all mutable fields will be updated. + */ + const fieldMask = { + paths: ['description', 'pubsub_topic', 'streaming_config.filter'], + }; + + // Build the request. + const updateNotificationConfigRequest = { + notificationConfig: notificationConfig, + }; + + async function updateNotificationConfig() { + const [response] = await client.updateNotificationConfig( + updateNotificationConfigRequest, + fieldMask + ); + console.log('Notification configuration update successful: %j', response); + } + + await updateNotificationConfig(); + // [END securitycenter_update_notification_config_v2] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +});