Skip to content

Commit 00867cf

Browse files
authored
Merge pull request #2867 from GoogleCloudPlatform/nodejs-security-center-migration
migrate code from googleapis/nodejs-security-center
2 parents 7f1b382 + 1a035ee commit 00867cf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2298
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
name: security-center-snippets
2+
on:
3+
push:
4+
branches:
5+
- main
6+
paths:
7+
- 'security-center/snippets/**'
8+
pull_request:
9+
paths:
10+
- 'security-center/snippets/**'
11+
pull_request_target:
12+
types: [labeled]
13+
paths:
14+
- 'security-center/snippets/**'
15+
schedule:
16+
- cron: '0 0 * * 0'
17+
env:
18+
GCLOUD_ORGANIZATION: 1081635000895
19+
jobs:
20+
test:
21+
if: ${{ github.event.action != 'labeled' || github.event.label.name == 'actions:force-run' }}
22+
runs-on: ubuntu-latest
23+
timeout-minutes: 60
24+
permissions:
25+
contents: 'write'
26+
pull-requests: 'write'
27+
id-token: 'write'
28+
steps:
29+
- uses: actions/[email protected]
30+
with:
31+
ref: ${{github.event.pull_request.head.sha}}
32+
- uses: 'google-github-actions/[email protected]'
33+
with:
34+
workload_identity_provider: 'projects/1046198160504/locations/global/workloadIdentityPools/github-actions-pool/providers/github-actions-provider'
35+
service_account: '[email protected]'
36+
create_credentials_file: 'true'
37+
access_token_lifetime: 600s
38+
- uses: actions/[email protected]
39+
with:
40+
node-version: 16
41+
- run: npm install
42+
working-directory: security-center/snippets
43+
- run: npm test
44+
working-directory: security-center/snippets
45+
env:
46+
MOCHA_REPORTER_SUITENAME: security_center_snippets
47+
MOCHA_REPORTER_OUTPUT: security_center_snippets_sponge_log.xml
48+
MOCHA_REPORTER: xunit
49+
- if: ${{ github.event.action == 'labeled' && github.event.label.name == 'actions:force-run' }}
50+
uses: actions/github-script@v6
51+
with:
52+
github-token: ${{ secrets.GITHUB_TOKEN }}
53+
script: |
54+
try {
55+
await github.rest.issues.removeLabel({
56+
name: 'actions:force-run',
57+
owner: 'GoogleCloudPlatform',
58+
repo: 'nodejs-docs-samples',
59+
issue_number: context.payload.pull_request.number
60+
});
61+
} catch (e) {
62+
if (!e.message.includes('Label does not exist')) {
63+
throw e;
64+
}
65+
}
66+
- if: ${{ github.event_name == 'schedule'}}
67+
run: |
68+
curl https://github.com/googleapis/repo-automation-bots/releases/download/flakybot-1.1.0/flakybot -o flakybot -s -L
69+
chmod +x ./flakybot
70+
./flakybot --repo GoogleCloudPlatform/nodejs-docs-samples --commit_hash ${{github.sha}} --build_url https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}

.github/workflows/workflows.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,9 @@
5757
"datacatalog/cloud-client",
5858
"datacatalog/quickstart",
5959
"datastore/functions",
60-
"service-directory/snippets",
6160
"scheduler",
61+
"security-center/snippets",
62+
"service-directory/snippets",
6263
"secret-manager",
6364
"speech",
6465
"talent",

security-center/snippets/package.json

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "nodejs-security-center-samples",
3+
"private": true,
4+
"files": [
5+
"**/*.js",
6+
"!system-test/"
7+
],
8+
"engines": {
9+
"node": ">=12.0.0"
10+
},
11+
"scripts": {
12+
"test": "mocha system-test/ --recursive --timeout 6000000"
13+
},
14+
"license": "Apache-2.0",
15+
"dependencies": {
16+
"@google-cloud/pubsub": "^3.0.0",
17+
"@google-cloud/security-center": "^6.3.1"
18+
},
19+
"devDependencies": {
20+
"chai": "^4.2.0",
21+
"mocha": "^8.0.0",
22+
"uuid": "^9.0.0"
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Copyright 2019 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
const {SecurityCenterClient} = require('@google-cloud/security-center');
18+
const {assert} = require('chai');
19+
const {describe, it, before} = require('mocha');
20+
const {execSync} = require('child_process');
21+
const exec = cmd => execSync(cmd, {encoding: 'utf8'});
22+
23+
const organizationId = process.env['GCLOUD_ORGANIZATION'];
24+
25+
describe('client with security marks for assets', async () => {
26+
let data;
27+
before(async () => {
28+
// Creates a new client.
29+
const client = new SecurityCenterClient();
30+
31+
const [assetResults] = await client.listAssets({
32+
parent: client.organizationPath(organizationId),
33+
});
34+
const randomAsset =
35+
assetResults[Math.floor(Math.random() * assetResults.length)].asset;
36+
console.log('random %j', randomAsset);
37+
data = {
38+
orgId: organizationId,
39+
assetName: randomAsset.name,
40+
};
41+
console.log('data %j', data);
42+
});
43+
it('client can add security marks to asset.', () => {
44+
const output = exec(`node v1/addSecurityMarks.js ${data.assetName}`);
45+
assert.include(output, data.assetName);
46+
assert.match(output, /key_a/);
47+
assert.match(output, /value_a/);
48+
assert.match(output, /key_b/);
49+
assert.match(output, /value_b/);
50+
assert.notMatch(output, /undefined/);
51+
});
52+
53+
it('client can add and delete security marks', () => {
54+
// Ensure marks are set.
55+
exec(`node v1/addSecurityMarks.js ${data.assetName}`);
56+
57+
const output = exec(`node v1/addDeleteSecurityMarks.js ${data.assetName}`);
58+
assert.match(output, /key_a/);
59+
assert.match(output, /new_value_a/);
60+
assert.notMatch(output, /key_b/);
61+
assert.notMatch(output, /undefined/);
62+
});
63+
64+
it('client can delete security marks', () => {
65+
// Ensure marks are set.
66+
exec(`node v1/addSecurityMarks.js ${data.assetName}`);
67+
68+
const output = exec(`node v1/deleteSecurityMarks.js ${data.assetName}`);
69+
assert.notMatch(output, /key_a/);
70+
assert.notMatch(output, /value_a/);
71+
assert.notMatch(output, /key_b/);
72+
assert.notMatch(output, /value_b/);
73+
assert.include(output, data.assetName);
74+
assert.include(output, data.assetName);
75+
assert.notMatch(output, /undefined/);
76+
});
77+
78+
it('client can list assets with security marks', () => {
79+
// Ensure marks are set.
80+
exec(`node v1/addSecurityMarks.js ${data.assetName}`);
81+
82+
const output = exec(`node v1/listAssetsWithSecurityMarks.js ${data.orgId}`);
83+
assert.include(output, data.assetName);
84+
assert.notMatch(output, /undefined/);
85+
});
86+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
// Copyright 2019 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
const {SecurityCenterClient} = require('@google-cloud/security-center');
18+
const {assert} = require('chai');
19+
const {describe, it, before} = require('mocha');
20+
const {execSync} = require('child_process');
21+
const exec = cmd => execSync(cmd, {encoding: 'utf8'});
22+
23+
const organizationId = process.env['GCLOUD_ORGANIZATION'];
24+
25+
describe('Client with SourcesAndFindings', async () => {
26+
let data;
27+
before(async () => {
28+
// Creates a new client.
29+
const client = new SecurityCenterClient();
30+
const [source] = await client
31+
.createSource({
32+
source: {
33+
displayName: 'Customized Display Name',
34+
description: 'A new custom source that does X',
35+
},
36+
parent: client.organizationPath(organizationId),
37+
})
38+
.catch(error => console.error(error));
39+
const eventTime = new Date();
40+
const createFindingTemplate = {
41+
parent: source.name,
42+
findingId: 'somefinding',
43+
finding: {
44+
state: 'ACTIVE',
45+
// Resource the finding is associated with. This is an
46+
// example any resource identifier can be used.
47+
resourceName:
48+
'//cloudresourcemanager.googleapis.com/organizations/11232',
49+
// A free-form category.
50+
category: 'MEDIUM_RISK_ONE',
51+
// The time associated with discovering the issue.
52+
eventTime: {
53+
seconds: Math.floor(eventTime.getTime() / 1000),
54+
nanos: (eventTime.getTime() % 1000) * 1e6,
55+
},
56+
},
57+
};
58+
const [finding] = await client.createFinding(createFindingTemplate);
59+
createFindingTemplate.findingId = 'untouchedFindingId';
60+
createFindingTemplate.finding.category = 'XSS';
61+
const [untouchedFinding] = await client
62+
.createFinding(createFindingTemplate)
63+
.catch(error => console.error(error));
64+
data = {
65+
orgId: organizationId,
66+
sourceName: source.name,
67+
findingName: finding.name,
68+
untouchedFindingName: untouchedFinding.name,
69+
};
70+
console.log('my data %j', data);
71+
});
72+
73+
it('client can create source', () => {
74+
const output = exec(`node v1/createSource.js ${data.orgId}`);
75+
assert.match(output, new RegExp(data.orgId));
76+
assert.match(output, /New Source/);
77+
assert.notMatch(output, /undefined/);
78+
});
79+
80+
it('client can get source', () => {
81+
const output = exec(`node v1/getSource.js ${data.sourceName}`);
82+
assert.match(output, new RegExp(data.sourceName));
83+
assert.match(output, /Source/);
84+
assert.match(output, /"description":"A new custom source that does X"/);
85+
assert.notMatch(output, /undefined/);
86+
});
87+
88+
it('client can list all sources', () => {
89+
const output = exec(`node v1/listAllSources.js ${data.orgId}`);
90+
assert.match(output, new RegExp(data.sourceName));
91+
assert.match(output, /Sources/);
92+
assert.notMatch(output, /undefined/);
93+
});
94+
95+
it('client can update a source', () => {
96+
const output = exec(`node v1/updateSource.js ${data.sourceName}`);
97+
assert.match(output, new RegExp(data.sourceName));
98+
assert.match(output, /New Display Name/);
99+
assert.match(output, /source that does X/);
100+
assert.notMatch(output, /undefined/);
101+
});
102+
103+
it('client can create a finding', () => {
104+
const output = exec(`node v1/createFinding.js ${data.sourceName}`);
105+
assert.match(output, new RegExp(data.sourceName));
106+
assert.match(output, /New finding created/);
107+
assert.notMatch(output, /undefined/);
108+
});
109+
110+
it('client can create a finding with source properties', () => {
111+
const output = exec(
112+
`node v1/createFindingSourceProperties.js ${data.sourceName}`
113+
);
114+
assert.match(output, new RegExp(data.sourceName));
115+
assert.match(output, /New finding created/);
116+
assert.match(output, /n_value/);
117+
assert.notMatch(output, /undefined/);
118+
});
119+
120+
it('client can update a findings source properties', () => {
121+
const output = exec(
122+
`node v1/updateFindingSourceProperties.js ${data.findingName}`
123+
);
124+
assert.match(output, new RegExp(data.findingName));
125+
assert.match(output, /Updated Finding/);
126+
assert.match(output, /new_string_example/);
127+
assert.notMatch(output, /undefined/);
128+
});
129+
130+
it('client can set finding state', () => {
131+
const output = exec(`node v1/setFindingState.js ${data.findingName}`);
132+
assert.match(output, new RegExp(data.findingName));
133+
assert.match(output, /INACTIVE/);
134+
assert.notMatch(output, /undefined/);
135+
});
136+
137+
it('client can test IAM privileges', () => {
138+
const output = exec(`node v1/testIam.js ${data.sourceName}`);
139+
assert.equal(
140+
(output.match(/true/g) || []).length,
141+
2,
142+
`${output} contains true twice`
143+
);
144+
assert.notMatch(output, /undefined/);
145+
});
146+
147+
it('client can list all findings', () => {
148+
const output = exec(`node v1/listAllFindings.js ${data.orgId}`);
149+
assert.match(output, new RegExp(data.findingName));
150+
assert.match(output, new RegExp(data.untouchedFindingName));
151+
assert.notMatch(output, /undefined/);
152+
});
153+
154+
it('client can list only some findings', () => {
155+
const output = exec(`node v1/listFilteredFindings.js ${data.sourceName}`);
156+
assert.match(output, new RegExp(data.findingName));
157+
assert.notMatch(output, new RegExp(data.untouchedFindingName));
158+
assert.notMatch(output, /undefined/);
159+
});
160+
161+
it('client can list findings at a time.', () => {
162+
const output = exec(`node v1/listFindingsAtTime.js ${data.sourceName}`);
163+
// Nothing was created for the source more then a few minutes ago, so
164+
// days ago should return nothing.
165+
assert.equal(output, '');
166+
});
167+
168+
it('client can add security marks to finding', () => {
169+
const output = exec(
170+
`node v1/addFindingSecurityMarks.js ${data.findingName}`
171+
);
172+
assert.match(output, new RegExp(data.findingName));
173+
assert.match(output, /key_a/);
174+
assert.match(output, /value_a/);
175+
assert.match(output, /key_b/);
176+
assert.match(output, /value_b/);
177+
assert.notMatch(output, /undefined/);
178+
});
179+
180+
it('client can list findings withe security marks', () => {
181+
// Ensure marks are set.
182+
exec(`node v1/addFindingSecurityMarks.js ${data.findingName}`);
183+
const output = exec(
184+
`node v1/listFindingsWithSecurityMarks.js ${data.sourceName}`
185+
);
186+
assert.notMatch(output, new RegExp(data.findingName));
187+
assert.match(output, new RegExp(data.untouchedFindingName));
188+
assert.notMatch(output, /undefined/);
189+
});
190+
191+
it('client can get a sources policy', () => {
192+
const output = exec(`node v1/getSourceIam.js ${data.sourceName}`);
193+
assert.match(output, /Current policy/);
194+
assert.notMatch(output, /undefined/);
195+
});
196+
197+
it('client set a sources policy', () => {
198+
const user = '[email protected]';
199+
const output = exec(`node v1/setSourceIam.js ${data.sourceName} ${user}`);
200+
assert.match(output, /Updated policy/);
201+
assert.include(output, user);
202+
assert.notMatch(output, /undefined/);
203+
});
204+
});

0 commit comments

Comments
 (0)