@contrast/contrast 1.0.6 → 1.0.7
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/.prettierignore +0 -6
- package/dist/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +4 -2
- package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +2 -1
- package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +2 -1
- package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +2 -1
- package/dist/audit/languageAnalysisEngine/languageAnalysisFactory.js +2 -0
- package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +10 -1
- package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +6 -9
- package/dist/audit/languageAnalysisEngine/sendSnapshot.js +65 -3
- package/dist/commands/audit/processAudit.js +1 -1
- package/dist/commands/scan/sca/scaAnalysis.js +13 -2
- package/dist/common/HTTPClient.js +50 -15
- package/dist/common/errorHandling.js +6 -1
- package/dist/common/versionChecker.js +1 -1
- package/dist/constants/constants.js +1 -1
- package/dist/constants/locales.js +3 -1
- package/dist/lambda/analytics.js +11 -0
- package/dist/lambda/lambda.js +35 -4
- package/dist/lambda/types.js +13 -0
- package/dist/scaAnalysis/common/formatMessage.js +17 -1
- package/dist/scaAnalysis/java/analysis.js +3 -6
- package/dist/scaAnalysis/java/index.js +2 -2
- package/dist/scaAnalysis/python/analysis.js +41 -0
- package/dist/scaAnalysis/python/index.js +10 -0
- package/dist/scaAnalysis/ruby/analysis.js +226 -0
- package/dist/scaAnalysis/ruby/index.js +10 -0
- package/dist/scan/autoDetection.js +6 -2
- package/dist/scan/fileUtils.js +14 -7
- package/dist/scan/formatScanOutput.js +9 -11
- package/dist/scan/models/groupedResultsModel.js +1 -1
- package/dist/scan/models/scanResultsModel.js +3 -1
- package/dist/scan/populateProjectIdAndProjectName.js +2 -1
- package/dist/scan/scan.js +1 -0
- package/dist/scan/scanConfig.js +6 -1
- package/dist/scan/scanController.js +16 -3
- package/dist/scan/scanResults.js +5 -1
- package/dist/utils/commonApi.js +4 -1
- package/package.json +11 -7
- package/src/audit/catalogueApplication/catalogueApplication.js +0 -1
- package/src/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +11 -8
- package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +2 -1
- package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +2 -1
- package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +2 -1
- package/src/audit/languageAnalysisEngine/languageAnalysisFactory.js +8 -0
- package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +10 -9
- package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +34 -29
- package/src/audit/languageAnalysisEngine/report/models/reportLibraryModel.ts +3 -3
- package/src/audit/languageAnalysisEngine/report/models/reportListModel.ts +15 -11
- package/src/audit/languageAnalysisEngine/report/models/reportSeverityModel.ts +6 -1
- package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +43 -27
- package/src/audit/languageAnalysisEngine/sendSnapshot.js +78 -3
- package/src/commands/audit/processAudit.ts +1 -1
- package/src/commands/scan/sca/scaAnalysis.js +13 -5
- package/src/common/HTTPClient.js +65 -25
- package/src/common/errorHandling.ts +10 -1
- package/src/common/versionChecker.ts +1 -1
- package/src/constants/constants.js +1 -1
- package/src/constants/locales.js +3 -1
- package/src/lambda/analytics.ts +9 -0
- package/src/lambda/arn.ts +2 -1
- package/src/lambda/lambda.ts +37 -17
- package/src/lambda/types.ts +35 -0
- package/src/lambda/utils.ts +2 -7
- package/src/scaAnalysis/common/formatMessage.js +19 -1
- package/src/scaAnalysis/go/goAnalysis.js +2 -3
- package/src/scaAnalysis/java/analysis.js +5 -6
- package/src/scaAnalysis/java/index.js +2 -2
- package/src/scaAnalysis/python/analysis.js +48 -0
- package/src/scaAnalysis/python/index.js +11 -0
- package/src/scaAnalysis/ruby/analysis.js +282 -0
- package/src/scaAnalysis/ruby/index.js +11 -0
- package/src/scan/autoDetection.js +9 -5
- package/src/scan/fileUtils.js +15 -7
- package/src/scan/formatScanOutput.ts +11 -12
- package/src/scan/models/groupedResultsModel.ts +3 -3
- package/src/scan/models/resultContentModel.ts +1 -1
- package/src/scan/models/scanResultsModel.ts +5 -2
- package/src/scan/populateProjectIdAndProjectName.js +3 -1
- package/src/scan/scan.ts +1 -0
- package/src/scan/scanConfig.js +5 -1
- package/src/scan/scanController.js +18 -4
- package/src/scan/scanResults.js +10 -0
- package/src/utils/commonApi.js +4 -1
package/.prettierignore
CHANGED
|
@@ -142,10 +142,12 @@ const parseMvn = mvnDependancyTreeOutput => {
|
|
|
142
142
|
});
|
|
143
143
|
return parsedDepObj;
|
|
144
144
|
};
|
|
145
|
-
exports.shaveConsoleOutputUntilItFindsFirsDigraphMention =
|
|
145
|
+
exports.shaveConsoleOutputUntilItFindsFirsDigraphMention =
|
|
146
|
+
shaveConsoleOutputUntilItFindsFirsDigraphMention;
|
|
146
147
|
exports.getDigraphObjInfo = getDigraphObjInfo;
|
|
147
148
|
exports.createDigraphObjKey = createDigraphObjKey;
|
|
148
|
-
exports.turnDigraphDependanciesIntoArrOfInnerDep =
|
|
149
|
+
exports.turnDigraphDependanciesIntoArrOfInnerDep =
|
|
150
|
+
turnDigraphDependanciesIntoArrOfInnerDep;
|
|
149
151
|
exports.hasVersion = hasVersion;
|
|
150
152
|
exports.formatKeyName = formatKeyName;
|
|
151
153
|
exports.createOuterDependanciesAndType = createOuterDependanciesAndType;
|
|
@@ -21,4 +21,5 @@ const checkForMultipleIdentifiedLanguages = identifiedLanguages => {
|
|
|
21
21
|
throw new Error(errMsg);
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
|
-
exports.checkForMultipleIdentifiedLanguages =
|
|
24
|
+
exports.checkForMultipleIdentifiedLanguages =
|
|
25
|
+
checkForMultipleIdentifiedLanguages;
|
|
@@ -21,4 +21,5 @@ const checkForMultipleIdentifiedProjectFiles = identifiedLanguages => {
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
|
-
exports.checkForMultipleIdentifiedProjectFiles =
|
|
24
|
+
exports.checkForMultipleIdentifiedProjectFiles =
|
|
25
|
+
checkForMultipleIdentifiedProjectFiles;
|
|
@@ -20,4 +20,5 @@ const checkIdentifiedLanguageHasProjectFile = identifiedLanguages => {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
|
-
exports.checkIdentifiedLanguageHasProjectFile =
|
|
23
|
+
exports.checkIdentifiedLanguageHasProjectFile =
|
|
24
|
+
checkIdentifiedLanguageHasProjectFile;
|
|
@@ -15,6 +15,7 @@ const chalk = require('chalk');
|
|
|
15
15
|
const saveFile = require('../../commands/audit/saveFile').default;
|
|
16
16
|
const generateSbom = require('../../sbom/generateSbom').default;
|
|
17
17
|
const { failSpinner, returnOra, startSpinner, succeedSpinner } = require('../../utils/oraWrapper');
|
|
18
|
+
const { pollForSnapshotCompletition } = require('./sendSnapshot');
|
|
18
19
|
module.exports = exports = (err, analysis) => {
|
|
19
20
|
const { identifiedLanguageInfo } = analysis.languageAnalysis;
|
|
20
21
|
const catalogueAppId = analysis.languageAnalysis.appId;
|
|
@@ -39,6 +40,7 @@ module.exports = exports = (err, analysis) => {
|
|
|
39
40
|
const reportSpinner = returnOra(i18n.__('auditSCAAnalysisBegins'));
|
|
40
41
|
startSpinner(reportSpinner);
|
|
41
42
|
const snapshotResponse = await newSendSnapShot(analysis, catalogueAppId);
|
|
43
|
+
const pollResult = await pollForSnapshotCompletition(analysis.config, snapshotResponse.id, reportSpinner);
|
|
42
44
|
succeedSpinner(reportSpinner, 'Contrast SCA analysis complete');
|
|
43
45
|
await vulnerabilityReport(analysis, catalogueAppId, snapshotResponse.id);
|
|
44
46
|
await auditSave(config);
|
|
@@ -38,6 +38,14 @@ const deduceLanguageScaAnalysis = filenames => {
|
|
|
38
38
|
deducedLanguages.push(filename);
|
|
39
39
|
language = NODE;
|
|
40
40
|
}
|
|
41
|
+
if (isRubyProjectFilename(filename)) {
|
|
42
|
+
deducedLanguages.push(filename);
|
|
43
|
+
language = RUBY;
|
|
44
|
+
}
|
|
45
|
+
if (isPythonProjectFilename(filename)) {
|
|
46
|
+
deducedLanguages.push(filename);
|
|
47
|
+
language = PYTHON;
|
|
48
|
+
}
|
|
41
49
|
if (isNodeLockFilename(filename)) {
|
|
42
50
|
deducedLanguages.push(filename);
|
|
43
51
|
language = NODE;
|
|
@@ -118,7 +126,8 @@ module.exports = exports = (analysis, next) => {
|
|
|
118
126
|
}
|
|
119
127
|
let language = config.language;
|
|
120
128
|
if (language === undefined) {
|
|
121
|
-
languageAnalysis.identifiedLanguages =
|
|
129
|
+
languageAnalysis.identifiedLanguages =
|
|
130
|
+
reduceIdentifiedLanguages(identifiedLanguages);
|
|
122
131
|
}
|
|
123
132
|
else {
|
|
124
133
|
let refinedIdentifiedLanguages = [];
|
|
@@ -28,7 +28,8 @@ function findCVESeverity(cve) {
|
|
|
28
28
|
else if (cve.cvss3SeverityCode === 'HIGH' || cve.severityCode === 'HIGH') {
|
|
29
29
|
return new reportSeverityModel_1.ReportSeverityModel('HIGH', constants_2.HIGH_PRIORITY, constants_2.HIGH_COLOUR, cveName);
|
|
30
30
|
}
|
|
31
|
-
else if (cve.cvss3SeverityCode === 'MEDIUM' ||
|
|
31
|
+
else if (cve.cvss3SeverityCode === 'MEDIUM' ||
|
|
32
|
+
cve.severityCode === 'MEDIUM') {
|
|
32
33
|
return new reportSeverityModel_1.ReportSeverityModel('MEDIUM', constants_2.MEDIUM_PRIORITY, constants_2.MEDIUM_COLOUR, cveName);
|
|
33
34
|
}
|
|
34
35
|
else if (cve.cvss3SeverityCode === 'LOW' || cve.severityCode === 'LOW') {
|
|
@@ -58,24 +59,20 @@ function severityCountAllCVEs(cveArray, severityCount) {
|
|
|
58
59
|
}
|
|
59
60
|
exports.severityCountAllCVEs = severityCountAllCVEs;
|
|
60
61
|
function severityCountSingleCVE(cve, severityCount) {
|
|
61
|
-
if (cve.cvss3SeverityCode === 'CRITICAL' ||
|
|
62
|
-
cve.severityCode === 'CRITICAL') {
|
|
62
|
+
if (cve.cvss3SeverityCode === 'CRITICAL' || cve.severityCode === 'CRITICAL') {
|
|
63
63
|
severityCount.critical += 1;
|
|
64
64
|
}
|
|
65
|
-
else if (cve.cvss3SeverityCode === 'HIGH' ||
|
|
66
|
-
cve.severityCode === 'HIGH') {
|
|
65
|
+
else if (cve.cvss3SeverityCode === 'HIGH' || cve.severityCode === 'HIGH') {
|
|
67
66
|
severityCount.high += 1;
|
|
68
67
|
}
|
|
69
68
|
else if (cve.cvss3SeverityCode === 'MEDIUM' ||
|
|
70
69
|
cve.severityCode === 'MEDIUM') {
|
|
71
70
|
severityCount.medium += 1;
|
|
72
71
|
}
|
|
73
|
-
else if (cve.cvss3SeverityCode === 'LOW' ||
|
|
74
|
-
cve.severityCode === 'LOW') {
|
|
72
|
+
else if (cve.cvss3SeverityCode === 'LOW' || cve.severityCode === 'LOW') {
|
|
75
73
|
severityCount.low += 1;
|
|
76
74
|
}
|
|
77
|
-
else if (cve.cvss3SeverityCode === 'NOTE' ||
|
|
78
|
-
cve.severityCode === 'NOTE') {
|
|
75
|
+
else if (cve.cvss3SeverityCode === 'NOTE' || cve.severityCode === 'NOTE') {
|
|
79
76
|
severityCount.note += 1;
|
|
80
77
|
}
|
|
81
78
|
return severityCount;
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const { getHttpClient } = require('../../utils/commonApi');
|
|
3
2
|
const { handleResponseErrors } = require('../../common/errorHandling');
|
|
4
3
|
const { APP_VERSION } = require('../../constants/constants');
|
|
4
|
+
const commonApi = require('../../utils/commonApi');
|
|
5
|
+
const _ = require('lodash');
|
|
6
|
+
const oraFunctions = require('../../utils/oraWrapper');
|
|
7
|
+
const i18n = require('i18n');
|
|
8
|
+
const oraWrapper = require('../../utils/oraWrapper');
|
|
9
|
+
const requestUtils = require('../../utils/requestUtils');
|
|
10
|
+
const { performance } = require('perf_hooks');
|
|
5
11
|
const newSendSnapShot = async (analysis) => {
|
|
6
12
|
const analysisLanguage = analysis.config.language.toLowerCase();
|
|
7
13
|
const requestBody = {
|
|
@@ -9,7 +15,7 @@ const newSendSnapShot = async (analysis) => {
|
|
|
9
15
|
cliVersion: APP_VERSION,
|
|
10
16
|
snapshot: { [analysisLanguage]: analysis[analysisLanguage] }
|
|
11
17
|
};
|
|
12
|
-
const client = getHttpClient(analysis.config);
|
|
18
|
+
const client = commonApi.getHttpClient(analysis.config);
|
|
13
19
|
return client
|
|
14
20
|
.sendSnapshot(requestBody, analysis.config)
|
|
15
21
|
.then(res => {
|
|
@@ -24,6 +30,62 @@ const newSendSnapShot = async (analysis) => {
|
|
|
24
30
|
console.log(err);
|
|
25
31
|
});
|
|
26
32
|
};
|
|
33
|
+
const pollSnapshotResults = async (config, snapshotId, client) => {
|
|
34
|
+
await requestUtils.sleep(5000);
|
|
35
|
+
return client
|
|
36
|
+
.getReportStatusById(config, snapshotId)
|
|
37
|
+
.then(res => {
|
|
38
|
+
return res;
|
|
39
|
+
})
|
|
40
|
+
.catch(err => {
|
|
41
|
+
console.log(err);
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
const getTimeout = config => {
|
|
45
|
+
if (config.timeout) {
|
|
46
|
+
return config.timeout;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
if (config.verbose) {
|
|
50
|
+
console.log('Timeout set to 2 minutes');
|
|
51
|
+
}
|
|
52
|
+
return 120;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
const pollForSnapshotCompletition = async (config, snapshotId, reportSpinner) => {
|
|
56
|
+
const client = commonApi.getHttpClient(config);
|
|
57
|
+
const startTime = performance.now();
|
|
58
|
+
const timeout = getTimeout(config);
|
|
59
|
+
let complete = false;
|
|
60
|
+
if (!_.isNil(snapshotId)) {
|
|
61
|
+
while (!complete) {
|
|
62
|
+
let result = await pollSnapshotResults(config, snapshotId, client);
|
|
63
|
+
if (result.statusCode === 200) {
|
|
64
|
+
if (result.body.status === 'PROCESSED') {
|
|
65
|
+
complete = true;
|
|
66
|
+
return result.body;
|
|
67
|
+
}
|
|
68
|
+
if (result.body.status === 'FAILED') {
|
|
69
|
+
complete = true;
|
|
70
|
+
if (config.debug) {
|
|
71
|
+
oraFunctions.failSpinner(reportSpinner, i18n.__('auditNotCompleted'));
|
|
72
|
+
}
|
|
73
|
+
console.log(result.body.errorMessage);
|
|
74
|
+
oraWrapper.stopSpinner(reportSpinner);
|
|
75
|
+
console.log('Contrast audit finished');
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const endTime = performance.now() - startTime;
|
|
80
|
+
if (requestUtils.millisToSeconds(endTime) > timeout) {
|
|
81
|
+
oraFunctions.failSpinner(reportSpinner, 'Contrast audit timed out at the specified ' + timeout + ' seconds.');
|
|
82
|
+
console.log('Please try again, allowing more time.');
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
27
88
|
module.exports = {
|
|
28
|
-
newSendSnapShot: newSendSnapShot
|
|
89
|
+
newSendSnapShot: newSendSnapShot,
|
|
90
|
+
pollForSnapshotCompletition: pollForSnapshotCompletition
|
|
29
91
|
};
|
|
@@ -7,7 +7,7 @@ const help_1 = require("./help");
|
|
|
7
7
|
const processAudit = async (argv) => {
|
|
8
8
|
if (argv.indexOf('--help') != -1) {
|
|
9
9
|
printHelpMessage();
|
|
10
|
-
process.exit(
|
|
10
|
+
process.exit(0);
|
|
11
11
|
}
|
|
12
12
|
const config = (0, auditConfig_1.getAuditConfig)(argv);
|
|
13
13
|
const auditResults = await (0, auditController_1.startAudit)(config);
|
|
@@ -4,15 +4,18 @@ const javaAnalysis = require('../../../scaAnalysis/java');
|
|
|
4
4
|
const treeUpload = require('../../../scaAnalysis/common/treeUpload');
|
|
5
5
|
const { manualDetectAuditFilesAndLanguages } = require('../../../scan/autoDetection');
|
|
6
6
|
const auditController = require('../../audit/auditController');
|
|
7
|
-
const { supportedLanguages: { JAVA, GO } } = require('../../../audit/languageAnalysisEngine/constants');
|
|
7
|
+
const { supportedLanguages: { JAVA, GO, RUBY, PYTHON } } = require('../../../audit/languageAnalysisEngine/constants');
|
|
8
8
|
const goAnalysis = require('../../../scaAnalysis/go/goAnalysis');
|
|
9
|
+
const { rubyAnalysis } = require('../../../scaAnalysis/ruby');
|
|
10
|
+
const { pythonAnalysis } = require('../../../scaAnalysis/python');
|
|
9
11
|
const processSca = async (config) => {
|
|
10
12
|
let filesFound;
|
|
11
13
|
if (config.projectPath) {
|
|
12
|
-
filesFound =
|
|
14
|
+
filesFound = manualDetectAuditFilesAndLanguages(config.projectPath);
|
|
13
15
|
}
|
|
14
16
|
else {
|
|
15
17
|
filesFound = await autoDetection.autoDetectAuditFilesAndLanguages(config);
|
|
18
|
+
config.projectPath = process.cwd();
|
|
16
19
|
}
|
|
17
20
|
let messageToSend = undefined;
|
|
18
21
|
if (filesFound.length === 1) {
|
|
@@ -21,6 +24,14 @@ const processSca = async (config) => {
|
|
|
21
24
|
messageToSend = javaAnalysis.javaAnalysis(config, filesFound[0]);
|
|
22
25
|
config.language = JAVA;
|
|
23
26
|
break;
|
|
27
|
+
case RUBY:
|
|
28
|
+
messageToSend = rubyAnalysis(config, filesFound[0]);
|
|
29
|
+
config.language = RUBY;
|
|
30
|
+
break;
|
|
31
|
+
case PYTHON:
|
|
32
|
+
messageToSend = pythonAnalysis(config, filesFound[0]);
|
|
33
|
+
config.language = PYTHON;
|
|
34
|
+
break;
|
|
24
35
|
case GO:
|
|
25
36
|
messageToSend = goAnalysis.goAnalysis(config, filesFound[0]);
|
|
26
37
|
config.language = GO;
|
|
@@ -20,7 +20,8 @@ function HTTPClient(config) {
|
|
|
20
20
|
Authorization: authToken,
|
|
21
21
|
'API-Key': apiKey,
|
|
22
22
|
SuperAuthorization: superAuthToken,
|
|
23
|
-
'Super-API-Key': superApiKey
|
|
23
|
+
'Super-API-Key': superApiKey,
|
|
24
|
+
'User-Agent': 'contrast-cli-v2'
|
|
24
25
|
}
|
|
25
26
|
};
|
|
26
27
|
if (config.proxy) {
|
|
@@ -66,10 +67,24 @@ HTTPClient.prototype.getSpecificScanResult = function getSpecificScanResult(conf
|
|
|
66
67
|
options.url = url;
|
|
67
68
|
return requestUtils.sendRequest({ method: 'get', options });
|
|
68
69
|
};
|
|
69
|
-
HTTPClient.prototype.getSpecificScanResultSarif =
|
|
70
|
+
HTTPClient.prototype.getSpecificScanResultSarif =
|
|
71
|
+
function getSpecificScanResultSarif(config, scanId) {
|
|
72
|
+
const options = _.cloneDeep(this.requestOptions);
|
|
73
|
+
options.url = createRawOutputURL(config, scanId);
|
|
74
|
+
return requestUtils.sendRequest({ method: 'get', options });
|
|
75
|
+
};
|
|
76
|
+
HTTPClient.prototype.createNewEvent = function createNewEvent(config, scanId, newProject) {
|
|
70
77
|
const options = _.cloneDeep(this.requestOptions);
|
|
71
|
-
options.url =
|
|
72
|
-
|
|
78
|
+
options.url = createEventCollectorURL(config, scanId);
|
|
79
|
+
options.body = {
|
|
80
|
+
eventSource: process.env.CODESEC_INVOCATION_ENVIRONMENT,
|
|
81
|
+
trackingProperties: {
|
|
82
|
+
projectNameSource: config.projectNameSource,
|
|
83
|
+
waitedForResults: !config.ff,
|
|
84
|
+
newProject
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
return requestUtils.sendRequest({ method: 'post', options });
|
|
73
88
|
};
|
|
74
89
|
HTTPClient.prototype.getScanId = function getScanId(config, codeArtifactId) {
|
|
75
90
|
const options = _.cloneDeep(this.requestOptions);
|
|
@@ -145,8 +160,6 @@ HTTPClient.prototype.catalogueCommand = function catalogueCommand(config) {
|
|
|
145
160
|
return requestUtils.sendRequest({ method: 'post', options });
|
|
146
161
|
};
|
|
147
162
|
HTTPClient.prototype.sendSnapshot = function sendSnapshot(requestBody, config) {
|
|
148
|
-
if (config.language.toUpperCase() === 'RUBY') {
|
|
149
|
-
}
|
|
150
163
|
const options = _.cloneDeep(this.requestOptions);
|
|
151
164
|
let url = createSnapshotURL(config);
|
|
152
165
|
options.url = url;
|
|
@@ -163,12 +176,18 @@ HTTPClient.prototype.getReportById = function getReportById(config, reportId) {
|
|
|
163
176
|
}
|
|
164
177
|
return requestUtils.sendRequest({ method: 'get', options });
|
|
165
178
|
};
|
|
166
|
-
HTTPClient.prototype.
|
|
179
|
+
HTTPClient.prototype.getReportStatusById = function getReportStatusById(config, snapshotId) {
|
|
167
180
|
const options = _.cloneDeep(this.requestOptions);
|
|
168
|
-
options.url =
|
|
169
|
-
|
|
170
|
-
return requestUtils.sendRequest({ method: 'put', options });
|
|
181
|
+
options.url = createSpecificReportStatusURL(config, snapshotId);
|
|
182
|
+
return requestUtils.sendRequest({ method: 'get', options });
|
|
171
183
|
};
|
|
184
|
+
HTTPClient.prototype.getLibraryVulnerabilities =
|
|
185
|
+
function getLibraryVulnerabilities(config, requestBody) {
|
|
186
|
+
const options = _.cloneDeep(this.requestOptions);
|
|
187
|
+
options.url = createLibraryVulnerabilitiesUrl(config);
|
|
188
|
+
options.body = requestBody;
|
|
189
|
+
return requestUtils.sendRequest({ method: 'put', options });
|
|
190
|
+
};
|
|
172
191
|
HTTPClient.prototype.getAppId = function getAppId(config) {
|
|
173
192
|
const options = _.cloneDeep(this.requestOptions);
|
|
174
193
|
let url = createAppNameUrl(config);
|
|
@@ -210,11 +229,12 @@ HTTPClient.prototype.getScanResources = async function getScanResources(config,
|
|
|
210
229
|
const options = { ...this.requestOptions, url };
|
|
211
230
|
return requestUtils.sendRequest({ method: 'get', options });
|
|
212
231
|
};
|
|
213
|
-
HTTPClient.prototype.getFunctionScanResults =
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
};
|
|
232
|
+
HTTPClient.prototype.getFunctionScanResults =
|
|
233
|
+
async function getFunctionScanResults(config, params, scanId, functionArn) {
|
|
234
|
+
const url = createScanResultsGetUrl(config, params, scanId, functionArn);
|
|
235
|
+
const options = { ...this.requestOptions, url };
|
|
236
|
+
return requestUtils.sendRequest({ method: 'get', options });
|
|
237
|
+
};
|
|
218
238
|
HTTPClient.prototype.checkLibrary = function checkLibrary(data) {
|
|
219
239
|
const options = _.cloneDeep(this.requestOptions);
|
|
220
240
|
let url = createDataUrl();
|
|
@@ -227,6 +247,15 @@ HTTPClient.prototype.getSbom = function getSbom(config) {
|
|
|
227
247
|
options.url = createSbomCycloneDXUrl(config);
|
|
228
248
|
return requestUtils.sendRequest({ method: 'get', options });
|
|
229
249
|
};
|
|
250
|
+
HTTPClient.prototype.postAnalyticsFunction = function (config, provider, body) {
|
|
251
|
+
const url = createAnalyticsFunctionPostUrl(config, provider);
|
|
252
|
+
const options = { ...this.requestOptions, body, url };
|
|
253
|
+
return requestUtils.sendRequest({ method: 'post', options });
|
|
254
|
+
};
|
|
255
|
+
const createAnalyticsFunctionPostUrl = (config, provider) => {
|
|
256
|
+
const url = getServerlessHost(config);
|
|
257
|
+
return `${url}/organizations/${config.organizationId}/providers/${provider}/analytics`;
|
|
258
|
+
};
|
|
230
259
|
const createGetScanIdURL = config => {
|
|
231
260
|
return `${config.host}/Contrast/api/sast/v1/organizations/${config.organizationId}/projects/${config.projectId}/scans/`;
|
|
232
261
|
};
|
|
@@ -248,6 +277,9 @@ function createHarmonyProjectsUrl(config) {
|
|
|
248
277
|
function createScanProjectUrl(config) {
|
|
249
278
|
return `${config.host}/Contrast/api/sast/v1/organizations/${config.organizationId}/projects/${config.projectId}`;
|
|
250
279
|
}
|
|
280
|
+
const createEventCollectorURL = (config, scanId) => {
|
|
281
|
+
return `${config.host}/Contrast/api/sast/organizations/${config.organizationId}/projects/${config.projectId}/scans/${scanId}/events`;
|
|
282
|
+
};
|
|
251
283
|
const createGlobalPropertiesUrl = protocol => {
|
|
252
284
|
return `${protocol}/Contrast/api/ng/global/properties`;
|
|
253
285
|
};
|
|
@@ -272,6 +304,9 @@ function createSpecificReportUrl(config, reportId) {
|
|
|
272
304
|
function createSpecificReportWithProdUrl(config, reportId) {
|
|
273
305
|
return createSpecificReportUrl(config, reportId).concat(`?nodesToInclude=PROD`);
|
|
274
306
|
}
|
|
307
|
+
function createSpecificReportStatusURL(config, reportId) {
|
|
308
|
+
return `${config.host}/Contrast/api/ng/sca/organizations/${config.organizationId}/applications/${config.applicationId}/snapshots/${reportId}/status`;
|
|
309
|
+
}
|
|
275
310
|
function createDataUrl() {
|
|
276
311
|
return `https://ardy.contrastsecurity.com/production`;
|
|
277
312
|
}
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.reportFailureError = exports.vulnerabilitiesFailureError = exports.snapshotFailureError = exports.findCommandOnError = exports.libraryAnalysisError = exports.handleResponseErrors = exports.getErrorMessage = exports.generalError = exports.failOptionError = exports.proxyError = exports.forbiddenError = exports.badRequestError = exports.unauthenticatedError = exports.genericError = void 0;
|
|
6
|
+
exports.maxAppError = exports.reportFailureError = exports.vulnerabilitiesFailureError = exports.snapshotFailureError = exports.findCommandOnError = exports.libraryAnalysisError = exports.handleResponseErrors = exports.getErrorMessage = exports.generalError = exports.failOptionError = exports.proxyError = exports.forbiddenError = exports.badRequestError = exports.unauthenticatedError = exports.genericError = void 0;
|
|
7
7
|
const i18n_1 = __importDefault(require("i18n"));
|
|
8
8
|
const handleResponseErrors = (res, api) => {
|
|
9
9
|
if (res.statusCode === 400) {
|
|
@@ -72,6 +72,11 @@ const proxyError = () => {
|
|
|
72
72
|
generalError('proxyErrorHeader', 'proxyErrorMessage');
|
|
73
73
|
};
|
|
74
74
|
exports.proxyError = proxyError;
|
|
75
|
+
const maxAppError = () => {
|
|
76
|
+
generalError('No applications remaining', 'You have reached the maximum number of application you can create.');
|
|
77
|
+
process.exit(1);
|
|
78
|
+
};
|
|
79
|
+
exports.maxAppError = maxAppError;
|
|
75
80
|
const failOptionError = () => {
|
|
76
81
|
console.log('\n ******************************** ' +
|
|
77
82
|
i18n_1.default.__('snapshotFailureHeader') +
|
|
@@ -27,6 +27,6 @@ async function findLatestCLIVersion(updateMessageHidden) {
|
|
|
27
27
|
}
|
|
28
28
|
exports.findLatestCLIVersion = findLatestCLIVersion;
|
|
29
29
|
async function isCorrectNodeVersion(currentVersion) {
|
|
30
|
-
return semver_1.default.satisfies(currentVersion, '>=16
|
|
30
|
+
return semver_1.default.satisfies(currentVersion, '>=16');
|
|
31
31
|
}
|
|
32
32
|
exports.isCorrectNodeVersion = isCorrectNodeVersion;
|
|
@@ -12,7 +12,7 @@ const MEDIUM = 'MEDIUM';
|
|
|
12
12
|
const HIGH = 'HIGH';
|
|
13
13
|
const CRITICAL = 'CRITICAL';
|
|
14
14
|
const APP_NAME = 'contrast';
|
|
15
|
-
const APP_VERSION = '1.0.
|
|
15
|
+
const APP_VERSION = '1.0.7';
|
|
16
16
|
const TIMEOUT = 120000;
|
|
17
17
|
const HIGH_COLOUR = '#ff9900';
|
|
18
18
|
const CRITICAL_COLOUR = '#e35858';
|
|
@@ -96,7 +96,7 @@ const en_locales = () => {
|
|
|
96
96
|
constantsCount: "The number of CVE's that must be exceeded to fail a build",
|
|
97
97
|
constantsHeader: 'CodeSec by Contrast Security',
|
|
98
98
|
constantsPrerequisitesContentScanLanguages: 'Java & JavaScript supported',
|
|
99
|
-
constantsContrastContent:
|
|
99
|
+
constantsContrastContent: "Use the 'contrast' command for fast and accurate security analysis of your applications and APIs (Java, JavaScript and .NET ) as well as serverless functions (AWS lambda, Java and Python).",
|
|
100
100
|
constantsUsageGuideContentRecommendation: 'Our recommendation is that this is invoked as part of a CI pipeline so that running the cli is automated as part of your build process.',
|
|
101
101
|
constantsPrerequisitesHeader: 'Pre-requisites',
|
|
102
102
|
constantsAuthUsageHeader: 'Usage',
|
|
@@ -247,6 +247,7 @@ const en_locales = () => {
|
|
|
247
247
|
redirectAuth: '\nOpening the authentication page in your web browser.\nSign in and complete the steps.\nReturn here to start using Contrast.\n\nIf your browser has trouble loading, try this:\n%s \n',
|
|
248
248
|
scanZipError: 'A .zip archive can be used for Javascript Scan. Archive found %s does not contain .JS files for Scan.',
|
|
249
249
|
fileNotExist: 'File specified does not exist, please check and try again.',
|
|
250
|
+
scanFileIsEmpty: 'File specified is empty. Please choose another.',
|
|
250
251
|
fileHasWhiteSpacesError: 'File cannot have spaces, please rename or choose another file to Scan.',
|
|
251
252
|
zipFileException: 'Error reading zip file',
|
|
252
253
|
connectionError: 'An error has occurred when trying to get the Project Id please check your internet connection or provide the Project Id manually',
|
|
@@ -278,6 +279,7 @@ const en_locales = () => {
|
|
|
278
279
|
auditOptionsSave: '-s, --save',
|
|
279
280
|
auditOptionsSaveDescription: 'saves the output in specified format Txt text, sbom',
|
|
280
281
|
scanNotCompleted: 'Scan not completed. Check for framework and language support here: %s',
|
|
282
|
+
auditNotCompleted: 'audit not completed. Please try again',
|
|
281
283
|
scanNoVulnerabilitiesFound: '👏 No vulnerabilities found',
|
|
282
284
|
scanNoVulnerabilitiesFoundSecureCode: '👍 Your code looks secure.',
|
|
283
285
|
scanNoVulnerabilitiesFoundGoodWork: '👏 Keep up the good work.',
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.postAnalytics = void 0;
|
|
4
|
+
const commonApi_1 = require("../utils/commonApi");
|
|
5
|
+
const paramHandler_1 = require("../utils/paramsUtil/paramHandler");
|
|
6
|
+
const postAnalytics = (data, provider = 'aws') => {
|
|
7
|
+
const config = (0, paramHandler_1.getAuth)();
|
|
8
|
+
const client = (0, commonApi_1.getHttpClient)(config);
|
|
9
|
+
return client.postAnalyticsFunction(config, provider, data);
|
|
10
|
+
};
|
|
11
|
+
exports.postAnalytics = postAnalytics;
|
package/dist/lambda/lambda.js
CHANGED
|
@@ -20,6 +20,8 @@ const utils_1 = require("./utils");
|
|
|
20
20
|
const lambdaUtils_1 = require("./lambdaUtils");
|
|
21
21
|
const requestUtils_1 = require("../utils/requestUtils");
|
|
22
22
|
const oraWrapper_1 = __importDefault(require("../utils/oraWrapper"));
|
|
23
|
+
const analytics_1 = require("./analytics");
|
|
24
|
+
const types_1 = require("./types");
|
|
23
25
|
const failedStates = [
|
|
24
26
|
'UNSUPPORTED',
|
|
25
27
|
'EXCLUDED',
|
|
@@ -57,9 +59,19 @@ const getLambdaOptions = (argv) => {
|
|
|
57
59
|
}
|
|
58
60
|
};
|
|
59
61
|
const processLambda = async (argv) => {
|
|
62
|
+
let errorMsg;
|
|
63
|
+
let scanInfo;
|
|
64
|
+
const commandSessionId = Date.now().toString(36);
|
|
60
65
|
try {
|
|
61
66
|
const lambdaOptions = getLambdaOptions(argv);
|
|
62
67
|
const { help } = lambdaOptions;
|
|
68
|
+
const startCommandAnalytics = {
|
|
69
|
+
arguments: lambdaOptions,
|
|
70
|
+
sessionId: commandSessionId,
|
|
71
|
+
eventType: types_1.EventType.START
|
|
72
|
+
};
|
|
73
|
+
(0, analytics_1.postAnalytics)(startCommandAnalytics).catch((error) => {
|
|
74
|
+
});
|
|
63
75
|
if (help) {
|
|
64
76
|
return handleLambdaHelp();
|
|
65
77
|
}
|
|
@@ -68,17 +80,35 @@ const processLambda = async (argv) => {
|
|
|
68
80
|
await getAvailableFunctions(lambdaOptions);
|
|
69
81
|
}
|
|
70
82
|
else {
|
|
71
|
-
await actualProcessLambda(lambdaOptions);
|
|
83
|
+
scanInfo = await actualProcessLambda(lambdaOptions);
|
|
72
84
|
}
|
|
73
85
|
}
|
|
74
86
|
catch (error) {
|
|
75
87
|
if (error instanceof cliError_1.CliError) {
|
|
76
|
-
|
|
88
|
+
errorMsg = error.getErrorMessage();
|
|
77
89
|
}
|
|
78
90
|
else if (error instanceof Error) {
|
|
79
|
-
|
|
91
|
+
errorMsg = error.message;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
const endCommandAnalytics = {
|
|
96
|
+
sessionId: commandSessionId,
|
|
97
|
+
eventType: types_1.EventType.END,
|
|
98
|
+
status: errorMsg ? types_1.StatusType.FAILED : types_1.StatusType.SUCCESS
|
|
99
|
+
};
|
|
100
|
+
if (errorMsg) {
|
|
101
|
+
endCommandAnalytics.errorMsg = errorMsg;
|
|
102
|
+
console.error(errorMsg);
|
|
103
|
+
}
|
|
104
|
+
if (scanInfo) {
|
|
105
|
+
endCommandAnalytics.scanFunctionData = scanInfo;
|
|
106
|
+
}
|
|
107
|
+
await (0, analytics_1.postAnalytics)(endCommandAnalytics).catch((error) => {
|
|
108
|
+
});
|
|
109
|
+
if (errorMsg) {
|
|
110
|
+
process.exit(1);
|
|
80
111
|
}
|
|
81
|
-
process.exit(1);
|
|
82
112
|
}
|
|
83
113
|
};
|
|
84
114
|
exports.processLambda = processLambda;
|
|
@@ -127,6 +157,7 @@ const actualProcessLambda = async (lambdaOptions) => {
|
|
|
127
157
|
if (results?.length) {
|
|
128
158
|
(0, utils_1.printResults)(results);
|
|
129
159
|
}
|
|
160
|
+
return { functionArn, scanId };
|
|
130
161
|
};
|
|
131
162
|
const validateRequiredLambdaParams = (options) => {
|
|
132
163
|
if (options._unknown?.length) {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EventType = exports.StatusType = void 0;
|
|
4
|
+
var StatusType;
|
|
5
|
+
(function (StatusType) {
|
|
6
|
+
StatusType["FAILED"] = "failed";
|
|
7
|
+
StatusType["SUCCESS"] = "success";
|
|
8
|
+
})(StatusType = exports.StatusType || (exports.StatusType = {}));
|
|
9
|
+
var EventType;
|
|
10
|
+
(function (EventType) {
|
|
11
|
+
EventType["START"] = "start_command_session";
|
|
12
|
+
EventType["END"] = "end_command_session";
|
|
13
|
+
})(EventType = exports.EventType || (exports.EventType = {}));
|
|
@@ -13,7 +13,23 @@ const createGoTSMessage = goTree => {
|
|
|
13
13
|
}
|
|
14
14
|
};
|
|
15
15
|
};
|
|
16
|
+
const createRubyTSMessage = rubyTree => {
|
|
17
|
+
return {
|
|
18
|
+
ruby: {
|
|
19
|
+
rubyDependencyTrees: rubyTree
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
const createPythonTSMessage = pythonTree => {
|
|
24
|
+
return {
|
|
25
|
+
python: {
|
|
26
|
+
pythonDependencyTrees: pythonTree
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
};
|
|
16
30
|
module.exports = {
|
|
17
31
|
createJavaTSMessage,
|
|
18
|
-
createGoTSMessage
|
|
32
|
+
createGoTSMessage,
|
|
33
|
+
createRubyTSMessage,
|
|
34
|
+
createPythonTSMessage
|
|
19
35
|
};
|
|
@@ -9,16 +9,13 @@ const determineProjectTypeAndCwd = (files, projectPath) => {
|
|
|
9
9
|
const projectData = {};
|
|
10
10
|
if (files[0].includes('pom.xml')) {
|
|
11
11
|
projectData.projectType = MAVEN;
|
|
12
|
-
projectData.cwd = projectPath
|
|
13
|
-
? projectPath
|
|
14
|
-
: files[0].replace('pom.xml', '');
|
|
15
12
|
}
|
|
16
13
|
else if (files[0].includes('build.gradle')) {
|
|
17
14
|
projectData.projectType = GRADLE;
|
|
18
|
-
projectData.cwd = projectPath
|
|
19
|
-
? projectPath
|
|
20
|
-
: files[0].replace('pom.xml', '');
|
|
21
15
|
}
|
|
16
|
+
projectData.cwd = projectPath
|
|
17
|
+
? projectPath.replace('pom.xml', '').replace('build.gradle', '')
|
|
18
|
+
: projectPath;
|
|
22
19
|
return projectData;
|
|
23
20
|
};
|
|
24
21
|
const buildMaven = (config, projectData, timeout) => {
|
|
@@ -3,10 +3,10 @@ const analysis = require('./analysis');
|
|
|
3
3
|
const { parseBuildDeps } = require('./javaBuildDepsParser');
|
|
4
4
|
const { createJavaTSMessage } = require('../common/formatMessage');
|
|
5
5
|
const javaAnalysis = (config, languageFiles) => {
|
|
6
|
-
languageFiles.
|
|
6
|
+
languageFiles.JAVA.forEach(file => {
|
|
7
7
|
file.replace('build.gradle.kts', 'build.gradle');
|
|
8
8
|
});
|
|
9
|
-
const javaDeps = buildJavaTree(config, languageFiles.
|
|
9
|
+
const javaDeps = buildJavaTree(config, languageFiles.JAVA);
|
|
10
10
|
return createJavaTSMessage(javaDeps);
|
|
11
11
|
};
|
|
12
12
|
const buildJavaTree = (config, files) => {
|