@contrast/contrast 1.0.23 → 2.0.1
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/save.js +6 -1
- package/dist/cliConstants.js +49 -0
- package/dist/commands/audit/auditController.js +2 -1
- package/dist/commands/audit/help.js +2 -3
- package/dist/commands/audit/processAudit.js +2 -0
- package/dist/commands/audit/saveFile.js +5 -1
- package/dist/commands/{fingerprint → github}/processFingerprint.js +6 -2
- package/dist/commands/github/projectGroup.js +174 -0
- package/dist/commands/github/repoServices.js +70 -0
- package/dist/common/HTTPClient.js +165 -13
- package/dist/common/errorHandling.js +1 -1
- package/dist/constants/constants.js +3 -5
- package/dist/constants/locales.js +7 -3
- package/dist/index.js +4 -4
- package/dist/lambda/lambda.js +3 -1
- package/dist/scaAnalysis/common/commonReportingFunctionsSca.js +3 -3
- package/dist/scaAnalysis/common/scaServicesUpload.js +77 -7
- package/dist/scaAnalysis/common/treeUpload.js +19 -5
- package/dist/scaAnalysis/go/goAnalysis.js +6 -1
- package/dist/scaAnalysis/java/index.js +6 -1
- package/dist/scaAnalysis/javascript/index.js +5 -2
- package/dist/scaAnalysis/legacy/legacyFlow.js +33 -0
- package/dist/scaAnalysis/php/index.js +8 -2
- package/dist/scaAnalysis/processServicesFlow.js +39 -0
- package/dist/scaAnalysis/python/analysis.js +10 -4
- package/dist/scaAnalysis/python/index.js +6 -1
- package/dist/scaAnalysis/repoMode/index.js +2 -2
- package/dist/scaAnalysis/ruby/analysis.js +10 -1
- package/dist/scaAnalysis/ruby/index.js +6 -1
- package/dist/scaAnalysis/scaAnalysis.js +47 -25
- package/dist/scan/autoDetection.js +47 -4
- package/dist/scan/fileUtils.js +5 -4
- package/dist/utils/commonApi.js +26 -1
- package/dist/utils/settingsHelper.js +14 -0
- package/package.json +8 -5
- package/src/audit/languageAnalysisEngine/sendSnapshot.js +3 -22
- package/src/audit/save.js +10 -1
- package/src/cliConstants.js +52 -0
- package/src/commands/audit/auditController.js +2 -1
- package/src/commands/audit/help.js +2 -3
- package/src/commands/audit/processAudit.js +2 -0
- package/src/commands/audit/saveFile.js +6 -1
- package/src/commands/{fingerprint → github}/processFingerprint.js +8 -2
- package/src/commands/github/projectGroup.js +198 -0
- package/src/commands/github/repoServices.js +80 -0
- package/src/common/HTTPClient.js +221 -13
- package/src/common/errorHandling.js +2 -2
- package/src/constants/constants.js +3 -5
- package/src/constants/locales.js +9 -3
- package/src/index.ts +5 -5
- package/src/lambda/lambda.ts +3 -1
- package/src/lambda/lambdaUtils.ts +1 -1
- package/src/scaAnalysis/common/commonReportingFunctionsSca.js +3 -3
- package/src/scaAnalysis/common/scaServicesUpload.js +92 -7
- package/src/scaAnalysis/common/treeUpload.js +20 -5
- package/src/scaAnalysis/go/goAnalysis.js +6 -1
- package/src/scaAnalysis/java/index.js +6 -1
- package/src/scaAnalysis/javascript/index.js +6 -4
- package/src/scaAnalysis/legacy/legacyFlow.js +48 -0
- package/src/scaAnalysis/php/index.js +8 -2
- package/src/scaAnalysis/processServicesFlow.js +61 -0
- package/src/scaAnalysis/python/analysis.js +10 -4
- package/src/scaAnalysis/python/index.js +6 -1
- package/src/scaAnalysis/repoMode/index.js +2 -2
- package/src/scaAnalysis/ruby/analysis.js +11 -1
- package/src/scaAnalysis/ruby/index.js +6 -1
- package/src/scaAnalysis/scaAnalysis.js +61 -37
- package/src/scan/autoDetection.js +50 -5
- package/src/scan/fileUtils.js +5 -4
- package/src/utils/commonApi.js +29 -1
- package/src/utils/settingsHelper.js +16 -0
- /package/dist/commands/{fingerprint → github}/fingerprintConfig.js +0 -0
- /package/src/commands/{fingerprint → github}/fingerprintConfig.js +0 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const projectConfig = require('../commands/github/projectGroup');
|
|
3
|
+
const scaServicesUpload = require('../scaAnalysis/common/scaServicesUpload');
|
|
4
|
+
const trackProcess = async (analysis, config, reportSpinner) => {
|
|
5
|
+
await projectConfig.registerNewProjectGroup(config);
|
|
6
|
+
let projectId = await projectConfig.getProjectIdByOrg(config);
|
|
7
|
+
await projectConfig.registerProjectIdOnCliServices(config, projectId);
|
|
8
|
+
config.projectId = projectId;
|
|
9
|
+
return await scaServicesUpload.scaTreeUpload(analysis, config, reportSpinner);
|
|
10
|
+
};
|
|
11
|
+
const repoProcess = async (analysis, config, reportSpinner) => {
|
|
12
|
+
let repoInfo = repoService.retrieveRepoId(config);
|
|
13
|
+
if (repoInfo.repoId === '') {
|
|
14
|
+
repoInfo = repoService.registerRepo(config);
|
|
15
|
+
}
|
|
16
|
+
await projectConfig.registerProjectIdOnCliServices(config, repoInfo.projectId);
|
|
17
|
+
return repoInfo;
|
|
18
|
+
};
|
|
19
|
+
const dealWithNoProjectId = async (analysis, config, reportSpinner) => {
|
|
20
|
+
if (config.track) {
|
|
21
|
+
return trackProcess(analysis, config, reportSpinner);
|
|
22
|
+
}
|
|
23
|
+
if (!config.track) {
|
|
24
|
+
return await scaServicesUpload.noProjectUpload(analysis, config, reportSpinner);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
const processUpload = async (analysis, config, reportSpinner) => {
|
|
28
|
+
let projectId = await projectConfig.getProjectIdByOrg(config);
|
|
29
|
+
if (projectId === '') {
|
|
30
|
+
return dealWithNoProjectId(analysis, config, reportSpinner);
|
|
31
|
+
}
|
|
32
|
+
if (projectId) {
|
|
33
|
+
config.projectId = projectId;
|
|
34
|
+
return await scaServicesUpload.scaTreeUpload(analysis, config, reportSpinner);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
module.exports = {
|
|
38
|
+
processUpload
|
|
39
|
+
};
|
|
@@ -48,10 +48,16 @@ const checkForCorrectFiles = languageFiles => {
|
|
|
48
48
|
};
|
|
49
49
|
const getPythonDeps = (config, languageFiles) => {
|
|
50
50
|
try {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
if (config.legacy === false) {
|
|
52
|
+
let pythonLockFileContents = readLockFile(config.file);
|
|
53
|
+
return scaPythonParser(pythonLockFileContents);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
checkForCorrectFiles(languageFiles);
|
|
57
|
+
const parseProject = readAndParseProjectFile(config.file);
|
|
58
|
+
const parsePip = readAndParseLockFile(config.file);
|
|
59
|
+
return { pipfileLock: parsePip, pipfilDependanceies: parseProject };
|
|
60
|
+
}
|
|
55
61
|
}
|
|
56
62
|
catch (err) {
|
|
57
63
|
console.log(err.message.toString());
|
|
@@ -3,7 +3,12 @@ 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
|
-
|
|
6
|
+
if (config.legacy === false) {
|
|
7
|
+
return pythonDeps;
|
|
8
|
+
}
|
|
9
|
+
else {
|
|
10
|
+
return createPythonTSMessage(pythonDeps);
|
|
11
|
+
}
|
|
7
12
|
};
|
|
8
13
|
module.exports = {
|
|
9
14
|
pythonAnalysis
|
|
@@ -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,16 @@ const getRubyDeps = (config, languageFiles) => {
|
|
|
6
6
|
checkForCorrectFiles(languageFiles);
|
|
7
7
|
const parsedGem = readAndParseGemfile(config.file);
|
|
8
8
|
const parsedLock = readAndParseGemLockFile(config.file);
|
|
9
|
-
|
|
9
|
+
if (config.legacy === false) {
|
|
10
|
+
const rubyArray = removeRedundantAndPopulateDefinedElements(parsedLock.sources);
|
|
11
|
+
let rubyTree = createRubyTree(rubyArray);
|
|
12
|
+
findChildrenDependencies(rubyTree);
|
|
13
|
+
processRootDependencies(parsedLock.dependencies, rubyTree);
|
|
14
|
+
return rubyTree;
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
return { gemfilesDependanceies: parsedGem, gemfileLock: parsedLock };
|
|
18
|
+
}
|
|
10
19
|
}
|
|
11
20
|
catch (err) {
|
|
12
21
|
throw err;
|
|
@@ -3,7 +3,12 @@ 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
|
-
|
|
6
|
+
if (config.legacy === false) {
|
|
7
|
+
return rubyDeps;
|
|
8
|
+
}
|
|
9
|
+
else {
|
|
10
|
+
return createRubyTSMessage(rubyDeps);
|
|
11
|
+
}
|
|
7
12
|
};
|
|
8
13
|
module.exports = {
|
|
9
14
|
rubyAnalysis
|
|
@@ -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');
|
|
@@ -19,9 +15,13 @@ const { rubyAnalysis } = require('./ruby');
|
|
|
19
15
|
const { pythonAnalysis } = require('./python');
|
|
20
16
|
const javaAnalysis = require('./java');
|
|
21
17
|
const jsAnalysis = require('./javascript');
|
|
18
|
+
const auditReport = require('./common/auditReport');
|
|
19
|
+
const processServices = require('./processServicesFlow');
|
|
22
20
|
const chalk = require('chalk');
|
|
21
|
+
const { convertGenericToTypedReportModelSca } = require('./common/utils/reportUtilsSca');
|
|
22
|
+
const projectConfig = require('../commands/github/projectGroup');
|
|
23
|
+
const { legacyFlow } = require('./legacy/legacyFlow');
|
|
23
24
|
const processSca = async (config) => {
|
|
24
|
-
const startTime = performance.now();
|
|
25
25
|
let filesFound;
|
|
26
26
|
if (config.help) {
|
|
27
27
|
console.log(auditUsageGuide);
|
|
@@ -43,7 +43,17 @@ const processSca = async (config) => {
|
|
|
43
43
|
switch (Object.keys(filesFound[0])[0]) {
|
|
44
44
|
case JAVA:
|
|
45
45
|
config.language = JAVA;
|
|
46
|
-
|
|
46
|
+
if (config.repo && !config.legacy) {
|
|
47
|
+
try {
|
|
48
|
+
messageToSend = await repoMode.buildRepo(config, filesFound[0]);
|
|
49
|
+
}
|
|
50
|
+
catch (e) {
|
|
51
|
+
throw new Error('Unable to build in repository mode. Check your project file');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
messageToSend = await javaAnalysis.javaAnalysis(config, filesFound[0]);
|
|
56
|
+
}
|
|
47
57
|
break;
|
|
48
58
|
case JAVASCRIPT:
|
|
49
59
|
messageToSend = await jsAnalysis.jsAnalysis(config, filesFound[0]);
|
|
@@ -66,32 +76,44 @@ const processSca = async (config) => {
|
|
|
66
76
|
config.language = GO;
|
|
67
77
|
break;
|
|
68
78
|
case DOTNET:
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
79
|
+
if (config.legacy === false) {
|
|
80
|
+
console.log(`${chalk.bold('\n.NET project found\n')} Language type is unsupported.`);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
messageToSend = dotNetAnalysis(config, filesFound[0]);
|
|
85
|
+
config.language = DOTNET;
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
72
88
|
default:
|
|
73
89
|
console.log('No supported language detected in project path');
|
|
74
90
|
return;
|
|
75
91
|
}
|
|
76
|
-
if (
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
92
|
+
if (config.legacy === false) {
|
|
93
|
+
if (!config.name) {
|
|
94
|
+
config = await projectConfig.dealWithNoName(config);
|
|
95
|
+
}
|
|
96
|
+
const startTime = performance.now();
|
|
97
|
+
console.log('');
|
|
98
|
+
const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'));
|
|
99
|
+
startSpinner(reportSpinner);
|
|
100
|
+
let reportResponse = await processServices.processUpload(messageToSend, config, reportSpinner);
|
|
101
|
+
const reportModelLibraryList = convertGenericToTypedReportModelSca(reportResponse.reportArray);
|
|
102
|
+
auditReport.processAuditReport(config, reportModelLibraryList);
|
|
103
|
+
if (config.save !== undefined) {
|
|
104
|
+
await auditSave.auditSave(config, reportResponse.reportId);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
console.log('Use contrast audit --save to generate an SBOM');
|
|
108
|
+
}
|
|
109
|
+
succeedSpinner(reportSpinner, i18n.__('auditSCAAnalysisComplete'));
|
|
110
|
+
const endTime = performance.now() - startTime;
|
|
111
|
+
const scanDurationMs = endTime - startTime;
|
|
112
|
+
console.log(`----- completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`);
|
|
88
113
|
}
|
|
89
114
|
else {
|
|
90
|
-
|
|
115
|
+
await legacyFlow(config, messageToSend);
|
|
91
116
|
}
|
|
92
|
-
const endTime = performance.now() - startTime;
|
|
93
|
-
const scanDurationMs = endTime - startTime;
|
|
94
|
-
console.log(`----- completed in ${(scanDurationMs / 1000).toFixed(2)}s -----`);
|
|
95
117
|
}
|
|
96
118
|
else {
|
|
97
119
|
if (filesFound.length === 0) {
|
|
@@ -1,16 +1,58 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const i18n = require('i18n');
|
|
3
3
|
const fileFinder = require('./fileUtils');
|
|
4
|
-
const
|
|
4
|
+
const { supportedLanguages: { JAVA, GO, PYTHON, RUBY, JAVASCRIPT, NODE, PHP, DOTNET } } = require('../constants/constants');
|
|
5
|
+
const autoDetectFingerprintInfo = async (filePath, depth, config) => {
|
|
5
6
|
let complexObj = await fileFinder.findAllFiles(filePath, depth);
|
|
6
7
|
let result = [];
|
|
7
8
|
let count = 0;
|
|
8
9
|
complexObj.forEach(i => {
|
|
9
10
|
count++;
|
|
10
|
-
result.push({
|
|
11
|
+
result.push({
|
|
12
|
+
filePath: i,
|
|
13
|
+
id: count.toString(),
|
|
14
|
+
repositoryId: config.repositoryId
|
|
15
|
+
});
|
|
11
16
|
});
|
|
12
17
|
return result;
|
|
13
18
|
};
|
|
19
|
+
const detectPackageManager = async (array) => {
|
|
20
|
+
array.forEach(i => {
|
|
21
|
+
if (i.filePath.includes('pom.xml')) {
|
|
22
|
+
i['language'] = JAVA;
|
|
23
|
+
i['packageManager'] = 'MAVEN';
|
|
24
|
+
}
|
|
25
|
+
if (i.filePath.includes('build.gradle.kts')) {
|
|
26
|
+
i['language'] = JAVA;
|
|
27
|
+
i['packageManager'] = 'GRADLE';
|
|
28
|
+
}
|
|
29
|
+
if (i.filePath.includes('build.gradle')) {
|
|
30
|
+
i['language'] = JAVA;
|
|
31
|
+
i['packageManager'] = 'GRADLE';
|
|
32
|
+
}
|
|
33
|
+
if (i.filePath.includes('package-lock.json')) {
|
|
34
|
+
i['language'] = JAVASCRIPT;
|
|
35
|
+
i['packageManager'] = 'NPM';
|
|
36
|
+
}
|
|
37
|
+
if (i.filePath.includes('yarn.lock')) {
|
|
38
|
+
i['language'] = JAVASCRIPT;
|
|
39
|
+
i['packageManager'] = 'YARN';
|
|
40
|
+
}
|
|
41
|
+
if (i.filePath.includes('Pipfile')) {
|
|
42
|
+
i['language'] = PYTHON;
|
|
43
|
+
}
|
|
44
|
+
if (i.filePath.includes('csproj')) {
|
|
45
|
+
i['language'] = DOTNET;
|
|
46
|
+
}
|
|
47
|
+
if (i.filePath.includes('Gemfile')) {
|
|
48
|
+
i['language'] = RUBY;
|
|
49
|
+
}
|
|
50
|
+
if (i.filePath.includes('go.mod')) {
|
|
51
|
+
i['language'] = GO;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
return array;
|
|
55
|
+
};
|
|
14
56
|
const autoDetectFileAndLanguage = async (configToUse) => {
|
|
15
57
|
const entries = await fileFinder.findFile();
|
|
16
58
|
if (entries.length === 1) {
|
|
@@ -53,7 +95,7 @@ const hasWhiteSpace = s => {
|
|
|
53
95
|
};
|
|
54
96
|
const dealWithMultiJava = filesFound => {
|
|
55
97
|
let hasMultiJava = filesFound.filter(data => {
|
|
56
|
-
return (Object.keys(data)[0] ===
|
|
98
|
+
return (Object.keys(data)[0] === JAVA &&
|
|
57
99
|
Object.values(data)[0].includes('build.gradle') &&
|
|
58
100
|
Object.values(data)[0].includes('pom.xml'));
|
|
59
101
|
}).length > 0;
|
|
@@ -101,5 +143,6 @@ module.exports = {
|
|
|
101
143
|
autoDetectAuditFilesAndLanguages,
|
|
102
144
|
errorOnAuditFileDetection,
|
|
103
145
|
autoDetectFingerprintInfo,
|
|
104
|
-
dealWithMultiJava
|
|
146
|
+
dealWithMultiJava,
|
|
147
|
+
detectPackageManager
|
|
105
148
|
};
|
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
|
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const generalAPI = require('./generalAPI');
|
|
3
|
+
const { SAAS } = require('../constants/constants');
|
|
4
|
+
const getSettings = async (config) => {
|
|
5
|
+
config.isEOP =
|
|
6
|
+
(await generalAPI.getMode(config)).toUpperCase() === SAAS ? false : true;
|
|
7
|
+
if (config.legacy === undefined) {
|
|
8
|
+
config.legacy = config.isEOP;
|
|
9
|
+
}
|
|
10
|
+
return config;
|
|
11
|
+
};
|
|
12
|
+
module.exports = {
|
|
13
|
+
getSettings
|
|
14
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contrast/contrast",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Contrast Security's command line tool",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -27,9 +27,12 @@
|
|
|
27
27
|
"test": "jest --testPathIgnorePatterns=./test-integration/",
|
|
28
28
|
"test-int": "jest ./test-integration/",
|
|
29
29
|
"test-int-scan": "jest ./test-integration/scan",
|
|
30
|
+
"test-int-audit": "jest test-integration/audit",
|
|
31
|
+
"test-int-audit-reports": "jest test-integration/audit/audit-language-reports-old-services.spec.js",
|
|
30
32
|
"test-int-scan-errors": "jest test-integration/scan/scanLocalErrors.spec.js",
|
|
31
33
|
"test-int-scan-reports": "jest test-integration/scan/scanReport.spec.js",
|
|
32
|
-
"test-int-audit-features": "jest test-integration/audit/auditFeatures",
|
|
34
|
+
"test-int-audit-features": "jest test-integration/audit/auditFeatures/",
|
|
35
|
+
"test-int-audit-projects": "jest test-integration/audit/audit-projects.spec.js",
|
|
33
36
|
"format": "prettier --write \"**/*.{ts,tsx,js,json,md,yml}\" .eslintrc.*",
|
|
34
37
|
"check-format": "prettier --check \"**/*.{ts,tsx,js,json,md,yml}\" .eslintrc.*",
|
|
35
38
|
"coverage-local": "nyc --reporter=text mocha './test/**/*.spec.js'",
|
|
@@ -59,7 +62,7 @@
|
|
|
59
62
|
"dotenv": "^16.0.0",
|
|
60
63
|
"fast-glob": "^3.2.11",
|
|
61
64
|
"gradle-to-js": "^2.0.1",
|
|
62
|
-
"i18n": "^0.
|
|
65
|
+
"i18n": "^0.15.1",
|
|
63
66
|
"js-yaml": "^4.1.0",
|
|
64
67
|
"lodash": "^4.17.21",
|
|
65
68
|
"log-symbols": "^4.1.0",
|
|
@@ -91,7 +94,7 @@
|
|
|
91
94
|
"husky": "^3.1.0",
|
|
92
95
|
"jest": "^27.5.1",
|
|
93
96
|
"jest-junit": "^13.2.0",
|
|
94
|
-
"mocha": "^
|
|
97
|
+
"mocha": "^10.2.0",
|
|
95
98
|
"npm-license-crawler": "^0.2.1",
|
|
96
99
|
"nyc": "^15.1.0",
|
|
97
100
|
"pkg": "^5.6.0",
|
|
@@ -100,7 +103,7 @@
|
|
|
100
103
|
"ts-jest": "^27.1.4",
|
|
101
104
|
"ts-node": "^10.7.0",
|
|
102
105
|
"typescript": "^4.6.3",
|
|
103
|
-
"uuid": "^
|
|
106
|
+
"uuid": "^9.0.0"
|
|
104
107
|
},
|
|
105
108
|
"resolutions": {
|
|
106
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
|
}
|
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:
|
|
@@ -38,7 +41,13 @@ async function auditSave(config, reportId) {
|
|
|
38
41
|
save.saveFile(config, fileFormat, sbomResponse)
|
|
39
42
|
}
|
|
40
43
|
}
|
|
41
|
-
|
|
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`
|
|
42
51
|
if (fs.existsSync(filename)) {
|
|
43
52
|
console.log(i18n.__('auditSBOMSaveSuccess') + ` - ${filename}`)
|
|
44
53
|
} else {
|
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,30 @@ 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')
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
name: 'repo-id',
|
|
432
|
+
type: String,
|
|
433
|
+
description: ''
|
|
402
434
|
}
|
|
403
435
|
]
|
|
404
436
|
|
|
@@ -409,6 +441,26 @@ const fingerprintOptionDefinitions = [
|
|
|
409
441
|
type: Number,
|
|
410
442
|
description:
|
|
411
443
|
'{bold ' + i18n.__('constantsOptional') + '}: ' + i18n.__('depthOption')
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
name: 'repo-url',
|
|
447
|
+
type: String,
|
|
448
|
+
description: ''
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
name: 'external-id',
|
|
452
|
+
type: String,
|
|
453
|
+
description: ''
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
name: 'repo-name',
|
|
457
|
+
type: String,
|
|
458
|
+
description: ''
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
name: 'language',
|
|
462
|
+
type: String,
|
|
463
|
+
description: ''
|
|
412
464
|
}
|
|
413
465
|
]
|
|
414
466
|
|
|
@@ -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) {
|
|
@@ -11,6 +12,7 @@ const processAudit = async (contrastConf, argvMain) => {
|
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
let config = await auditConfig.getAuditConfig(contrastConf, 'audit', argvMain)
|
|
15
|
+
config = await settingsHelper.getSettings(config)
|
|
14
16
|
|
|
15
17
|
await scaController.processSca(config)
|
|
16
18
|
if (!config.fingerprint) {
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
const fs = require('fs')
|
|
2
2
|
|
|
3
3
|
const saveFile = (config, type, rawResults) => {
|
|
4
|
-
|
|
4
|
+
let fileStart = config.legacy ? config.applicationId : config.projectId
|
|
5
|
+
if (fileStart === undefined) {
|
|
6
|
+
fileStart = 'my'
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const fileName = `${fileStart}-sbom-${type}.json`
|
|
5
10
|
fs.writeFileSync(fileName, JSON.stringify(rawResults))
|
|
6
11
|
}
|
|
7
12
|
|