Skip to content

Commit

Permalink
feat: Adding API v2 IAM+Notifications samples (GoogleCloudPlatform#3717)
Browse files Browse the repository at this point in the history
* 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 <rerodrigues@google.com>
Co-authored-by: Jennifer Davis <sigje@google.com>
Co-authored-by: Adam Ross <adamross@google.com>
Co-authored-by: Tony Pujals <subfuzion@users.noreply.github.com>
Co-authored-by: Tony Pujals <tonypujals@google.com>
  • Loading branch information
6 people committed Aug 14, 2024
1 parent 30e988e commit 9af3f5d
Show file tree
Hide file tree
Showing 16 changed files with 539 additions and 13 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/utils/workflows.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,5 +94,6 @@
"video-intelligence",
"vision/productSearch",
"workflows",
"workflows/invoke-private-endpoint"
"workflows/invoke-private-endpoint",
"security-center/snippets/v2"
]
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion security-center/snippets/system-test/v1/findings.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 3 additions & 2 deletions security-center/snippets/system-test/v1/listAllAssets.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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/);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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/);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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/);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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/);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down
3 changes: 2 additions & 1 deletion security-center/snippets/system-test/v1/orgSettings.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down
131 changes: 131 additions & 0 deletions security-center/snippets/system-test/v2/notifications.test.js
Original file line number Diff line number Diff line change
@@ -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/);
});
});
81 changes: 81 additions & 0 deletions security-center/snippets/v2/createNotificationConfig.js
Original file line number Diff line number Diff line change
@@ -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;
});
54 changes: 54 additions & 0 deletions security-center/snippets/v2/deleteNotificationConfig.js
Original file line number Diff line number Diff line change
@@ -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;
});
Loading

0 comments on commit 9af3f5d

Please sign in to comment.