@contrast/contrast 1.0.20 → 1.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cliConstants.js +17 -9
- package/dist/commands/audit/help.js +5 -1
- package/dist/commands/audit/processAudit.js +1 -1
- package/dist/commands/auth/auth.js +5 -0
- package/dist/commands/fingerprint/fingerprintConfig.js +12 -0
- package/dist/commands/fingerprint/processFingerprint.js +14 -0
- package/dist/commands/learn/learn.js +9 -0
- package/dist/commands/learn/processLearn.js +10 -0
- package/dist/common/HTTPClient.js +9 -0
- package/dist/common/commonHelp.js +8 -1
- package/dist/constants/constants.js +1 -1
- package/dist/constants/lambda.js +1 -0
- package/dist/constants/locales.js +20 -12
- package/dist/index.js +8 -0
- package/dist/lambda/help.js +5 -1
- package/dist/lambda/scanRequest.js +12 -1
- package/dist/scaAnalysis/common/treeUpload.js +3 -0
- package/dist/scaAnalysis/javascript/analysis.js +11 -33
- package/dist/scaAnalysis/javascript/index.js +14 -1
- package/dist/scaAnalysis/javascript/scaServiceParser.js +3 -3
- package/dist/scaAnalysis/scaAnalysis.js +155 -0
- package/dist/scan/autoDetection.js +2 -2
- package/dist/scan/fileUtils.js +2 -2
- package/dist/scan/help.js +5 -1
- package/dist/utils/settingsHelper.js +2 -2
- package/package.json +1 -1
- package/src/cliConstants.js +19 -9
- package/src/commands/audit/help.js +5 -1
- package/src/commands/audit/processAudit.js +1 -1
- package/src/commands/auth/auth.js +5 -0
- package/src/commands/fingerprint/fingerprintConfig.js +19 -0
- package/src/commands/fingerprint/processFingerprint.js +21 -0
- package/src/commands/learn/learn.js +10 -0
- package/src/commands/learn/processLearn.js +13 -0
- package/src/common/HTTPClient.js +11 -0
- package/src/common/commonHelp.js +11 -1
- package/src/constants/constants.js +1 -1
- package/src/constants/lambda.js +1 -0
- package/src/constants/locales.js +28 -12
- package/src/index.ts +10 -0
- package/src/lambda/help.ts +5 -1
- package/src/lambda/scanRequest.ts +27 -2
- package/src/scaAnalysis/common/treeUpload.js +7 -0
- package/src/scaAnalysis/javascript/analysis.js +19 -34
- package/src/scaAnalysis/javascript/index.js +29 -1
- package/src/scaAnalysis/javascript/scaServiceParser.js +3 -3
- package/src/scaAnalysis/scaAnalysis.js +206 -0
- package/src/scan/autoDetection.js +2 -2
- package/src/scan/fileUtils.js +2 -2
- package/src/scan/help.js +5 -1
- package/src/utils/settingsHelper.js +2 -2
- package/dist/commands/scan/sca/scaAnalysis.js +0 -157
- package/src/commands/scan/sca/scaAnalysis.js +0 -211
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const { supportedLanguages: { JAVA, GO, PYTHON, RUBY, JAVASCRIPT, NODE, PHP, DOTNET } } = require('../constants/constants');
|
|
3
|
+
const { pollForSnapshotCompletion } = require('../audit/languageAnalysisEngine/sendSnapshot');
|
|
4
|
+
const { returnOra, startSpinner, succeedSpinner } = require('../utils/oraWrapper');
|
|
5
|
+
const { vulnerabilityReportV2 } = require('../audit/report/reportingFeature');
|
|
6
|
+
const autoDetection = require('../scan/autoDetection');
|
|
7
|
+
const treeUpload = require('./common/treeUpload');
|
|
8
|
+
const auditController = require('../commands/audit/auditController');
|
|
9
|
+
const rootFile = require('../audit/languageAnalysisEngine/getProjectRootFilenames');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const i18n = require('i18n');
|
|
12
|
+
const auditSave = require('../audit/save');
|
|
13
|
+
const { auditUsageGuide } = require('../commands/audit/help');
|
|
14
|
+
const repoMode = require('./repoMode');
|
|
15
|
+
const { dotNetAnalysis } = require('./dotnet');
|
|
16
|
+
const { goAnalysis } = require('./go/goAnalysis');
|
|
17
|
+
const { phpAnalysis } = require('./php');
|
|
18
|
+
const { rubyAnalysis } = require('./ruby');
|
|
19
|
+
const { pythonAnalysis } = require('./python');
|
|
20
|
+
const javaAnalysis = require('./java');
|
|
21
|
+
const jsAnalysis = require('./javascript');
|
|
22
|
+
const auditReport = require('./common/auditReport');
|
|
23
|
+
const scaUpload = require('./common/scaServicesUpload');
|
|
24
|
+
const settingsHelper = require('../utils/settingsHelper');
|
|
25
|
+
const chalk = require('chalk');
|
|
26
|
+
const saveResults = require('../scan/saveResults');
|
|
27
|
+
const { convertGenericToTypedReportModelSca } = require('./common/utils/reportUtilsSca');
|
|
28
|
+
const processSca = async (config) => {
|
|
29
|
+
config = await settingsHelper.getSettings(config);
|
|
30
|
+
const startTime = performance.now();
|
|
31
|
+
let filesFound;
|
|
32
|
+
if (config.help) {
|
|
33
|
+
console.log(auditUsageGuide);
|
|
34
|
+
process.exit(0);
|
|
35
|
+
}
|
|
36
|
+
const projectStats = await rootFile.getProjectStats(config.file);
|
|
37
|
+
let pathWithFile = projectStats.isFile();
|
|
38
|
+
config.fileName = config.file;
|
|
39
|
+
config.file = pathWithFile
|
|
40
|
+
? rootFile.getDirectoryFromPathGiven(config.file).concat('/')
|
|
41
|
+
: config.file;
|
|
42
|
+
filesFound = await autoDetection.autoDetectAuditFilesAndLanguages(config.file);
|
|
43
|
+
autoDetection.dealWithMultiJava(filesFound);
|
|
44
|
+
if (filesFound.length > 1 && pathWithFile) {
|
|
45
|
+
filesFound = filesFound.filter(i => Object.values(i)[0].includes(path.basename(config.fileName)));
|
|
46
|
+
}
|
|
47
|
+
let messageToSend = undefined;
|
|
48
|
+
if (filesFound.length === 1) {
|
|
49
|
+
switch (Object.keys(filesFound[0])[0]) {
|
|
50
|
+
case JAVA:
|
|
51
|
+
config.language = JAVA;
|
|
52
|
+
if (config.mode === 'repo') {
|
|
53
|
+
try {
|
|
54
|
+
return repoMode.buildRepo(config, filesFound[0]);
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
throw new Error('Unable to build in repository mode. Check your project file');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
messageToSend = await javaAnalysis.javaAnalysis(config, filesFound[0]);
|
|
62
|
+
}
|
|
63
|
+
break;
|
|
64
|
+
case JAVASCRIPT:
|
|
65
|
+
messageToSend = await jsAnalysis.jsAnalysis(config, filesFound[0]);
|
|
66
|
+
config.language = NODE;
|
|
67
|
+
break;
|
|
68
|
+
case PYTHON:
|
|
69
|
+
messageToSend = pythonAnalysis(config, filesFound[0]);
|
|
70
|
+
config.language = PYTHON;
|
|
71
|
+
break;
|
|
72
|
+
case RUBY:
|
|
73
|
+
messageToSend = rubyAnalysis(config, filesFound[0]);
|
|
74
|
+
config.language = RUBY;
|
|
75
|
+
break;
|
|
76
|
+
case PHP:
|
|
77
|
+
messageToSend = phpAnalysis(config, filesFound[0]);
|
|
78
|
+
config.language = PHP;
|
|
79
|
+
break;
|
|
80
|
+
case GO:
|
|
81
|
+
messageToSend = goAnalysis(config, filesFound[0]);
|
|
82
|
+
config.language = GO;
|
|
83
|
+
break;
|
|
84
|
+
case DOTNET:
|
|
85
|
+
if (config.experimental) {
|
|
86
|
+
console.log(`${chalk.bold('\n.NET project found\n')} Language type is unsupported.`);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
messageToSend = dotNetAnalysis(config, filesFound[0]);
|
|
91
|
+
config.language = DOTNET;
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
default:
|
|
95
|
+
console.log('No supported language detected in project path');
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (!config.applicationId) {
|
|
99
|
+
config.applicationId = await auditController.dealWithNoAppId(config);
|
|
100
|
+
}
|
|
101
|
+
if (config.experimental) {
|
|
102
|
+
console.log('');
|
|
103
|
+
const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'));
|
|
104
|
+
startSpinner(reportSpinner);
|
|
105
|
+
const { reportArray, reportId } = await scaUpload.scaTreeUpload(messageToSend, config);
|
|
106
|
+
const reportModelLibraryList = convertGenericToTypedReportModelSca(reportArray);
|
|
107
|
+
auditReport.processAuditReport(config, reportModelLibraryList);
|
|
108
|
+
succeedSpinner(reportSpinner, i18n.__('auditSCAAnalysisComplete'));
|
|
109
|
+
if (config.save !== undefined) {
|
|
110
|
+
await auditSave.auditSave(config, reportId);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
console.log('Use contrast audit --save to generate an SBOM');
|
|
114
|
+
}
|
|
115
|
+
const endTime = performance.now() - startTime;
|
|
116
|
+
const scanDurationMs = endTime - startTime;
|
|
117
|
+
console.log(`----- completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
console.log('');
|
|
121
|
+
const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'));
|
|
122
|
+
startSpinner(reportSpinner);
|
|
123
|
+
const snapshotResponse = await treeUpload.commonSendSnapShot(messageToSend, config);
|
|
124
|
+
await pollForSnapshotCompletion(config, snapshotResponse.id, reportSpinner);
|
|
125
|
+
succeedSpinner(reportSpinner, i18n.__('auditSCAAnalysisComplete'));
|
|
126
|
+
await vulnerabilityReportV2(config, snapshotResponse.id);
|
|
127
|
+
if (config.save !== undefined) {
|
|
128
|
+
await auditSave.auditSave(config);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
console.log('\nUse contrast audit --save to generate an SBOM');
|
|
132
|
+
}
|
|
133
|
+
const endTime = performance.now() - startTime;
|
|
134
|
+
const scanDurationMs = endTime - startTime;
|
|
135
|
+
console.log(`----- completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
if (filesFound.length === 0) {
|
|
140
|
+
console.log(i18n.__('languageAnalysisNoLanguage'));
|
|
141
|
+
console.log(i18n.__('languageAnalysisNoLanguageHelpLine'));
|
|
142
|
+
throw new Error();
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
console.log(chalk.bold(`\nMultiple language files detected \n`));
|
|
146
|
+
filesFound.forEach(file => {
|
|
147
|
+
console.log(`${Object.keys(file)[0]} : `, Object.values(file)[0]);
|
|
148
|
+
});
|
|
149
|
+
throw new Error(`Please use --file to audit one language only. \nExample: contrast audit --file package-lock.json`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
module.exports = {
|
|
154
|
+
processSca
|
|
155
|
+
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const i18n = require('i18n');
|
|
3
3
|
const fileFinder = require('./fileUtils');
|
|
4
|
-
const autoDetectFingerprintInfo = async (filePath) => {
|
|
5
|
-
let complexObj = await fileFinder.findAllFiles(filePath);
|
|
4
|
+
const autoDetectFingerprintInfo = async (filePath, depth) => {
|
|
5
|
+
let complexObj = await fileFinder.findAllFiles(filePath, depth);
|
|
6
6
|
let result = [];
|
|
7
7
|
let count = 0;
|
|
8
8
|
complexObj.forEach(i => {
|
package/dist/scan/fileUtils.js
CHANGED
|
@@ -10,7 +10,7 @@ const findFile = async () => {
|
|
|
10
10
|
onlyFiles: true
|
|
11
11
|
});
|
|
12
12
|
};
|
|
13
|
-
const findAllFiles = async (filePath) => {
|
|
13
|
+
const findAllFiles = async (filePath, depth = 2) => {
|
|
14
14
|
const result = await fg([
|
|
15
15
|
'**/pom.xml',
|
|
16
16
|
'**/build.gradle',
|
|
@@ -22,7 +22,7 @@ const findAllFiles = async (filePath) => {
|
|
|
22
22
|
'**/go.mod'
|
|
23
23
|
], {
|
|
24
24
|
dot: false,
|
|
25
|
-
deep:
|
|
25
|
+
deep: depth,
|
|
26
26
|
onlyFiles: true,
|
|
27
27
|
absolute: true,
|
|
28
28
|
cwd: filePath ? filePath : process.cwd()
|
package/dist/scan/help.js
CHANGED
|
@@ -4,6 +4,9 @@ const i18n = require('i18n');
|
|
|
4
4
|
const constants = require('../cliConstants');
|
|
5
5
|
const { commonHelpLinks } = require('../common/commonHelp');
|
|
6
6
|
const scanUsageGuide = commandLineUsage([
|
|
7
|
+
{
|
|
8
|
+
header: i18n.__('constantsHeader')
|
|
9
|
+
},
|
|
7
10
|
{
|
|
8
11
|
header: i18n.__('scanHeader')
|
|
9
12
|
},
|
|
@@ -43,7 +46,8 @@ const scanUsageGuide = commandLineUsage([
|
|
|
43
46
|
optionList: constants.commandLineDefinitions.scanAdvancedOptionDefinitionsForHelp
|
|
44
47
|
},
|
|
45
48
|
commonHelpLinks()[0],
|
|
46
|
-
commonHelpLinks()[1]
|
|
49
|
+
commonHelpLinks()[1],
|
|
50
|
+
commonHelpLinks()[2]
|
|
47
51
|
]);
|
|
48
52
|
module.exports = {
|
|
49
53
|
scanUsageGuide
|
|
@@ -11,9 +11,9 @@ const getSettings = async (config) => {
|
|
|
11
11
|
const isSCAServicesAvailable = async (config) => {
|
|
12
12
|
const client = commonApi.getHttpClient(config);
|
|
13
13
|
return client
|
|
14
|
-
.
|
|
14
|
+
.scaServiceHealth(config)
|
|
15
15
|
.then(res => {
|
|
16
|
-
return res.
|
|
16
|
+
return res.body.status === 'UP';
|
|
17
17
|
})
|
|
18
18
|
.catch(err => {
|
|
19
19
|
console.log(err);
|
package/package.json
CHANGED
package/src/cliConstants.js
CHANGED
|
@@ -212,6 +212,7 @@ const scanOptionDefinitions = [
|
|
|
212
212
|
|
|
213
213
|
const authOptionDefinitions = [
|
|
214
214
|
...sharedConnectionOptionDefinitions,
|
|
215
|
+
...sharedCertOptionDefinitions,
|
|
215
216
|
{
|
|
216
217
|
name: 'help',
|
|
217
218
|
alias: 'h',
|
|
@@ -337,10 +338,6 @@ const auditOptionDefinitions = [
|
|
|
337
338
|
'}: ' +
|
|
338
339
|
i18n.__('constantsIgnoreDev')
|
|
339
340
|
},
|
|
340
|
-
{
|
|
341
|
-
name: 'fingerprint',
|
|
342
|
-
type: Boolean
|
|
343
|
-
},
|
|
344
341
|
{
|
|
345
342
|
name: 'save',
|
|
346
343
|
alias: 's',
|
|
@@ -405,6 +402,16 @@ const auditOptionDefinitions = [
|
|
|
405
402
|
}
|
|
406
403
|
]
|
|
407
404
|
|
|
405
|
+
const fingerprintOptionDefinitions = [
|
|
406
|
+
...auditOptionDefinitions,
|
|
407
|
+
{
|
|
408
|
+
name: 'depth',
|
|
409
|
+
type: Number,
|
|
410
|
+
description:
|
|
411
|
+
'{bold ' + i18n.__('constantsOptional') + '}: ' + i18n.__('depthOption')
|
|
412
|
+
}
|
|
413
|
+
]
|
|
414
|
+
|
|
408
415
|
const mainUsageGuide = commandLineUsage([
|
|
409
416
|
{
|
|
410
417
|
header: i18n.__('constantsHeader'),
|
|
@@ -421,12 +428,13 @@ const mainUsageGuide = commandLineUsage([
|
|
|
421
428
|
header: i18n.__('constantsCommands'),
|
|
422
429
|
content: [
|
|
423
430
|
{ name: i18n.__('authName'), summary: i18n.__('helpAuthSummary') },
|
|
431
|
+
{ name: i18n.__('configName'), summary: i18n.__('helpConfigSummary') },
|
|
432
|
+
{ name: i18n.__('versionName'), summary: i18n.__('helpVersionSummary') },
|
|
433
|
+
{ name: i18n.__('auditName'), summary: i18n.__('helpAuditSummary') },
|
|
424
434
|
{ name: i18n.__('scanName'), summary: i18n.__('helpScanSummary') },
|
|
425
435
|
{ name: i18n.__('lambdaName'), summary: i18n.__('helpLambdaSummary') },
|
|
426
|
-
{ name: i18n.__('
|
|
427
|
-
{ name: i18n.__('
|
|
428
|
-
{ name: i18n.__('configName'), summary: i18n.__('helpConfigSummary') },
|
|
429
|
-
{ name: i18n.__('helpName'), summary: i18n.__('helpSummary') }
|
|
436
|
+
{ name: i18n.__('helpName'), summary: i18n.__('helpSummary') },
|
|
437
|
+
{ name: i18n.__('learnName'), summary: i18n.__('helpLearnSummary') }
|
|
430
438
|
]
|
|
431
439
|
},
|
|
432
440
|
{
|
|
@@ -440,7 +448,8 @@ const mainUsageGuide = commandLineUsage([
|
|
|
440
448
|
]
|
|
441
449
|
},
|
|
442
450
|
commonHelpLinks()[0],
|
|
443
|
-
commonHelpLinks()[1]
|
|
451
|
+
commonHelpLinks()[1],
|
|
452
|
+
commonHelpLinks()[2]
|
|
444
453
|
])
|
|
445
454
|
|
|
446
455
|
const mainDefinition = [{ name: 'command', defaultOption: true }]
|
|
@@ -450,6 +459,7 @@ module.exports = {
|
|
|
450
459
|
mainUsageGuide,
|
|
451
460
|
mainDefinition,
|
|
452
461
|
scanOptionDefinitions,
|
|
462
|
+
fingerprintOptionDefinitions,
|
|
453
463
|
auditOptionDefinitions,
|
|
454
464
|
authOptionDefinitions,
|
|
455
465
|
configOptionDefinitions,
|
|
@@ -4,6 +4,9 @@ const constants = require('../../cliConstants')
|
|
|
4
4
|
const { commonHelpLinks } = require('../../common/commonHelp')
|
|
5
5
|
|
|
6
6
|
const auditUsageGuide = commandLineUsage([
|
|
7
|
+
{
|
|
8
|
+
header: i18n.__('constantsHeader')
|
|
9
|
+
},
|
|
7
10
|
{
|
|
8
11
|
header: i18n.__('auditHeader'),
|
|
9
12
|
content: [i18n.__('auditHeaderMessage')]
|
|
@@ -62,7 +65,8 @@ const auditUsageGuide = commandLineUsage([
|
|
|
62
65
|
constants.commandLineDefinitions.auditAdvancedOptionDefinitionsForHelp
|
|
63
66
|
},
|
|
64
67
|
commonHelpLinks()[0],
|
|
65
|
-
commonHelpLinks()[1]
|
|
68
|
+
commonHelpLinks()[1],
|
|
69
|
+
commonHelpLinks()[2]
|
|
66
70
|
])
|
|
67
71
|
|
|
68
72
|
module.exports = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const auditConfig = require('./auditConfig')
|
|
2
2
|
const { auditUsageGuide } = require('./help')
|
|
3
|
-
const scaController = require('
|
|
3
|
+
const scaController = require('../../scaAnalysis/scaAnalysis')
|
|
4
4
|
const { sendTelemetryConfigAsObject } = require('../../telemetry/telemetry')
|
|
5
5
|
const { postRunMessage } = require('../../common/commonHelp')
|
|
6
6
|
|
|
@@ -101,6 +101,11 @@ const authUsageGuide = commandLineUsage([
|
|
|
101
101
|
{
|
|
102
102
|
header: i18n.__('constantsAuthUsageHeader'),
|
|
103
103
|
content: [i18n.__('constantsAuthUsageContents')]
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
header: i18n.__('constantsAdvancedOptions'),
|
|
107
|
+
optionList: constants.commandLineDefinitions.authOptionDefinitions,
|
|
108
|
+
hide: ['organization-id', 'api-key', 'authorization', 'host']
|
|
104
109
|
}
|
|
105
110
|
])
|
|
106
111
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const parsedCLIOptions = require('../../utils/parsedCLIOptions')
|
|
2
|
+
const constants = require('../../cliConstants')
|
|
3
|
+
const paramHandler = require('../../utils/paramsUtil/paramHandler')
|
|
4
|
+
|
|
5
|
+
const getFingerprintConfig = async (contrastConf, command, argv) => {
|
|
6
|
+
const fingerprintParameters = await parsedCLIOptions.getCommandLineArgsCustom(
|
|
7
|
+
contrastConf,
|
|
8
|
+
command,
|
|
9
|
+
argv,
|
|
10
|
+
constants.commandLineDefinitions.fingerprintOptionDefinitions
|
|
11
|
+
)
|
|
12
|
+
const paramsAuth = paramHandler.getAuth(fingerprintParameters)
|
|
13
|
+
|
|
14
|
+
return { ...paramsAuth, ...fingerprintParameters }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = {
|
|
18
|
+
getFingerprintConfig
|
|
19
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const fingerprintConfig = require('./fingerprintConfig')
|
|
2
|
+
const autoDetection = require('../../scan/autoDetection')
|
|
3
|
+
const saveResults = require('../../scan/saveResults')
|
|
4
|
+
const processFingerprint = async (contrastConf, argvMain) => {
|
|
5
|
+
const config = await fingerprintConfig.getFingerprintConfig(
|
|
6
|
+
contrastConf,
|
|
7
|
+
'fingerprint',
|
|
8
|
+
argvMain
|
|
9
|
+
)
|
|
10
|
+
let fingerprint = await autoDetection.autoDetectFingerprintInfo(
|
|
11
|
+
config.file,
|
|
12
|
+
config.depth
|
|
13
|
+
)
|
|
14
|
+
let idArray = fingerprint.map(x => x.id)
|
|
15
|
+
await saveResults.writeResultsToFile(fingerprint, 'fingerPrintInfo.json')
|
|
16
|
+
return console.log(idArray)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module.exports = {
|
|
20
|
+
processFingerprint
|
|
21
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const { openLearnPage } = require('./learn')
|
|
2
|
+
|
|
3
|
+
async function processLearn() {
|
|
4
|
+
console.log('Opening Contrast’s Secure Code Learning Hub...')
|
|
5
|
+
console.log(
|
|
6
|
+
'If the page does not open you can open it directly via https://www.contrastsecurity.com/developer/learn'
|
|
7
|
+
)
|
|
8
|
+
return openLearnPage()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
module.exports = {
|
|
12
|
+
processLearn
|
|
13
|
+
}
|
package/src/common/HTTPClient.js
CHANGED
|
@@ -254,6 +254,13 @@ HTTPClient.prototype.scaServiceIngests = function scaServiceIngests(config) {
|
|
|
254
254
|
return requestUtils.sendRequest({ method: 'get', options })
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
+
HTTPClient.prototype.scaServiceHealth = function scaServiceIngests(config) {
|
|
258
|
+
const options = _.cloneDeep(this.requestOptions)
|
|
259
|
+
let url = createScaServiceHealthURL(config)
|
|
260
|
+
options.url = url
|
|
261
|
+
return requestUtils.sendRequest({ method: 'get', options })
|
|
262
|
+
}
|
|
263
|
+
|
|
257
264
|
HTTPClient.prototype.getReportById = function getReportById(config, reportId) {
|
|
258
265
|
const options = _.cloneDeep(this.requestOptions)
|
|
259
266
|
if (config.ignoreDev) {
|
|
@@ -474,6 +481,10 @@ function createScaServiceIngestsURL(config) {
|
|
|
474
481
|
return `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/applications/${config.applicationId}/libraries/ingests`
|
|
475
482
|
}
|
|
476
483
|
|
|
484
|
+
function createScaServiceHealthURL(config) {
|
|
485
|
+
return `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/health`
|
|
486
|
+
}
|
|
487
|
+
|
|
477
488
|
function createScaServiceIngestURL(config) {
|
|
478
489
|
let baseUrl = `${config.host}/Contrast/api/sca/organizations/${config.organizationId}/applications/${config.applicationId}/libraries/ingests/tree`
|
|
479
490
|
baseUrl = config.track ? baseUrl.concat('?persist=true') : baseUrl
|
package/src/common/commonHelp.js
CHANGED
|
@@ -19,6 +19,11 @@ const commonHelpLinks = () => {
|
|
|
19
19
|
i18n.__('commonHelpLearnMoreEnterpriseHeader') +
|
|
20
20
|
i18n.__('commonHelpLearnMoreEnterpriseText')
|
|
21
21
|
]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
content: [
|
|
25
|
+
i18n.__('commonHelpLearnHeader') + i18n.__('commonHelpLearnText')
|
|
26
|
+
]
|
|
22
27
|
}
|
|
23
28
|
]
|
|
24
29
|
}
|
|
@@ -27,7 +32,7 @@ const postRunMessage = commandName => {
|
|
|
27
32
|
console.log('\n' + chalk.underline.bold('Other Features:'))
|
|
28
33
|
if (commandName !== 'scan')
|
|
29
34
|
console.log(
|
|
30
|
-
"'contrast scan' to run
|
|
35
|
+
"'contrast scan' to run Contrast's industry leading SAST scanner"
|
|
31
36
|
)
|
|
32
37
|
if (commandName !== 'audit')
|
|
33
38
|
console.log(
|
|
@@ -35,6 +40,11 @@ const postRunMessage = commandName => {
|
|
|
35
40
|
)
|
|
36
41
|
if (commandName !== 'lambda')
|
|
37
42
|
console.log("'contrast lambda' to secure your AWS serverless functions")
|
|
43
|
+
|
|
44
|
+
if (commandName !== 'learn')
|
|
45
|
+
console.log(
|
|
46
|
+
"'contrast learn' launches Contrast's Secure Code Learning Hub."
|
|
47
|
+
)
|
|
38
48
|
}
|
|
39
49
|
|
|
40
50
|
module.exports = {
|
package/src/constants/lambda.js
CHANGED
|
@@ -66,6 +66,7 @@ const lambda = {
|
|
|
66
66
|
'Scanning a function of an inactive account is not supported',
|
|
67
67
|
not_supported_runtime:
|
|
68
68
|
'Scanning resource of runtime "{{runtime}}" is not supported.\nSupported runtimes: {{supportedRuntimes}}',
|
|
69
|
+
not_supported_lambda: 'This function cannot be scanned',
|
|
69
70
|
not_supported_onboard_account:
|
|
70
71
|
'Scanning a function of onboard account is not supported',
|
|
71
72
|
scan_lock:
|
package/src/constants/locales.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const { lambda } = require('./lambda')
|
|
2
2
|
const chalk = require('chalk')
|
|
3
|
+
const { APP_VERSION } = require('./constants')
|
|
3
4
|
|
|
4
5
|
const en_locales = () => {
|
|
5
6
|
return {
|
|
@@ -83,7 +84,7 @@ const en_locales = () => {
|
|
|
83
84
|
' FAIL - Results detected vulnerabilities over accepted severity level',
|
|
84
85
|
constantsSeverity:
|
|
85
86
|
'Use with "contrast scan --fail --severity high" or "contrast audit --fail --severity high". Set the severity level to detect vulnerabilities or dependencies. Severity levels are critical, high, medium, low or note.',
|
|
86
|
-
constantsHeader:
|
|
87
|
+
constantsHeader: `Contrast CLI @ v${APP_VERSION}`,
|
|
87
88
|
configHeader2: 'Config options',
|
|
88
89
|
clearHeader: '-c, --clear',
|
|
89
90
|
clearContent: 'Removes stored credentials',
|
|
@@ -160,13 +161,13 @@ const en_locales = () => {
|
|
|
160
161
|
scanErrorFileMessage:
|
|
161
162
|
'We only accept the following file types: \nJava - .jar, .war \nJavaScript - .js or .zip files',
|
|
162
163
|
helpAuthSummary:
|
|
163
|
-
'Authenticate Contrast using your Github or Google account',
|
|
164
|
+
'Authenticate Contrast using your Github or Google account OR include credentials if you are an existing licensed Contrast user.',
|
|
164
165
|
helpAuditSummary:
|
|
165
|
-
'Searches for a suitable file in the working directory to perform a security audit of dependencies and returns the results. [
|
|
166
|
+
'Searches for a suitable file in the working directory to perform a security audit of dependencies and returns the results. \n[audit --help for options] Java, .NET, Node, Ruby, Python, Go, PHP are supported. ',
|
|
166
167
|
helpScanSummary:
|
|
167
|
-
'Searches for a .jar, .war, .js, or .zip file in the working directory, uploads files for analysis, and returns the results. [
|
|
168
|
+
'Searches for a .jar, .war, .js, or .zip file in the working directory, uploads files for analysis, and returns the results. \n[scan --help for options] Java, .NET, .NET Core, JavaScript are supported. ',
|
|
168
169
|
helpLambdaSummary:
|
|
169
|
-
'Performs a static security scan on an AWS lambda function. lambda --help
|
|
170
|
+
'Performs a static security scan on an AWS lambda function. [lambda --help for options] AWS Lambda - Java & Python are supported. ',
|
|
170
171
|
helpVersionSummary: 'Displays version of Contrast CLI',
|
|
171
172
|
helpConfigSummary: 'Displays stored credentials',
|
|
172
173
|
helpSummary: 'Displays usage guide',
|
|
@@ -177,6 +178,12 @@ const en_locales = () => {
|
|
|
177
178
|
versionName: 'version',
|
|
178
179
|
configName: 'config',
|
|
179
180
|
helpName: 'help',
|
|
181
|
+
learnName: 'learn',
|
|
182
|
+
helpLearnSummary: 'Launches Contrast’s Secure Code Learning Hub.',
|
|
183
|
+
fingerprintName:
|
|
184
|
+
'assess repo to see how many languages it can detect. For use in pipeline only.',
|
|
185
|
+
depthOption:
|
|
186
|
+
'can set how deep in the file system the cli looks for language files',
|
|
180
187
|
scanOptionsLanguageSummary: 'Valid values are JAVA, JAVASCRIPT and DOTNET',
|
|
181
188
|
scanOptionsTimeoutSummary:
|
|
182
189
|
'Time in seconds to wait for scan to complete. Default value is 300 seconds.',
|
|
@@ -196,7 +203,7 @@ const en_locales = () => {
|
|
|
196
203
|
chalk.bold('\ncontrast audit') +
|
|
197
204
|
' to find vulnerabilities in your open source dependencies.' +
|
|
198
205
|
'\nSupports Java, .NET, Node, Ruby, Python, Go and PHP.' +
|
|
199
|
-
'\nOur CLI runs native build tools to generate a complete dependency tree.' +
|
|
206
|
+
'\n\nOur CLI runs native build tools to generate a complete dependency tree.' +
|
|
200
207
|
'\nIf you are running on untrusted code, consider running in a sandbox.\n' +
|
|
201
208
|
chalk.bold('\ncontrast lambda') +
|
|
202
209
|
' to secure your AWS serverless functions. \nSupports Java and Python \n' +
|
|
@@ -210,7 +217,7 @@ const en_locales = () => {
|
|
|
210
217
|
searchingScanFileDirectory: 'Searching for file to scan from %s...',
|
|
211
218
|
searchingAuditFileDirectory:
|
|
212
219
|
'Searching for package manager files from %s...',
|
|
213
|
-
scanHeader:
|
|
220
|
+
scanHeader: `Contrast Scan CLI`,
|
|
214
221
|
authHeader: 'Auth',
|
|
215
222
|
lambdaHeader: 'Contrast Lambda CLI',
|
|
216
223
|
lambdaSummary:
|
|
@@ -251,7 +258,7 @@ const en_locales = () => {
|
|
|
251
258
|
'An error has occurred when trying to get the Project Id please check your internet connection or provide the Project Id manually',
|
|
252
259
|
internalServerErrorHeader: '500 error - Internal server error',
|
|
253
260
|
resourceLockedErrorHeader: '423 error - Resource is locked',
|
|
254
|
-
auditHeader: 'Contrast
|
|
261
|
+
auditHeader: 'Contrast Audit CLI',
|
|
255
262
|
auditHeaderMessage:
|
|
256
263
|
"Use 'contrast audit' to analyze a project’s dependencies for vulnerabilities.",
|
|
257
264
|
constantsAuditPrerequisitesContentSupportedLanguages:
|
|
@@ -320,12 +327,21 @@ const en_locales = () => {
|
|
|
320
327
|
commonHelpJoinDiscussionHeader: chalk.hex('#9DC184')(
|
|
321
328
|
'Join the discussion:'
|
|
322
329
|
),
|
|
323
|
-
commonHelpJoinDiscussionText:
|
|
330
|
+
commonHelpJoinDiscussionText:
|
|
331
|
+
' https://www.contrastsecurity.com/developer/community',
|
|
332
|
+
commonHelpLearnHeader:
|
|
333
|
+
chalk.hex('#ffe599')('\r Want to UP your game?') +
|
|
334
|
+
" type 'contrast learn'",
|
|
335
|
+
commonHelpLearnText: `\n💰 Advance your security knowledge and become an ${chalk.hex(
|
|
336
|
+
'#ffd966'
|
|
337
|
+
)('All-star coder')} ⭐ with ${chalk.bold(
|
|
338
|
+
'Contrast Secure Code Learning Hub.'
|
|
339
|
+
)} 😺`,
|
|
324
340
|
authCommand: {
|
|
325
341
|
credentialsAccepted: {
|
|
326
|
-
title: 'Credentials
|
|
327
|
-
body: '
|
|
328
|
-
extra: '
|
|
342
|
+
title: '✔ Credentials successfully saved',
|
|
343
|
+
body: `\n${chalk.bold('Contrast CLI')}`,
|
|
344
|
+
extra: 'Scan, secure and ship your code in minutes.'
|
|
329
345
|
},
|
|
330
346
|
credentialsMissing: {
|
|
331
347
|
title: 'Credentials missing',
|
package/src/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { processAudit } from './commands/audit/processAudit'
|
|
|
5
5
|
import { processAuth } from './commands/auth/auth'
|
|
6
6
|
import { processConfig } from './commands/config/config'
|
|
7
7
|
import { processScan } from './commands/scan/processScan'
|
|
8
|
+
import { processFingerprint } from './commands/fingerprint/processFingerprint'
|
|
8
9
|
import constants from './cliConstants'
|
|
9
10
|
import { APP_NAME, APP_VERSION } from './constants/constants'
|
|
10
11
|
import { processLambda } from './lambda/lambda'
|
|
@@ -15,6 +16,7 @@ import {
|
|
|
15
16
|
} from './common/versionChecker'
|
|
16
17
|
import { findCommandOnError } from './common/errorHandling'
|
|
17
18
|
import { sendTelemetryConfigAsConfObj } from './telemetry/telemetry'
|
|
19
|
+
import { processLearn } from './commands/learn/processLearn'
|
|
18
20
|
const {
|
|
19
21
|
commandLineDefinitions: { mainUsageGuide, mainDefinition }
|
|
20
22
|
} = constants
|
|
@@ -82,6 +84,14 @@ const start = async () => {
|
|
|
82
84
|
return await processAudit(config, argvMain)
|
|
83
85
|
}
|
|
84
86
|
|
|
87
|
+
if (command === 'learn') {
|
|
88
|
+
return processLearn()
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (command === 'fingerprint') {
|
|
92
|
+
return await processFingerprint(config, argvMain)
|
|
93
|
+
}
|
|
94
|
+
|
|
85
95
|
if (
|
|
86
96
|
command === 'help' ||
|
|
87
97
|
argvMain.includes('--help') ||
|
package/src/lambda/help.ts
CHANGED
|
@@ -3,6 +3,9 @@ import i18n from 'i18n'
|
|
|
3
3
|
import { commonHelpLinks } from '../common/commonHelp'
|
|
4
4
|
|
|
5
5
|
const lambdaUsageGuide = commandLineUsage([
|
|
6
|
+
{
|
|
7
|
+
header: i18n.__('constantsHeader')
|
|
8
|
+
},
|
|
6
9
|
{
|
|
7
10
|
header: i18n.__('lambdaHeader'),
|
|
8
11
|
content: [i18n.__('lambdaSummary')]
|
|
@@ -82,7 +85,8 @@ const lambdaUsageGuide = commandLineUsage([
|
|
|
82
85
|
]
|
|
83
86
|
},
|
|
84
87
|
commonHelpLinks()[0],
|
|
85
|
-
commonHelpLinks()[1]
|
|
88
|
+
commonHelpLinks()[1],
|
|
89
|
+
commonHelpLinks()[2]
|
|
86
90
|
])
|
|
87
91
|
|
|
88
92
|
export { lambdaUsageGuide }
|