@contrast/contrast 1.0.22 → 2.0.0
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/README.md +21 -138
- package/dist/audit/languageAnalysisEngine/sendSnapshot.js +2 -19
- package/dist/audit/report/commonReportingFunctions.js +1 -1
- package/dist/audit/save.js +16 -5
- package/dist/cliConstants.js +29 -0
- package/dist/commands/audit/auditController.js +2 -1
- package/dist/commands/audit/help.js +3 -3
- package/dist/commands/audit/processAudit.js +3 -1
- package/dist/commands/audit/saveFile.js +5 -1
- package/dist/commands/github/projectGroup.js +164 -0
- package/dist/common/HTTPClient.js +165 -13
- package/dist/constants/constants.js +3 -5
- package/dist/constants/locales.js +7 -3
- package/dist/index.js +0 -4
- package/dist/lambda/lambda.js +3 -1
- package/dist/sbom/generateSbom.js +7 -0
- package/dist/scaAnalysis/common/commonReportingFunctionsSca.js +6 -6
- package/dist/scaAnalysis/common/scaServicesUpload.js +77 -7
- package/dist/scaAnalysis/common/treeUpload.js +1 -1
- package/dist/scaAnalysis/go/goAnalysis.js +1 -1
- package/dist/scaAnalysis/java/analysis.js +24 -32
- package/dist/scaAnalysis/java/index.js +1 -1
- package/dist/scaAnalysis/javascript/index.js +3 -3
- package/dist/scaAnalysis/legacy/legacyFlow.js +33 -0
- package/dist/scaAnalysis/php/index.js +1 -1
- package/dist/scaAnalysis/processServicesFlow.js +21 -0
- package/dist/scaAnalysis/python/analysis.js +1 -1
- package/dist/scaAnalysis/python/index.js +1 -1
- package/dist/scaAnalysis/repoMode/index.js +2 -2
- package/dist/scaAnalysis/ruby/analysis.js +1 -1
- package/dist/scaAnalysis/ruby/index.js +1 -1
- package/dist/scaAnalysis/scaAnalysis.js +16 -36
- package/dist/scan/autoDetection.js +41 -2
- package/dist/scan/fileUtils.js +5 -4
- package/dist/utils/commonApi.js +26 -1
- package/dist/utils/settingsHelper.js +7 -17
- package/package.json +6 -6
- package/src/audit/languageAnalysisEngine/sendSnapshot.js +3 -22
- package/src/audit/report/commonReportingFunctions.js +1 -1
- package/src/audit/save.js +21 -10
- package/src/cliConstants.js +32 -0
- package/src/commands/audit/auditController.js +2 -1
- package/src/commands/audit/help.js +3 -3
- package/src/commands/audit/processAudit.js +4 -5
- package/src/commands/audit/saveFile.js +6 -1
- package/src/commands/github/projectGroup.js +187 -0
- package/src/common/HTTPClient.js +221 -13
- package/src/constants/constants.js +3 -5
- package/src/constants/locales.js +9 -3
- package/src/index.ts +0 -5
- package/src/lambda/lambda.ts +3 -1
- package/src/lambda/lambdaUtils.ts +1 -1
- package/src/sbom/generateSbom.ts +8 -0
- package/src/scaAnalysis/common/commonReportingFunctionsSca.js +6 -6
- package/src/scaAnalysis/common/scaServicesUpload.js +92 -7
- package/src/scaAnalysis/common/treeUpload.js +1 -1
- package/src/scaAnalysis/go/goAnalysis.js +1 -1
- package/src/scaAnalysis/java/analysis.js +29 -34
- package/src/scaAnalysis/java/index.js +1 -1
- package/src/scaAnalysis/javascript/index.js +3 -6
- package/src/scaAnalysis/legacy/legacyFlow.js +48 -0
- package/src/scaAnalysis/php/index.js +1 -1
- package/src/scaAnalysis/processServicesFlow.js +29 -0
- package/src/scaAnalysis/python/analysis.js +1 -1
- package/src/scaAnalysis/python/index.js +1 -1
- package/src/scaAnalysis/repoMode/index.js +2 -2
- package/src/scaAnalysis/ruby/analysis.js +1 -1
- package/src/scaAnalysis/ruby/index.js +1 -1
- package/src/scaAnalysis/scaAnalysis.js +21 -57
- package/src/scan/autoDetection.js +44 -3
- package/src/scan/fileUtils.js +5 -4
- package/src/utils/commonApi.js +29 -1
- package/src/utils/settingsHelper.js +8 -18
- package/dist/commands/fingerprint/processFingerprint.js +0 -14
- package/src/commands/fingerprint/processFingerprint.js +0 -21
- /package/dist/commands/{fingerprint → github}/fingerprintConfig.js +0 -0
- /package/src/commands/{fingerprint → github}/fingerprintConfig.js +0 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const auditController = require('../../commands/audit/auditController');
|
|
3
|
+
const { returnOra, startSpinner, succeedSpinner } = require('../../utils/oraWrapper');
|
|
4
|
+
const i18n = require('i18n');
|
|
5
|
+
const treeUpload = require('../common/treeUpload');
|
|
6
|
+
const { pollForSnapshotCompletion } = require('../../audit/languageAnalysisEngine/sendSnapshot');
|
|
7
|
+
const { vulnerabilityReportV2 } = require('../../audit/report/reportingFeature');
|
|
8
|
+
const { auditSave } = require('../../audit/save');
|
|
9
|
+
const legacyFlow = async (config, messageToSend) => {
|
|
10
|
+
const startTime = performance.now();
|
|
11
|
+
if (!config.applicationId) {
|
|
12
|
+
config.applicationId = await auditController.dealWithNoAppId(config);
|
|
13
|
+
}
|
|
14
|
+
console.log('');
|
|
15
|
+
const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'));
|
|
16
|
+
startSpinner(reportSpinner);
|
|
17
|
+
const snapshotResponse = await treeUpload.commonSendSnapShot(messageToSend, config);
|
|
18
|
+
await pollForSnapshotCompletion(config, snapshotResponse.id, reportSpinner);
|
|
19
|
+
succeedSpinner(reportSpinner, i18n.__('auditSCAAnalysisComplete'));
|
|
20
|
+
await vulnerabilityReportV2(config, snapshotResponse.id);
|
|
21
|
+
if (config.save !== undefined) {
|
|
22
|
+
await auditSave(config);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
console.log('\nUse contrast audit --save to generate an SBOM');
|
|
26
|
+
}
|
|
27
|
+
const endTime = performance.now() - startTime;
|
|
28
|
+
const scanDurationMs = endTime - startTime;
|
|
29
|
+
console.log(`----- completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`);
|
|
30
|
+
};
|
|
31
|
+
module.exports = {
|
|
32
|
+
legacyFlow
|
|
33
|
+
};
|
|
@@ -4,7 +4,7 @@ const { createPhpTSMessage } = require('../common/formatMessage');
|
|
|
4
4
|
const { parsePHPLockFileForScaServices } = require('./phpNewServicesMapper');
|
|
5
5
|
const phpAnalysis = config => {
|
|
6
6
|
let analysis = readFiles(config);
|
|
7
|
-
if (config.
|
|
7
|
+
if (config.legacy === false) {
|
|
8
8
|
return parsePHPLockFileForScaServices(analysis.rawLockFileContents);
|
|
9
9
|
}
|
|
10
10
|
else {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const projectConfig = require('../commands/github/projectGroup');
|
|
3
|
+
const scaServicesUpload = require('../scaAnalysis/common/scaServicesUpload');
|
|
4
|
+
const processUpload = async (analysis, config, reportSpinner) => {
|
|
5
|
+
let projectId = await projectConfig.getProjectIdByOrg(config);
|
|
6
|
+
if (projectId === '') {
|
|
7
|
+
if (config.track === true) {
|
|
8
|
+
await projectConfig.registerNewProjectGroup(config);
|
|
9
|
+
projectId = await projectConfig.getProjectIdByOrg(config);
|
|
10
|
+
}
|
|
11
|
+
if (config.track === false || config.track === undefined) {
|
|
12
|
+
return await scaServicesUpload.noProjectUpload(analysis, config, reportSpinner);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
await projectConfig.registerProjectIdOnCliServices(config, projectId);
|
|
16
|
+
config.projectId = projectId;
|
|
17
|
+
return await scaServicesUpload.scaTreeUpload(analysis, config, reportSpinner);
|
|
18
|
+
};
|
|
19
|
+
module.exports = {
|
|
20
|
+
processUpload
|
|
21
|
+
};
|
|
@@ -48,7 +48,7 @@ const checkForCorrectFiles = languageFiles => {
|
|
|
48
48
|
};
|
|
49
49
|
const getPythonDeps = (config, languageFiles) => {
|
|
50
50
|
try {
|
|
51
|
-
if (config.
|
|
51
|
+
if (config.legacy === false) {
|
|
52
52
|
let pythonLockFileContents = readLockFile(config.file);
|
|
53
53
|
return scaPythonParser(pythonLockFileContents);
|
|
54
54
|
}
|
|
@@ -3,7 +3,7 @@ const { createPythonTSMessage } = require('../common/formatMessage');
|
|
|
3
3
|
const { getPythonDeps, secondaryParser } = require('./analysis');
|
|
4
4
|
const pythonAnalysis = (config, languageFiles) => {
|
|
5
5
|
const pythonDeps = getPythonDeps(config, languageFiles.PYTHON);
|
|
6
|
-
if (config.
|
|
6
|
+
if (config.legacy === false) {
|
|
7
7
|
return pythonDeps;
|
|
8
8
|
}
|
|
9
9
|
else {
|
|
@@ -6,11 +6,11 @@ const buildRepo = async (config, languageFiles) => {
|
|
|
6
6
|
const project = determineProjectTypeAndCwd(languageFiles.JAVA, config);
|
|
7
7
|
if (project.projectType === 'maven') {
|
|
8
8
|
let jsonPomFile = mavenParser.readPomFile(project);
|
|
9
|
-
mavenParser.parsePomFile(jsonPomFile);
|
|
9
|
+
return mavenParser.parsePomFile(jsonPomFile);
|
|
10
10
|
}
|
|
11
11
|
else if (project.projectType === 'gradle') {
|
|
12
12
|
const gradleJson = gradleParser.readBuildGradleFile(project);
|
|
13
|
-
gradleParser.parseGradleJson(await gradleJson);
|
|
13
|
+
return gradleParser.parseGradleJson(await gradleJson);
|
|
14
14
|
}
|
|
15
15
|
else {
|
|
16
16
|
console.log('Unable to read project files.');
|
|
@@ -6,7 +6,7 @@ const getRubyDeps = (config, languageFiles) => {
|
|
|
6
6
|
checkForCorrectFiles(languageFiles);
|
|
7
7
|
const parsedGem = readAndParseGemfile(config.file);
|
|
8
8
|
const parsedLock = readAndParseGemLockFile(config.file);
|
|
9
|
-
if (config.
|
|
9
|
+
if (config.legacy === false) {
|
|
10
10
|
const rubyArray = removeRedundantAndPopulateDefinedElements(parsedLock.sources);
|
|
11
11
|
let rubyTree = createRubyTree(rubyArray);
|
|
12
12
|
findChildrenDependencies(rubyTree);
|
|
@@ -3,7 +3,7 @@ const analysis = require('./analysis');
|
|
|
3
3
|
const { createRubyTSMessage } = require('../common/formatMessage');
|
|
4
4
|
const rubyAnalysis = (config, languageFiles) => {
|
|
5
5
|
const rubyDeps = analysis.getRubyDeps(config, languageFiles.RUBY);
|
|
6
|
-
if (config.
|
|
6
|
+
if (config.legacy === false) {
|
|
7
7
|
return rubyDeps;
|
|
8
8
|
}
|
|
9
9
|
else {
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const { supportedLanguages: { JAVA, GO, PYTHON, RUBY, JAVASCRIPT, NODE, PHP, DOTNET } } = require('../constants/constants');
|
|
3
|
-
const { pollForSnapshotCompletion } = require('../audit/languageAnalysisEngine/sendSnapshot');
|
|
4
3
|
const { returnOra, startSpinner, succeedSpinner } = require('../utils/oraWrapper');
|
|
5
|
-
const { vulnerabilityReportV2 } = require('../audit/report/reportingFeature');
|
|
6
4
|
const autoDetection = require('../scan/autoDetection');
|
|
7
|
-
const treeUpload = require('./common/treeUpload');
|
|
8
|
-
const auditController = require('../commands/audit/auditController');
|
|
9
5
|
const rootFile = require('../audit/languageAnalysisEngine/getProjectRootFilenames');
|
|
10
6
|
const path = require('path');
|
|
11
7
|
const i18n = require('i18n');
|
|
@@ -20,14 +16,12 @@ const { pythonAnalysis } = require('./python');
|
|
|
20
16
|
const javaAnalysis = require('./java');
|
|
21
17
|
const jsAnalysis = require('./javascript');
|
|
22
18
|
const auditReport = require('./common/auditReport');
|
|
23
|
-
const
|
|
24
|
-
const settingsHelper = require('../utils/settingsHelper');
|
|
19
|
+
const processServices = require('./processServicesFlow');
|
|
25
20
|
const chalk = require('chalk');
|
|
26
|
-
const saveResults = require('../scan/saveResults');
|
|
27
21
|
const { convertGenericToTypedReportModelSca } = require('./common/utils/reportUtilsSca');
|
|
22
|
+
const projectConfig = require('../commands/github/projectGroup');
|
|
23
|
+
const { legacyFlow } = require('./legacy/legacyFlow');
|
|
28
24
|
const processSca = async (config) => {
|
|
29
|
-
config = await settingsHelper.getSettings(config);
|
|
30
|
-
const startTime = performance.now();
|
|
31
25
|
let filesFound;
|
|
32
26
|
if (config.help) {
|
|
33
27
|
console.log(auditUsageGuide);
|
|
@@ -49,9 +43,9 @@ const processSca = async (config) => {
|
|
|
49
43
|
switch (Object.keys(filesFound[0])[0]) {
|
|
50
44
|
case JAVA:
|
|
51
45
|
config.language = JAVA;
|
|
52
|
-
if (config.
|
|
46
|
+
if (config.repo && !config.legacy) {
|
|
53
47
|
try {
|
|
54
|
-
|
|
48
|
+
messageToSend = await repoMode.buildRepo(config, filesFound[0]);
|
|
55
49
|
}
|
|
56
50
|
catch (e) {
|
|
57
51
|
throw new Error('Unable to build in repository mode. Check your project file');
|
|
@@ -82,7 +76,7 @@ const processSca = async (config) => {
|
|
|
82
76
|
config.language = GO;
|
|
83
77
|
break;
|
|
84
78
|
case DOTNET:
|
|
85
|
-
if (config.
|
|
79
|
+
if (config.legacy === false) {
|
|
86
80
|
console.log(`${chalk.bold('\n.NET project found\n')} Language type is unsupported.`);
|
|
87
81
|
return;
|
|
88
82
|
}
|
|
@@ -95,44 +89,30 @@ const processSca = async (config) => {
|
|
|
95
89
|
console.log('No supported language detected in project path');
|
|
96
90
|
return;
|
|
97
91
|
}
|
|
98
|
-
if (
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
92
|
+
if (config.legacy === false) {
|
|
93
|
+
if (!config.name) {
|
|
94
|
+
config = await projectConfig.dealWithNoName(config);
|
|
95
|
+
}
|
|
96
|
+
const startTime = performance.now();
|
|
102
97
|
console.log('');
|
|
103
98
|
const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'));
|
|
104
99
|
startSpinner(reportSpinner);
|
|
105
|
-
|
|
106
|
-
const reportModelLibraryList = convertGenericToTypedReportModelSca(reportArray);
|
|
100
|
+
let reportResponse = await processServices.processUpload(messageToSend, config, reportSpinner);
|
|
101
|
+
const reportModelLibraryList = convertGenericToTypedReportModelSca(reportResponse.reportArray);
|
|
107
102
|
auditReport.processAuditReport(config, reportModelLibraryList);
|
|
108
|
-
succeedSpinner(reportSpinner, i18n.__('auditSCAAnalysisComplete'));
|
|
109
103
|
if (config.save !== undefined) {
|
|
110
|
-
await auditSave.auditSave(config, reportId);
|
|
104
|
+
await auditSave.auditSave(config, reportResponse.reportId);
|
|
111
105
|
}
|
|
112
106
|
else {
|
|
113
107
|
console.log('Use contrast audit --save to generate an SBOM');
|
|
114
108
|
}
|
|
109
|
+
succeedSpinner(reportSpinner, i18n.__('auditSCAAnalysisComplete'));
|
|
115
110
|
const endTime = performance.now() - startTime;
|
|
116
111
|
const scanDurationMs = endTime - startTime;
|
|
117
112
|
console.log(`----- completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`);
|
|
118
113
|
}
|
|
119
114
|
else {
|
|
120
|
-
|
|
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 -----`);
|
|
115
|
+
await legacyFlow(config, messageToSend);
|
|
136
116
|
}
|
|
137
117
|
}
|
|
138
118
|
else {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const i18n = require('i18n');
|
|
3
3
|
const fileFinder = require('./fileUtils');
|
|
4
|
+
const { supportedLanguages: { JAVA, GO, PYTHON, RUBY, JAVASCRIPT, NODE, PHP, DOTNET } } = require('../constants/constants');
|
|
4
5
|
const autoDetectFingerprintInfo = async (filePath, depth) => {
|
|
5
6
|
let complexObj = await fileFinder.findAllFiles(filePath, depth);
|
|
6
7
|
let result = [];
|
|
@@ -11,6 +12,43 @@ const autoDetectFingerprintInfo = async (filePath, depth) => {
|
|
|
11
12
|
});
|
|
12
13
|
return result;
|
|
13
14
|
};
|
|
15
|
+
const detectPackageManager = async (array) => {
|
|
16
|
+
array.forEach(i => {
|
|
17
|
+
if (i.filePath.includes('pom.xml')) {
|
|
18
|
+
i['language'] = JAVA;
|
|
19
|
+
i['packageManager'] = 'MAVEN';
|
|
20
|
+
}
|
|
21
|
+
if (i.filePath.includes('build.gradle.kts')) {
|
|
22
|
+
i['language'] = JAVA;
|
|
23
|
+
i['packageManager'] = 'GRADLE';
|
|
24
|
+
}
|
|
25
|
+
if (i.filePath.includes('build.gradle')) {
|
|
26
|
+
i['language'] = JAVA;
|
|
27
|
+
i['packageManager'] = 'GRADLE';
|
|
28
|
+
}
|
|
29
|
+
if (i.filePath.includes('package.json')) {
|
|
30
|
+
i['language'] = JAVASCRIPT;
|
|
31
|
+
i['packageManager'] = 'NPM';
|
|
32
|
+
}
|
|
33
|
+
if (i.filePath.includes('yarn.lock')) {
|
|
34
|
+
i['language'] = JAVASCRIPT;
|
|
35
|
+
i['packageManager'] = 'YARN';
|
|
36
|
+
}
|
|
37
|
+
if (i.filePath.includes('Pipfile')) {
|
|
38
|
+
i['language'] = PYTHON;
|
|
39
|
+
}
|
|
40
|
+
if (i.filePath.includes('csproj')) {
|
|
41
|
+
i['language'] = DOTNET;
|
|
42
|
+
}
|
|
43
|
+
if (i.filePath.includes('Gemfile')) {
|
|
44
|
+
i['language'] = RUBY;
|
|
45
|
+
}
|
|
46
|
+
if (i.filePath.includes('go.mod')) {
|
|
47
|
+
i['language'] = GO;
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
return array;
|
|
51
|
+
};
|
|
14
52
|
const autoDetectFileAndLanguage = async (configToUse) => {
|
|
15
53
|
const entries = await fileFinder.findFile();
|
|
16
54
|
if (entries.length === 1) {
|
|
@@ -53,7 +91,7 @@ const hasWhiteSpace = s => {
|
|
|
53
91
|
};
|
|
54
92
|
const dealWithMultiJava = filesFound => {
|
|
55
93
|
let hasMultiJava = filesFound.filter(data => {
|
|
56
|
-
return (Object.keys(data)[0] ===
|
|
94
|
+
return (Object.keys(data)[0] === JAVA &&
|
|
57
95
|
Object.values(data)[0].includes('build.gradle') &&
|
|
58
96
|
Object.values(data)[0].includes('pom.xml'));
|
|
59
97
|
}).length > 0;
|
|
@@ -101,5 +139,6 @@ module.exports = {
|
|
|
101
139
|
autoDetectAuditFilesAndLanguages,
|
|
102
140
|
errorOnAuditFileDetection,
|
|
103
141
|
autoDetectFingerprintInfo,
|
|
104
|
-
dealWithMultiJava
|
|
142
|
+
dealWithMultiJava,
|
|
143
|
+
detectPackageManager
|
|
105
144
|
};
|
package/dist/scan/fileUtils.js
CHANGED
|
@@ -16,6 +16,7 @@ const findAllFiles = async (filePath, depth = 2) => {
|
|
|
16
16
|
'**/build.gradle',
|
|
17
17
|
'**/build.gradle.kts',
|
|
18
18
|
'**/package.json',
|
|
19
|
+
'**/yarn.lock',
|
|
19
20
|
'**/Pipfile',
|
|
20
21
|
'**/*.csproj',
|
|
21
22
|
'**/Gemfile',
|
|
@@ -32,15 +33,15 @@ const findAllFiles = async (filePath, depth = 2) => {
|
|
|
32
33
|
}
|
|
33
34
|
return [];
|
|
34
35
|
};
|
|
35
|
-
const findFilesJava = async (languagesFound, filePath) => {
|
|
36
|
+
const findFilesJava = async (languagesFound, filePath, depth = 1) => {
|
|
36
37
|
const result = await fg(['**/pom.xml', '**/build.gradle', '**/build.gradle.kts'], {
|
|
37
38
|
dot: false,
|
|
38
|
-
deep:
|
|
39
|
+
deep: depth,
|
|
39
40
|
onlyFiles: true,
|
|
40
41
|
cwd: filePath ? filePath : process.cwd()
|
|
41
42
|
});
|
|
42
43
|
if (result.length > 0) {
|
|
43
|
-
return languagesFound.push({ JAVA: result });
|
|
44
|
+
return languagesFound.push({ JAVA: result, language: 'JAVA' });
|
|
44
45
|
}
|
|
45
46
|
return languagesFound;
|
|
46
47
|
};
|
|
@@ -52,7 +53,7 @@ const findFilesJavascript = async (languagesFound, filePath) => {
|
|
|
52
53
|
cwd: filePath ? filePath : process.cwd()
|
|
53
54
|
});
|
|
54
55
|
if (result.length > 0) {
|
|
55
|
-
return languagesFound.push({ JAVASCRIPT: result });
|
|
56
|
+
return languagesFound.push({ JAVASCRIPT: result, language: 'JAVASCRIPT' });
|
|
56
57
|
}
|
|
57
58
|
return languagesFound;
|
|
58
59
|
};
|
package/dist/utils/commonApi.js
CHANGED
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const HttpClient = require('./../common/HTTPClient');
|
|
3
3
|
const { badRequestError, unauthenticatedError, forbiddenError, proxyError, genericError, maxAppError, snapshotFailureError, vulnerabilitiesFailureError, reportFailureError, parametersError, invalidHostNameError } = require('../common/errorHandling');
|
|
4
|
+
const { performance } = require('perf_hooks');
|
|
5
|
+
const requestUtils = require('./requestUtils');
|
|
6
|
+
const oraFunctions = require('./oraWrapper');
|
|
7
|
+
const getTimeout = config => {
|
|
8
|
+
if (config.timeout) {
|
|
9
|
+
return config.timeout;
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
if (config.verbose) {
|
|
13
|
+
console.log('Timeout set to 5 minutes');
|
|
14
|
+
}
|
|
15
|
+
return 300;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const handleTimeout = (startTime, timeout, reportSpinner) => {
|
|
19
|
+
const endTime = performance.now() - startTime;
|
|
20
|
+
if (requestUtils.millisToSeconds(endTime) > timeout) {
|
|
21
|
+
oraFunctions.failSpinner(reportSpinner, 'Contrast audit timed out at the specified timeout of ' +
|
|
22
|
+
timeout +
|
|
23
|
+
' seconds.');
|
|
24
|
+
throw new Error('You can update the timeout using --timeout');
|
|
25
|
+
}
|
|
26
|
+
};
|
|
4
27
|
const handleResponseErrors = (res, api) => {
|
|
5
28
|
if (res.statusCode === 400) {
|
|
6
29
|
api === 'catalogue' ? badRequestError(true) : badRequestError(false);
|
|
@@ -60,5 +83,7 @@ module.exports = {
|
|
|
60
83
|
getValidHost: getValidHost,
|
|
61
84
|
getProtocol: getProtocol,
|
|
62
85
|
handleResponseErrors: handleResponseErrors,
|
|
63
|
-
getHttpClient: getHttpClient
|
|
86
|
+
getHttpClient: getHttpClient,
|
|
87
|
+
handleTimeout: handleTimeout,
|
|
88
|
+
getTimeout: getTimeout
|
|
64
89
|
};
|
|
@@ -1,24 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const
|
|
3
|
-
const {
|
|
4
|
-
const { SAAS, MODE_BUILD } = require('../constants/constants');
|
|
2
|
+
const generalAPI = require('./generalAPI');
|
|
3
|
+
const { SAAS } = require('../constants/constants');
|
|
5
4
|
const getSettings = async (config) => {
|
|
6
|
-
config.isEOP =
|
|
7
|
-
|
|
8
|
-
config.
|
|
5
|
+
config.isEOP =
|
|
6
|
+
(await generalAPI.getMode(config)).toUpperCase() === SAAS ? false : true;
|
|
7
|
+
if (config.legacy === undefined) {
|
|
8
|
+
config.legacy = config.isEOP;
|
|
9
|
+
}
|
|
9
10
|
return config;
|
|
10
11
|
};
|
|
11
|
-
const isSCAServicesAvailable = async (config) => {
|
|
12
|
-
const client = commonApi.getHttpClient(config);
|
|
13
|
-
return client
|
|
14
|
-
.scaServiceHealth(config)
|
|
15
|
-
.then(res => {
|
|
16
|
-
return res.body.status === 'UP';
|
|
17
|
-
})
|
|
18
|
-
.catch(err => {
|
|
19
|
-
console.log(err);
|
|
20
|
-
});
|
|
21
|
-
};
|
|
22
12
|
module.exports = {
|
|
23
13
|
getSettings
|
|
24
14
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contrast/contrast",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Contrast Security's command line tool",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
"test-int": "jest ./test-integration/",
|
|
29
29
|
"test-int-scan": "jest ./test-integration/scan",
|
|
30
30
|
"test-int-audit": "jest test-integration/audit",
|
|
31
|
-
"test-int-audit-reports": "jest test-integration/audit/audit-language-reports.spec.js",
|
|
31
|
+
"test-int-audit-reports": "jest test-integration/audit/audit-language-reports-old-services.spec.js",
|
|
32
32
|
"test-int-scan-errors": "jest test-integration/scan/scanLocalErrors.spec.js",
|
|
33
33
|
"test-int-scan-reports": "jest test-integration/scan/scanReport.spec.js",
|
|
34
34
|
"test-int-audit-features": "jest test-integration/audit/auditFeatures/",
|
|
35
|
-
"test-int-audit-
|
|
35
|
+
"test-int-audit-projects": "jest test-integration/audit/audit-projects.spec.js",
|
|
36
36
|
"format": "prettier --write \"**/*.{ts,tsx,js,json,md,yml}\" .eslintrc.*",
|
|
37
37
|
"check-format": "prettier --check \"**/*.{ts,tsx,js,json,md,yml}\" .eslintrc.*",
|
|
38
38
|
"coverage-local": "nyc --reporter=text mocha './test/**/*.spec.js'",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"dotenv": "^16.0.0",
|
|
63
63
|
"fast-glob": "^3.2.11",
|
|
64
64
|
"gradle-to-js": "^2.0.1",
|
|
65
|
-
"i18n": "^0.
|
|
65
|
+
"i18n": "^0.15.1",
|
|
66
66
|
"js-yaml": "^4.1.0",
|
|
67
67
|
"lodash": "^4.17.21",
|
|
68
68
|
"log-symbols": "^4.1.0",
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
"husky": "^3.1.0",
|
|
95
95
|
"jest": "^27.5.1",
|
|
96
96
|
"jest-junit": "^13.2.0",
|
|
97
|
-
"mocha": "^
|
|
97
|
+
"mocha": "^10.2.0",
|
|
98
98
|
"npm-license-crawler": "^0.2.1",
|
|
99
99
|
"nyc": "^15.1.0",
|
|
100
100
|
"pkg": "^5.6.0",
|
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
"ts-jest": "^27.1.4",
|
|
104
104
|
"ts-node": "^10.7.0",
|
|
105
105
|
"typescript": "^4.6.3",
|
|
106
|
-
"uuid": "^
|
|
106
|
+
"uuid": "^9.0.0"
|
|
107
107
|
},
|
|
108
108
|
"resolutions": {
|
|
109
109
|
"faker": "5.5.3",
|
|
@@ -18,21 +18,10 @@ const pollSnapshotResults = async (config, snapshotId, client) => {
|
|
|
18
18
|
})
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
const getTimeout = config => {
|
|
22
|
-
if (config.timeout) {
|
|
23
|
-
return config.timeout
|
|
24
|
-
} else {
|
|
25
|
-
if (config.verbose) {
|
|
26
|
-
console.log('Timeout set to 5 minutes')
|
|
27
|
-
}
|
|
28
|
-
return 300
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
21
|
const pollForSnapshotCompletion = async (config, snapshotId, reportSpinner) => {
|
|
33
22
|
const client = commonApi.getHttpClient(config)
|
|
34
23
|
const startTime = performance.now()
|
|
35
|
-
const timeout = getTimeout(config)
|
|
24
|
+
const timeout = commonApi.getTimeout(config)
|
|
36
25
|
|
|
37
26
|
let complete = false
|
|
38
27
|
if (!_.isNil(snapshotId)) {
|
|
@@ -57,16 +46,8 @@ const pollForSnapshotCompletion = async (config, snapshotId, reportSpinner) => {
|
|
|
57
46
|
process.exit(1)
|
|
58
47
|
}
|
|
59
48
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
oraFunctions.failSpinner(
|
|
63
|
-
reportSpinner,
|
|
64
|
-
'Contrast audit timed out at the specified timeout of ' +
|
|
65
|
-
timeout +
|
|
66
|
-
' seconds.'
|
|
67
|
-
)
|
|
68
|
-
throw new Error('You can update the timeout using --timeout')
|
|
69
|
-
}
|
|
49
|
+
|
|
50
|
+
commonApi.handleTimeout(startTime, timeout, reportSpinner)
|
|
70
51
|
}
|
|
71
52
|
}
|
|
72
53
|
}
|
|
@@ -247,7 +247,7 @@ function buildBody(cveArray, advice) {
|
|
|
247
247
|
//todo different advice based on remediationGuidance being available or now
|
|
248
248
|
// console.log(advice)
|
|
249
249
|
|
|
250
|
-
const minOrMax = advice.
|
|
250
|
+
const minOrMax = advice.minimum ? advice.minimum : advice.maximum
|
|
251
251
|
const displayAdvice = minOrMax
|
|
252
252
|
? `Change to version ${chalk.bold(minOrMax)}`
|
|
253
253
|
: 'No recommendation is available according to our data. Upgrade to the latest stable is the best advice we can give.'
|
package/src/audit/save.js
CHANGED
|
@@ -10,6 +10,9 @@ const {
|
|
|
10
10
|
|
|
11
11
|
async function auditSave(config, reportId) {
|
|
12
12
|
let fileFormat
|
|
13
|
+
//validate the config to see if we can uppercase it
|
|
14
|
+
config.save = config.save ? config.save.toUpperCase() : config.save
|
|
15
|
+
|
|
13
16
|
switch (config.save) {
|
|
14
17
|
case null:
|
|
15
18
|
case SBOM_CYCLONE_DX_FILE:
|
|
@@ -23,26 +26,34 @@ async function auditSave(config, reportId) {
|
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
if (fileFormat) {
|
|
26
|
-
if (config.
|
|
27
|
-
|
|
29
|
+
if (config.legacy === false) {
|
|
30
|
+
const sbomResponse = await sbom.generateSCASbom(
|
|
28
31
|
config,
|
|
29
32
|
fileFormat,
|
|
30
|
-
|
|
33
|
+
reportId
|
|
31
34
|
)
|
|
35
|
+
if (sbomResponse) {
|
|
36
|
+
save.saveFile(config, fileFormat, sbomResponse)
|
|
37
|
+
}
|
|
32
38
|
} else {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
fileFormat,
|
|
36
|
-
|
|
37
|
-
)
|
|
39
|
+
const sbomResponse = await sbom.generateSbom(config, fileFormat)
|
|
40
|
+
if (sbomResponse) {
|
|
41
|
+
save.saveFile(config, fileFormat, sbomResponse)
|
|
42
|
+
}
|
|
38
43
|
}
|
|
39
|
-
|
|
44
|
+
|
|
45
|
+
let fileStart = config.legacy ? config.applicationId : config.projectId
|
|
46
|
+
if (fileStart === undefined) {
|
|
47
|
+
fileStart = 'my'
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const filename = `${fileStart}-sbom-${fileFormat}.json`
|
|
40
51
|
if (fs.existsSync(filename)) {
|
|
41
52
|
console.log(i18n.__('auditSBOMSaveSuccess') + ` - ${filename}`)
|
|
42
53
|
} else {
|
|
43
54
|
console.log(
|
|
44
55
|
chalk.yellow.bold(
|
|
45
|
-
`\
|
|
56
|
+
`\nUnable to save ${filename} Software Bill of Materials (SBOM)`
|
|
46
57
|
)
|
|
47
58
|
)
|
|
48
59
|
}
|
package/src/cliConstants.js
CHANGED
|
@@ -254,6 +254,14 @@ const auditAdvancedOptionDefinitionsForHelp = [
|
|
|
254
254
|
'}: ' +
|
|
255
255
|
i18n.__('constantsApplicationName')
|
|
256
256
|
},
|
|
257
|
+
{
|
|
258
|
+
name: 'name',
|
|
259
|
+
description:
|
|
260
|
+
'{bold ' +
|
|
261
|
+
i18n.__('constantsOptional') +
|
|
262
|
+
'}: ' +
|
|
263
|
+
i18n.__('constantsProjectName')
|
|
264
|
+
},
|
|
257
265
|
{
|
|
258
266
|
name: 'app-groups',
|
|
259
267
|
description:
|
|
@@ -399,6 +407,25 @@ const auditOptionDefinitions = [
|
|
|
399
407
|
i18n.__('constantsOptional') +
|
|
400
408
|
'}:' +
|
|
401
409
|
i18n.__('auditOptionsBranchSummary')
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
name: 'legacy',
|
|
413
|
+
alias: 'l',
|
|
414
|
+
type: Boolean,
|
|
415
|
+
description:
|
|
416
|
+
'{bold ' +
|
|
417
|
+
i18n.__('constantsOptional') +
|
|
418
|
+
'}:' +
|
|
419
|
+
i18n.__('auditOptionsLegacySummary')
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
name: 'repo',
|
|
423
|
+
type: Boolean,
|
|
424
|
+
description:
|
|
425
|
+
'{bold ' +
|
|
426
|
+
i18n.__('constantsOptional') +
|
|
427
|
+
'}:' +
|
|
428
|
+
i18n.__('auditOptionsRepoSummary')
|
|
402
429
|
}
|
|
403
430
|
]
|
|
404
431
|
|
|
@@ -409,6 +436,11 @@ const fingerprintOptionDefinitions = [
|
|
|
409
436
|
type: Number,
|
|
410
437
|
description:
|
|
411
438
|
'{bold ' + i18n.__('constantsOptional') + '}: ' + i18n.__('depthOption')
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
name: 'repoUrl',
|
|
442
|
+
type: String,
|
|
443
|
+
description: ''
|
|
412
444
|
}
|
|
413
445
|
]
|
|
414
446
|
|
|
@@ -3,6 +3,7 @@ const { auditUsageGuide } = require('./help')
|
|
|
3
3
|
const scaController = require('../../scaAnalysis/scaAnalysis')
|
|
4
4
|
const { sendTelemetryConfigAsObject } = require('../../telemetry/telemetry')
|
|
5
5
|
const { postRunMessage } = require('../../common/commonHelp')
|
|
6
|
+
const settingsHelper = require('../../utils/settingsHelper')
|
|
6
7
|
|
|
7
8
|
const processAudit = async (contrastConf, argvMain) => {
|
|
8
9
|
if (argvMain.indexOf('--help') !== -1) {
|
|
@@ -10,11 +11,9 @@ const processAudit = async (contrastConf, argvMain) => {
|
|
|
10
11
|
process.exit(0)
|
|
11
12
|
}
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
argvMain
|
|
17
|
-
)
|
|
14
|
+
let config = await auditConfig.getAuditConfig(contrastConf, 'audit', argvMain)
|
|
15
|
+
config = await settingsHelper.getSettings(config)
|
|
16
|
+
|
|
18
17
|
await scaController.processSca(config)
|
|
19
18
|
if (!config.fingerprint) {
|
|
20
19
|
postRunMessage('audit')
|