Skip to content

Commit

Permalink
feat(securitycenter): add finding sources iam samples (#3722)
Browse files Browse the repository at this point in the history
* feat:add finding sources iam samples

* fix: tests, proper async handling, refactor

This streamlines the sample and better aligns it with other languages.

---------

Co-authored-by: Rafael Rodrigues <[email protected]>
Co-authored-by: Tony Pujals <[email protected]>
  • Loading branch information
3 people authored Aug 20, 2024
1 parent 6fe7417 commit f76c2fb
Show file tree
Hide file tree
Showing 24 changed files with 1,907 additions and 29 deletions.
1 change: 1 addition & 0 deletions .github/workflows/security-center-snippets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ jobs:
- run: npm test
env:
GCLOUD_ORGANIZATION: 1081635000895
GOOGLE_SAMPLES_PROJECT: "long-door-651"
- name: upload test results for FlakyBot workflow
if: github.event.action == 'schedule' && always()
uses: actions/upload-artifact@v3
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/utils/workflows.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,5 @@
"video-intelligence",
"vision/productSearch",
"workflows",
"workflows/invoke-private-endpoint",
"security-center/snippets/v2"
"workflows/invoke-private-endpoint"
]
8 changes: 4 additions & 4 deletions security-center/snippets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@
"node": ">=16.0.0"
},
"scripts": {
"test": "c8 mocha -p -j 2 system-test/ --recursive --timeout 6000000"
"test": "c8 mocha -p -j 2 --recursive --timeout 6000000 system-test/v2/findings.test.js"
},
"license": "Apache-2.0",
"dependencies": {
"@google-cloud/pubsub": "^4.0.0",
"@google-cloud/security-center": "^8.0.0"
"@google-cloud/security-center": "^8.7.0"
},
"devDependencies": {
"c8": "^10.0.0",
"chai": "^4.5.0",
"mocha": "^10.0.0",
"chai": "^4.2.0",
"mocha": "^10.4.0",
"uuid": "^10.0.0"
}
}
68 changes: 68 additions & 0 deletions security-center/snippets/system-test/v2/findings.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// 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
//
// 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.

const spawnSync = require('node:child_process').spawnSync;

// TODO: replace chai with standard assert/strict
const {assert} = require('chai');
const {describe, it} = require('mocha');

// Can't use arrow function to access this context in describe hook, needed
// to pass the configured timeout to the hook's process runner (assertExec).
// eslint-disable-next-line prefer-arrow-callback
describe('Client v2 with sources and findings', async function () {
// Spawn child process and assert that it exits normally.
const assertChild = (...args) => {
const result = spawnSync('node', args, {timeout: this.timeout()});
const output = result.stdout.toString();
console.log(output);
console.error(result.stderr.toString());
assert(
result.status === 0,
`process exited with non-zero status: ${result.status}`
);
return output;
};

// Register test for the child process.
const testChild = (msg, ...args) => {
it(msg, () => {
assertChild(...args);
});
};

testChild('can create source', 'v2/createSource.js');
testChild('can create a finding', 'v2/createFinding.js');
testChild('can list all findings', 'v2/listAllFindings.js');
testChild('can list only some findings', 'v2/listFilteredFindings.js');
testChild('can mute a finding', 'v2/setMuteFinding.js');
testChild('can unmute a finding', 'v2/setUnmuteFinding.js');
testChild('can group all findings', 'v2/groupFindings.js');
testChild('can group filtered findings', 'v2/groupFindingsWithFilter.js');
testChild('can bulk mute findings', 'v2/bulkMuteFindings.js');
testChild('can get IAM policy', 'v2/getIamPolicy.js');
testChild('can IAM policies', 'v2/testIam.js');
testChild('can set access control policy on a source', 'v2/setIamPolicy.js');
testChild('client can update a finding state', 'v2/setFindingState.js');
testChild(
'can create or update a finding source',
'v2/updateFindingSource.js'
);
testChild(
'can list all security sources in an organization',
'v2/listAllSources.js'
);
testChild('client can create or update a source', 'v2/updateSource.js');
testChild('client can get a specific source', 'v2/getSource.js');
});
29 changes: 14 additions & 15 deletions security-center/snippets/system-test/v2/notifications.test.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
/*
* 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.
*/
// 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
//
// 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 {execSync} = require('node:child_process');
Expand Down
14 changes: 9 additions & 5 deletions security-center/snippets/v1/createFinding.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
/*
* Copyright 2019, Google, LLC.
* 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
* 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,
Expand All @@ -17,7 +18,7 @@
/**
* Demonstrates how to create a new security finding in CSCC.
*/
function main(sourceName = 'FULL_PATH_TO_SOURCE_FOR_FINDING') {
async function main(sourceName = 'FULL_PATH_TO_SOURCE_FOR_FINDING') {
// [START securitycenter_create_finding]
// Imports the Google Cloud client library.
const {SecurityCenterClient} = require('@google-cloud/security-center');
Expand Down Expand Up @@ -54,8 +55,11 @@ function main(sourceName = 'FULL_PATH_TO_SOURCE_FOR_FINDING') {
});
console.log('New finding created: %j', newFinding);
}
createFinding();
await createFinding();
// [END securitycenter_create_finding]
}

main(...process.argv.slice(2));
main(process.argv.slice(2)[0]).catch(err => {
console.log(err);
process.exitCode = 1;
});
9 changes: 6 additions & 3 deletions security-center/snippets/v1/listAllFindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
'use strict';

/** Prints all findings across all sources. */
function main(organizationId = 'YOUR_NUMERIC_ORG_ID') {
async function main(organizationId = 'YOUR_NUMERIC_ORG_ID') {
// [START securitycenter_list_all_findings]
// Imports the Google Cloud client library.
const {SecurityCenterClient} = require('@google-cloud/security-center');
Expand Down Expand Up @@ -43,8 +43,11 @@ function main(organizationId = 'YOUR_NUMERIC_ORG_ID') {
)
);
}
listAllFindings();
await listAllFindings();
// [END securitycenter_list_all_findings]
}

main(...process.argv.slice(2));
main(process.argv.slice(2)[0]).catch(err => {
console.error(err);
process.exitCode = 1;
});
123 changes: 123 additions & 0 deletions security-center/snippets/v2/bulkMuteFindings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// 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
//
// 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';

// Kicks off a long-running operation (LRO) to bulk mute findings for a parent based on a filter.
// The parent can be either an organization, folder, or project. The findings
// matched by the filter will be muted after the LRO is done.
async function main() {
// [START securitycenter_bulk_mute_v2]
// Imports the Google Cloud client library.
const {SecurityCenterClient} = require('@google-cloud/security-center').v2;

// Create a Security Center client
const client = new SecurityCenterClient();

// TODO(developer): Update the following for your own environment.
const organizationId = '1081635000895';
const projectId = 'long-door-651';
const location = 'global';

async function createSampleFinding() {
const uuid = require('uuid');

const [source] = await client.createSource({
source: {
displayName: 'Customized Display Name V2',
description: 'A new custom source that does X',
},
parent: client.organizationPath(organizationId),
});

const sourceId = source.name.split('/')[3];

// Resource name of the new finding's parent. Examples:
// - `organizations/[organization_id]/sources/[source_id]`
// - `organizations/[organization_id]/sources/[source_id]/locations/[location_id]`
const parent = `organizations/${organizationId}/sources/${sourceId}/locations/${location}`;

// The resource this finding applied to. The Cloud Security Command Center UI can link the
// findings for a resource to the corresponding asset of a resource if there are matches.
const resourceName = `//cloudresourcemanager.googleapis.com/organizations/${organizationId}`;

// Unique identifier provided by the client within the parent scope.
// It must be alphanumeric and less than or equal to 32 characters and
// greater than 0 characters in length.
const findingId = uuid.v4().replace(/-/g, '');

// Get the current timestamp.
const eventDate = new Date();

// Finding category.
const category = 'MEDIUM_RISK_ONE';

// Build the finding request object.
const createFindingRequest = {
parent: parent,
findingId: findingId,
finding: {
resourceName,
category,
state: 'ACTIVE',
// The time associated with discovering the issue.
eventTime: {
seconds: Math.floor(eventDate.getTime() / 1000),
nanos: (eventDate.getTime() % 1000) * 1e6,
},
},
};

await client.createFinding(createFindingRequest);
}

await createSampleFinding();

// Required. The parent, at which bulk action needs to be applied. If no
// location is specified, findings are updated in global. The following list
// shows some examples:
// - `organizations/[organization_id]`
// - `organizations/[organization_id]/locations/[location_id]`
// - `folders/[folder_id]`
// - `folders/[folder_id]/locations/[location_id]`
// - `projects/[project_id]`
// - `projects/[project_id]/locations/[location_id]`
const parent = `organizations/${organizationId}/locations/${location}`;

// muteRule: Expression that identifies findings that should be muted.
// Can also refer to an organization/ folder.
// eg: "resource.project_display_name=\"PROJECT_ID\""
const filter = `resource.project_display_name="${projectId}"`;

// Build the request.
const bulkMuteFindingRequest = {
parent,
filter,
};

async function callBulkMuteFindings() {
// Call the API.
const [operation] = await client.bulkMuteFindings(bulkMuteFindingRequest);
const [response] = await operation.promise();
console.log('Bulk mute findings completed successfully: %j', response);
}

await callBulkMuteFindings();
// [END securitycenter_bulk_mute_v2]
}

main().catch(err => {
console.error(err);
process.exitCode = 1;
});
Loading

0 comments on commit f76c2fb

Please sign in to comment.