@contrast/contrast 1.0.1 → 1.0.4

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.
Files changed (94) hide show
  1. package/.prettierignore +2 -0
  2. package/README.md +103 -133
  3. package/dist/audit/languageAnalysisEngine/{langugageAnalysisFactory.js → languageAnalysisFactory.js} +26 -11
  4. package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +62 -234
  5. package/dist/audit/languageAnalysisEngine/report/models/reportLibraryModel.js +19 -0
  6. package/dist/audit/languageAnalysisEngine/report/models/reportListModel.js +24 -0
  7. package/dist/audit/languageAnalysisEngine/report/models/reportSeverityModel.js +10 -0
  8. package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +24 -129
  9. package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +85 -0
  10. package/dist/audit/languageAnalysisEngine/sendSnapshot.js +3 -1
  11. package/dist/commands/audit/auditController.js +6 -3
  12. package/dist/commands/audit/saveFile.js +11 -0
  13. package/dist/commands/auth/auth.js +19 -1
  14. package/dist/commands/config/config.js +19 -8
  15. package/dist/commands/scan/processScan.js +8 -25
  16. package/dist/common/HTTPClient.js +30 -26
  17. package/dist/common/errorHandling.js +17 -1
  18. package/dist/common/versionChecker.js +32 -0
  19. package/dist/constants/constants.js +4 -2
  20. package/dist/constants/lambda.js +3 -1
  21. package/dist/constants/locales.js +41 -18
  22. package/dist/constants.js +39 -3
  23. package/dist/index.js +49 -28
  24. package/dist/lambda/help.js +22 -14
  25. package/dist/lambda/lambda.js +6 -0
  26. package/dist/sbom/generateSbom.js +20 -0
  27. package/dist/scan/help.js +4 -2
  28. package/dist/scan/models/groupedResultsModel.js +10 -0
  29. package/dist/scan/models/resultContentModel.js +2 -0
  30. package/dist/scan/models/scanResultsModel.js +11 -0
  31. package/dist/scan/populateProjectIdAndProjectName.js +1 -0
  32. package/dist/scan/saveResults.js +9 -10
  33. package/dist/scan/scan.js +99 -74
  34. package/dist/scan/scanConfig.js +20 -1
  35. package/dist/scan/scanController.js +7 -2
  36. package/dist/scan/scanResults.js +6 -0
  37. package/dist/utils/getConfig.js +3 -0
  38. package/dist/utils/paramsUtil/commandlineParams.js +1 -1
  39. package/dist/utils/requestUtils.js +1 -1
  40. package/dist/utils/saveFile.js +19 -0
  41. package/package.json +2 -2
  42. package/src/audit/languageAnalysisEngine/{langugageAnalysisFactory.js → languageAnalysisFactory.js} +33 -15
  43. package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +127 -0
  44. package/src/audit/languageAnalysisEngine/report/models/reportLibraryModel.ts +30 -0
  45. package/src/audit/languageAnalysisEngine/report/models/reportListModel.ts +32 -0
  46. package/src/audit/languageAnalysisEngine/report/models/reportSeverityModel.ts +9 -0
  47. package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +56 -0
  48. package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +110 -0
  49. package/src/audit/languageAnalysisEngine/sendSnapshot.js +3 -1
  50. package/src/commands/audit/auditController.ts +12 -3
  51. package/src/commands/audit/processAudit.ts +0 -1
  52. package/src/commands/audit/saveFile.ts +6 -0
  53. package/src/commands/auth/auth.js +25 -1
  54. package/src/commands/config/config.js +22 -8
  55. package/src/commands/scan/processScan.js +8 -29
  56. package/src/common/HTTPClient.js +42 -36
  57. package/src/common/errorHandling.ts +29 -2
  58. package/src/common/versionChecker.ts +41 -0
  59. package/src/constants/constants.js +5 -4
  60. package/src/constants/lambda.js +3 -1
  61. package/src/constants/locales.js +51 -19
  62. package/src/constants.js +44 -3
  63. package/src/index.ts +63 -31
  64. package/src/lambda/help.ts +22 -14
  65. package/src/lambda/lambda.ts +8 -0
  66. package/src/sbom/generateSbom.ts +17 -0
  67. package/src/scan/help.js +4 -2
  68. package/src/scan/models/groupedResultsModel.ts +18 -0
  69. package/src/scan/models/resultContentModel.ts +86 -0
  70. package/src/scan/models/scanResultsModel.ts +52 -0
  71. package/src/scan/populateProjectIdAndProjectName.js +1 -0
  72. package/src/scan/saveResults.js +8 -9
  73. package/src/scan/scan.ts +192 -0
  74. package/src/scan/scanConfig.js +26 -1
  75. package/src/scan/scanController.js +11 -2
  76. package/src/scan/scanResults.js +11 -0
  77. package/src/utils/getConfig.ts +12 -0
  78. package/src/utils/paramsUtil/commandlineParams.js +1 -1
  79. package/src/utils/requestUtils.js +1 -1
  80. package/src/utils/saveFile.js +19 -0
  81. package/dist/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +0 -17
  82. package/dist/audit/languageAnalysisEngine/report/newReportingFeature.js +0 -81
  83. package/dist/common/findLatestCLIVersion.js +0 -23
  84. package/dist/lambda/scanDetail.js +0 -30
  85. package/dist/scan/fileFinder.js +0 -15
  86. package/dist/utils/fileUtils.js +0 -31
  87. package/dist/utils/paramsUtil/genericCommandLineParams.js +0 -12
  88. package/dist/utils/paramsUtil/yamlParams.js +0 -6
  89. package/src/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +0 -27
  90. package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.js +0 -303
  91. package/src/audit/languageAnalysisEngine/report/newReportingFeature.js +0 -124
  92. package/src/audit/languageAnalysisEngine/report/reportingFeature.js +0 -190
  93. package/src/common/findLatestCLIVersion.ts +0 -27
  94. package/src/scan/scan.js +0 -162
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ReportCVEModel = exports.ReportLibraryModel = void 0;
4
+ class ReportLibraryModel {
5
+ constructor(name, cveArray) {
6
+ this.name = name;
7
+ this.cveArray = cveArray;
8
+ }
9
+ }
10
+ exports.ReportLibraryModel = ReportLibraryModel;
11
+ class ReportCVEModel {
12
+ constructor(name, description, severityCode, cvss3SeverityCode) {
13
+ this.name = name;
14
+ this.description = description;
15
+ this.severityCode = severityCode;
16
+ this.cvss3SeverityCode = cvss3SeverityCode;
17
+ }
18
+ }
19
+ exports.ReportCVEModel = ReportCVEModel;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ReportCompositeKey = exports.ReportModelStructure = exports.ReportList = void 0;
4
+ class ReportList {
5
+ constructor() {
6
+ this.reportOutputList = [];
7
+ }
8
+ }
9
+ exports.ReportList = ReportList;
10
+ class ReportModelStructure {
11
+ constructor(compositeKey, cveArray) {
12
+ this.compositeKey = compositeKey;
13
+ this.cveArray = cveArray;
14
+ }
15
+ }
16
+ exports.ReportModelStructure = ReportModelStructure;
17
+ class ReportCompositeKey {
18
+ constructor(libraryName, libraryVersion, highestSeverity) {
19
+ this.libraryName = libraryName;
20
+ this.libraryVersion = libraryVersion;
21
+ this.highestSeverity = highestSeverity;
22
+ }
23
+ }
24
+ exports.ReportCompositeKey = ReportCompositeKey;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ReportSeverityModel = void 0;
4
+ class ReportSeverityModel {
5
+ constructor(severity, priority) {
6
+ this.severity = severity;
7
+ this.priority = priority;
8
+ }
9
+ }
10
+ exports.ReportSeverityModel = ReportSeverityModel;
@@ -1,133 +1,28 @@
1
1
  "use strict";
2
- const i18n = require('i18n');
3
- const commonApi = require('../commonApi');
4
- const commonReport = require('./commonReportingFunctions');
5
- function displaySuccessMessageVulnerabilities() {
6
- console.log(i18n.__('vulnerabilitiesSuccessMessage'));
7
- }
8
- const vulnerabilityReport = async (analysis, applicationId, config) => {
9
- let depRiskReportCount = {};
10
- if (analysis.language === 'NODE') {
11
- depRiskReportCount = await commonReport.dependencyRiskReport(analysis.node.packageJSON, config);
12
- }
13
- if (config['report']) {
14
- const reportResponse = await commonReport.getReport(applicationId);
15
- if (reportResponse !== undefined) {
16
- const libraryVulnerabilityInput = createLibraryVulnerabilityInput(reportResponse.reports);
17
- const libraryVulnerabilityResponse = await getLibraryVulnerabilities(libraryVulnerabilityInput, applicationId);
18
- const severity = config['cve_severity'];
19
- const id = applicationId;
20
- const name = config.applicationName;
21
- const hasSomeVulnerabilitiesReported = formatVulnerabilityOutput(libraryVulnerabilityResponse, severity, id, name, depRiskReportCount, config);
22
- commonReport.analyseReportOptions(hasSomeVulnerabilitiesReported);
23
- }
24
- }
25
- };
26
- const createLibraryVulnerabilityInput = report => {
27
- const language = Object.keys(report[0].report)[0];
28
- const reportTree = report[0].report[language].dependencyTree;
29
- const libraries = reportTree[Object.keys(reportTree)[0]];
30
- let gav = [];
31
- for (const key of Object.keys(libraries)) {
32
- gav.push({
33
- name: libraries[key].name,
34
- group: libraries[key].group,
35
- version: libraries[key].resolved
36
- });
37
- }
38
- return {
39
- name_group_versions: gav,
40
- language: language.toUpperCase()
41
- };
42
- };
43
- const oldCountSeverity = vulnerableLibraries => {
44
- const severityCount = {
45
- critical: 0,
46
- high: 0,
47
- medium: 0,
48
- low: 0
49
- };
50
- vulnerableLibraries.forEach(lib => {
51
- lib.vulns.forEach(vuln => {
52
- if (vuln.severity_code === 'HIGH') {
53
- severityCount['high'] += 1;
54
- }
55
- else if (vuln.severity_code === 'MEDIUM') {
56
- severityCount['medium'] += 1;
57
- }
58
- else if (vuln.severity_code === 'LOW') {
59
- severityCount['low'] += 1;
60
- }
61
- else if (vuln.severity_code === 'CRITICAL') {
62
- severityCount['critical'] += 1;
63
- }
64
- });
65
- });
66
- return severityCount;
67
- };
68
- const parseVulnerabilites = libraryVulnerabilityResponse => {
69
- let parsedVulnerabilites = {};
70
- let vulnName = libraryVulnerabilityResponse.libraries;
71
- for (let x in vulnName) {
72
- let vuln = vulnName[x].vulns;
73
- if (vuln.length > 0) {
74
- let libname = vulnName[x].group +
75
- '/' +
76
- vulnName[x].file_name +
77
- '@' +
78
- vulnName[x].file_version;
79
- parsedVulnerabilites[libname] = vulnName[x].vulns;
80
- }
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatVulnerabilityOutput = exports.vulnerabilityReport = void 0;
4
+ const commonReportingFunctions_1 = require("./commonReportingFunctions");
5
+ const reportUtils_1 = require("./utils/reportUtils");
6
+ async function vulnerabilityReport(analysis, applicationId, reportId) {
7
+ const reportResponse = await (0, commonReportingFunctions_1.getReport)(analysis.config, reportId);
8
+ if (reportResponse !== undefined) {
9
+ const id = applicationId;
10
+ const name = analysis.config.applicationName;
11
+ formatVulnerabilityOutput(reportResponse.vulnerabilities, id, name, analysis.config);
81
12
  }
82
- return parsedVulnerabilites;
83
- };
84
- const formatVulnerabilityOutput = (libraryVulnerabilityResponse, severity, id, name, depRiskReportCount, config) => {
85
- let vulnerableLibraries = libraryVulnerabilityResponse.libraries.filter(data => {
86
- return data.vulns.length > 0;
87
- });
13
+ }
14
+ exports.vulnerabilityReport = vulnerabilityReport;
15
+ function formatVulnerabilityOutput(libraryVulnerabilityResponse, id, name, config) {
16
+ const vulnerableLibraries = (0, reportUtils_1.convertGenericToTypedLibraries)(libraryVulnerabilityResponse);
88
17
  const numberOfVulnerableLibraries = vulnerableLibraries.length;
89
18
  let numberOfCves = 0;
90
- vulnerableLibraries.forEach(lib => (numberOfCves += lib.vulns.length));
91
- commonReport.createLibraryHeader(id, numberOfVulnerableLibraries, numberOfCves, name);
92
- const severityCount = oldCountSeverity(vulnerableLibraries);
93
- let vulnerabilities = parseVulnerabilites(libraryVulnerabilityResponse);
94
- let filteredVulns = commonReport.filterVulnerabilitiesBySeverity(severity, vulnerabilities);
95
- let hasSomeVulnerabilitiesReported;
96
- hasSomeVulnerabilitiesReported = commonReport.printVulnerabilityResponse(severity, filteredVulns, vulnerabilities);
97
- console.log('\n **************************' +
98
- ` Found ${numberOfVulnerableLibraries} vulnerable libraries containing ${numberOfCves} CVE's ` +
99
- '************************** ');
100
- if (depRiskReportCount && depRiskReportCount.scopedCount === 0) {
101
- console.log(' No private libraries that are not scoped detected');
102
- }
103
- console.log(' \n Please go to the Contrast UI to view your dependency tree: \n' +
104
- ` \n ${config.host}/Contrast/static/ng/index.html#/${config.organizationId}/applications/${config.applicationId}/libs/dependency-tree`);
105
- return [hasSomeVulnerabilitiesReported, numberOfCves, severityCount];
106
- };
107
- const getLibraryVulnerabilities = async (input, applicationId) => {
108
- const requestBody = input;
109
- const addParams = agent.getAdditionalParams();
110
- const userParams = await util.getParams(applicationId);
111
- const protocol = getValidHost(userParams.host);
112
- const client = commonApi.getHttpClient(userParams, protocol, addParams);
113
- return client
114
- .getLibraryVulnerabilities(requestBody, userParams)
115
- .then(res => {
116
- if (res.statusCode === 200) {
117
- displaySuccessMessageVulnerabilities();
118
- return res.body;
119
- }
120
- else {
121
- handleResponseErrors(res, 'vulnerabilities');
122
- }
123
- })
124
- .catch(err => {
125
- console.log(err);
126
- });
127
- };
128
- module.exports = {
129
- vulnerabilityReport: vulnerabilityReport,
130
- getLibraryVulnerabilities: getLibraryVulnerabilities,
131
- formatVulnerabilityOutput: formatVulnerabilityOutput,
132
- createLibraryVulnerabilityInput: createLibraryVulnerabilityInput
133
- };
19
+ vulnerableLibraries.forEach(lib => (numberOfCves += lib.cveArray.length));
20
+ (0, commonReportingFunctions_1.createLibraryHeader)(id, numberOfVulnerableLibraries, numberOfCves, name);
21
+ const hasSomeVulnerabilitiesReported = (0, commonReportingFunctions_1.printVulnerabilityResponse)(vulnerableLibraries, config);
22
+ return [
23
+ hasSomeVulnerabilitiesReported,
24
+ numberOfCves,
25
+ (0, reportUtils_1.severityCount)(vulnerableLibraries)
26
+ ];
27
+ }
28
+ exports.formatVulnerabilityOutput = formatVulnerabilityOutput;
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.findNameAndVersion = exports.severityCount = exports.convertGenericToTypedLibraries = exports.findHighestSeverityCVE = void 0;
7
+ const reportLibraryModel_1 = require("../models/reportLibraryModel");
8
+ const reportSeverityModel_1 = require("../models/reportSeverityModel");
9
+ const constants_1 = __importDefault(require("../../../languageAnalysisEngine/constants"));
10
+ const { supportedLanguages: { GO } } = constants_1.default;
11
+ function findHighestSeverityCVE(cveArray) {
12
+ if (cveArray.find(cve => cve.cvss3SeverityCode === 'CRITICAL' || cve.severityCode === 'CRITICAL')) {
13
+ return new reportSeverityModel_1.ReportSeverityModel('CRITICAL', 1);
14
+ }
15
+ else if (cveArray.find(cve => cve.cvss3SeverityCode === 'HIGH' || cve.severityCode === 'HIGH')) {
16
+ return new reportSeverityModel_1.ReportSeverityModel('HIGH', 2);
17
+ }
18
+ else if (cveArray.find(cve => cve.cvss3SeverityCode === 'MEDIUM' || cve.severityCode === 'MEDIUM')) {
19
+ return new reportSeverityModel_1.ReportSeverityModel('MEDIUM', 3);
20
+ }
21
+ else if (cveArray.find(cve => cve.cvss3SeverityCode === 'LOW' || cve.severityCode === 'LOW')) {
22
+ return new reportSeverityModel_1.ReportSeverityModel('LOW', 4);
23
+ }
24
+ else if (cveArray.find(cve => cve.cvss3SeverityCode === 'NOTE' || cve.severityCode === 'NOTE')) {
25
+ return new reportSeverityModel_1.ReportSeverityModel('NOTE', 5);
26
+ }
27
+ }
28
+ exports.findHighestSeverityCVE = findHighestSeverityCVE;
29
+ function convertGenericToTypedLibraries(libraries) {
30
+ return Object.entries(libraries).map(([name, cveArray]) => {
31
+ return new reportLibraryModel_1.ReportLibraryModel(name, cveArray);
32
+ });
33
+ }
34
+ exports.convertGenericToTypedLibraries = convertGenericToTypedLibraries;
35
+ function severityCount(vulnerableLibraries) {
36
+ const severityCount = {
37
+ critical: 0,
38
+ high: 0,
39
+ medium: 0,
40
+ low: 0,
41
+ note: 0
42
+ };
43
+ vulnerableLibraries.forEach(lib => {
44
+ lib.cveArray.forEach(cve => {
45
+ if (cve.cvss3SeverityCode === 'CRITICAL' ||
46
+ cve.severityCode === 'CRITICAL') {
47
+ severityCount['critical'] += 1;
48
+ }
49
+ else if (cve.cvss3SeverityCode === 'HIGH' ||
50
+ cve.severityCode === 'HIGH') {
51
+ severityCount['high'] += 1;
52
+ }
53
+ else if (cve.cvss3SeverityCode === 'MEDIUM' ||
54
+ cve.severityCode === 'MEDIUM') {
55
+ severityCount['medium'] += 1;
56
+ }
57
+ else if (cve.cvss3SeverityCode === 'LOW' ||
58
+ cve.severityCode === 'LOW') {
59
+ severityCount['low'] += 1;
60
+ }
61
+ else if (cve.cvss3SeverityCode === 'NOTE' ||
62
+ cve.severityCode === 'NOTE') {
63
+ severityCount['note'] += 1;
64
+ }
65
+ });
66
+ });
67
+ return severityCount;
68
+ }
69
+ exports.severityCount = severityCount;
70
+ function findNameAndVersion(library, config) {
71
+ if (config.language.toUpperCase() === GO) {
72
+ const nameVersion = library.name.split('@');
73
+ const name = nameVersion[0];
74
+ const version = nameVersion[1];
75
+ return { name, version };
76
+ }
77
+ else {
78
+ const splitLibraryName = library.name.split('/');
79
+ const nameVersion = splitLibraryName[1].split('@');
80
+ const name = nameVersion[0];
81
+ const version = nameVersion[1];
82
+ return { name, version };
83
+ }
84
+ }
85
+ exports.findNameAndVersion = findNameAndVersion;
@@ -24,7 +24,9 @@ const newSendSnapShot = async (analysis, applicationId) => {
24
24
  .sendSnapshot(requestBody, analysis.config)
25
25
  .then(res => {
26
26
  if (res.statusCode === 201) {
27
- displaySnapshotSuccessMessage(analysis.config);
27
+ if (analysis.config.host !== 'https://ce.contrastsecurity.com/') {
28
+ displaySnapshotSuccessMessage(analysis.config);
29
+ }
28
30
  return res.body;
29
31
  }
30
32
  else {
@@ -7,7 +7,7 @@ exports.startAudit = void 0;
7
7
  const catalogueApplication_1 = require("../../audit/catalogueApplication/catalogueApplication");
8
8
  const commonApi_1 = __importDefault(require("../../audit/languageAnalysisEngine/commonApi"));
9
9
  const identifyLanguageAE = require('./../../audit/languageAnalysisEngine');
10
- const languageFactory = require('./../../audit/languageAnalysisEngine/langugageAnalysisFactory');
10
+ const languageFactory = require('../../audit/languageAnalysisEngine/languageAnalysisFactory');
11
11
  const dealWithNoAppId = async (config) => {
12
12
  let appID;
13
13
  try {
@@ -17,9 +17,12 @@ const dealWithNoAppId = async (config) => {
17
17
  }
18
18
  }
19
19
  catch (e) {
20
- console.log(e);
20
+ if (e.toString().includes('tunneling socket could not be established')) {
21
+ console.log(e.message);
22
+ console.log('There seems to be an issue with your proxy, please check and try again');
23
+ }
24
+ process.exit(1);
21
25
  }
22
- console.log(appID);
23
26
  return appID;
24
27
  };
25
28
  const startAudit = async (config) => {
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const fs_1 = __importDefault(require("fs"));
7
+ function saveFile(config, rawResults) {
8
+ const fileName = `${config.applicationId}-sbom-cyclonedx.json`;
9
+ fs_1.default.writeFileSync(fileName, JSON.stringify(rawResults));
10
+ }
11
+ exports.default = saveFile;
@@ -7,7 +7,15 @@ const { sleep } = require('../../utils/requestUtils');
7
7
  const i18n = require('i18n');
8
8
  const { returnOra, startSpinner, failSpinner, succeedSpinner } = require('../../utils/oraWrapper');
9
9
  const { TIMEOUT, AUTH_UI_URL } = require('../../constants/constants');
10
- const processAuth = async (config) => {
10
+ const parsedCLIOptions = require('../../utils/parsedCLIOptions');
11
+ const constants = require('../../constants');
12
+ const commandLineUsage = require('command-line-usage');
13
+ const processAuth = async (argv, config) => {
14
+ let authParams = parsedCLIOptions.getCommandLineArgsCustom(argv, constants.commandLineDefinitions.authOptionDefinitions);
15
+ if (authParams.help) {
16
+ console.log(authUsageGuide);
17
+ process.exit(0);
18
+ }
11
19
  const token = uuidv4();
12
20
  const url = `${AUTH_UI_URL}/?token=${token}`;
13
21
  console.log(i18n.__('redirectAuth', url));
@@ -56,6 +64,16 @@ const pollAuthResult = async (token, client) => {
56
64
  console.log(err);
57
65
  });
58
66
  };
67
+ const authUsageGuide = commandLineUsage([
68
+ {
69
+ header: i18n.__('authHeader'),
70
+ content: [i18n.__('constantsAuthHeaderContents')]
71
+ },
72
+ {
73
+ header: i18n.__('constantsAuthUsageHeader'),
74
+ content: [i18n.__('constantsAuthUsageContents')]
75
+ }
76
+ ]);
59
77
  module.exports = {
60
78
  processAuth: processAuth
61
79
  };
@@ -1,14 +1,16 @@
1
1
  "use strict";
2
- const commandLineArgs = require('command-line-args');
2
+ const parsedCLIOptions = require('../../utils/parsedCLIOptions');
3
+ const constants = require('../../constants');
4
+ const commandLineUsage = require('command-line-usage');
5
+ const i18n = require('i18n');
3
6
  const processConfig = (argv, config) => {
4
- const options = [{ name: 'clear', alias: 'c', type: Boolean }];
5
7
  try {
6
- const configOptions = commandLineArgs(options, {
7
- argv,
8
- caseInsensitive: true,
9
- camelCase: true
10
- });
11
- if (configOptions.clear) {
8
+ let configParams = parsedCLIOptions.getCommandLineArgsCustom(argv, constants.commandLineDefinitions.configOptionDefinitions);
9
+ if (configParams.help) {
10
+ console.log(configUsageGuide);
11
+ process.exit(0);
12
+ }
13
+ if (configParams.clear) {
12
14
  config.clear();
13
15
  }
14
16
  else {
@@ -19,6 +21,15 @@ const processConfig = (argv, config) => {
19
21
  console.log(e.message.toString());
20
22
  }
21
23
  };
24
+ const configUsageGuide = commandLineUsage([
25
+ {
26
+ header: i18n.__('configHeader')
27
+ },
28
+ {
29
+ content: [i18n.__('constantsConfigUsageContents')],
30
+ optionList: constants.commandLineDefinitions.configOptionDefinitions
31
+ }
32
+ ]);
22
33
  module.exports = {
23
34
  processConfig: processConfig
24
35
  };
@@ -1,37 +1,20 @@
1
1
  "use strict";
2
2
  const { startScan } = require('../../scan/scanController');
3
- const { formatScanOutput } = require('../../scan/scan');
4
3
  const { scanUsageGuide } = require('../../scan/help');
5
4
  const scanConfig = require('../../scan/scanConfig');
6
- const saveResults = require('../../scan/saveResults');
7
- const commonApi = require('../../utils/commonApi');
8
- const i18n = require('i18n');
5
+ const { saveScanFile } = require('../../utils/saveFile');
6
+ const { ScanResultsModel } = require('../../scan/models/scanResultsModel');
7
+ const { formatScanOutput } = require('../../scan/scan');
9
8
  const processScan = async (argvMain) => {
10
- if (argvMain.indexOf('--help') !== -1) {
11
- printHelpMessage();
12
- process.exit(1);
13
- }
14
9
  let config = scanConfig.getScanConfig(argvMain);
15
- let scanResults = await startScan(config);
10
+ let scanResults = new ScanResultsModel(await startScan(config));
16
11
  if (scanResults) {
17
- formatScanOutput(scanResults?.projectOverview, scanResults?.scanResultsInstances);
12
+ formatScanOutput(scanResults);
18
13
  }
19
- if (config.save) {
20
- if (config.save.toLowerCase() === 'sarif') {
21
- const scanId = scanResults.scanDetail.id;
22
- const client = commonApi.getHttpClient(config);
23
- const rawResults = await client.getSpecificScanResultSarif(config, scanId);
24
- saveResults.writeResultsToFile(rawResults?.body);
25
- }
26
- else {
27
- console.log(i18n.__('scanNoFiletypeSpecifiedForSave'));
28
- }
14
+ if (config.save !== undefined) {
15
+ await saveScanFile(config, scanResults);
29
16
  }
30
17
  };
31
- const printHelpMessage = () => {
32
- console.log(scanUsageGuide);
33
- };
34
18
  module.exports = {
35
- processScan,
36
- printHelpMessage
19
+ processScan
37
20
  };
@@ -77,7 +77,9 @@ HTTPClient.prototype.getScanId = function getScanId(config, codeArtifactId) {
77
77
  options.url = url;
78
78
  options.body = {
79
79
  codeArtifactId: codeArtifactId,
80
- label: `Started by CLI tool at ${new Date().toString()}`
80
+ label: config.label
81
+ ? config.label
82
+ : `Started by CLI tool at ${new Date().toString()}`
81
83
  };
82
84
  return requestUtils.sendRequest({ method: 'post', options });
83
85
  };
@@ -97,6 +99,9 @@ HTTPClient.prototype.createProjectId = function createProjectId(config) {
97
99
  name: config.name,
98
100
  archived: 'false'
99
101
  };
102
+ if (config.language) {
103
+ options.body.language = config.language;
104
+ }
100
105
  options.url = createHarmonyProjectsUrl(config);
101
106
  return requestUtils.sendRequest({ method: 'post', options });
102
107
  };
@@ -140,28 +145,28 @@ HTTPClient.prototype.catalogueCommand = function catalogueCommand(config) {
140
145
  return requestUtils.sendRequest({ method: 'post', options });
141
146
  };
142
147
  HTTPClient.prototype.sendSnapshot = function sendSnapshot(requestBody, config) {
148
+ if (config.language.toUpperCase() === 'RUBY') {
149
+ console.log('sendSnapshot requestBody', requestBody.snapshot.ruby);
150
+ }
143
151
  const options = _.cloneDeep(this.requestOptions);
144
152
  let url = createSnapshotURL(config);
145
153
  options.url = url;
146
154
  options.body = requestBody;
147
155
  return requestUtils.sendRequest({ method: 'post', options });
148
156
  };
149
- HTTPClient.prototype.getReport = function getReport(config) {
150
- const options = _.cloneDeep(this.requestOptions);
151
- let url = createReportUrl(config);
152
- options.url = url;
153
- return requestUtils.sendRequest({ method: 'get', options });
154
- };
155
- HTTPClient.prototype.getSpecificReport = function getSpecificReport(config, reportId) {
157
+ HTTPClient.prototype.getReportById = function getReportById(config, reportId) {
156
158
  const options = _.cloneDeep(this.requestOptions);
157
- let url = createSpecificReportUrl(config, reportId);
158
- options.url = url;
159
+ if (config.ignoreDev) {
160
+ options.url = createSpecificReportWithProdUrl(config, reportId);
161
+ }
162
+ else {
163
+ options.url = createSpecificReportUrl(config, reportId);
164
+ }
159
165
  return requestUtils.sendRequest({ method: 'get', options });
160
166
  };
161
- HTTPClient.prototype.getLibraryVulnerabilities = function getLibraryVulnerabilities(requestBody, config) {
167
+ HTTPClient.prototype.getLibraryVulnerabilities = function getLibraryVulnerabilities(config, requestBody) {
162
168
  const options = _.cloneDeep(this.requestOptions);
163
- let url = createLibraryVulnerabilitiesUrl(config);
164
- options.url = url;
169
+ options.url = createLibraryVulnerabilitiesUrl(config);
165
170
  options.body = requestBody;
166
171
  return requestUtils.sendRequest({ method: 'put', options });
167
172
  };
@@ -171,12 +176,6 @@ HTTPClient.prototype.getAppId = function getAppId(config) {
171
176
  options.url = url;
172
177
  return requestUtils.sendRequest({ method: 'get', options });
173
178
  };
174
- HTTPClient.prototype.getDependencyTree = function getReport(orgUuid, appId, reportId) {
175
- const options = _.cloneDeep(this.requestOptions);
176
- let url = createGetDependencyTree(options.uri, orgUuid, appId, reportId);
177
- options.url = url;
178
- return requestUtils.sendRequest({ method: 'get', options });
179
- };
180
179
  function getServerlessHost(config = {}) {
181
180
  const originalHost = config?.host || config?.get('host');
182
181
  const host = originalHost?.endsWith('/')
@@ -224,6 +223,11 @@ HTTPClient.prototype.checkLibrary = function checkLibrary(data) {
224
223
  options.body = data;
225
224
  return requestUtils.sendRequest({ method: 'post', options });
226
225
  };
226
+ HTTPClient.prototype.getSbom = function getSbom(config) {
227
+ const options = _.cloneDeep(this.requestOptions);
228
+ options.url = createSbomCycloneDXUrl(config);
229
+ return requestUtils.sendRequest({ method: 'get', options });
230
+ };
227
231
  const createGetScanIdURL = config => {
228
232
  return `${config.host}/Contrast/api/sast/v1/organizations/${config.organizationId}/projects/${config.projectId}/scans/`;
229
233
  };
@@ -263,18 +267,18 @@ const createAppNameUrl = config => {
263
267
  function createLibraryVulnerabilitiesUrl(config) {
264
268
  return `${config.host}/Contrast/api/ng/${config.organizationId}/libraries/artifactsByGroupNameVersion`;
265
269
  }
266
- function createReportUrl(config) {
267
- return `${config.host}/Contrast/api/ng/sca/organizations/${config.organizationId}/applications/${config.applicationId}/reports`;
268
- }
269
270
  function createSpecificReportUrl(config, reportId) {
270
- return `${config.host}/Contrast/api/ng/sca/organizations/${config.organizationId}/applications/${config.applicationId}/reports/${reportId}?nodesToInclude=PROD`;
271
+ return `${config.host}/Contrast/api/ng/sca/organizations/${config.organizationId}/applications/${config.applicationId}/reports/${reportId}`;
272
+ }
273
+ function createSpecificReportWithProdUrl(config, reportId) {
274
+ return createSpecificReportUrl(config, reportId).concat(`?nodesToInclude=PROD`);
271
275
  }
272
276
  function createDataUrl() {
273
277
  return `https://ardy.contrastsecurity.com/production`;
274
278
  }
275
- const createGetDependencyTree = (protocol, orgUuid, appId, reportId) => {
276
- return `${protocol}/Contrast/api/ng/sca/organizations/${orgUuid}/applications/${appId}/reports/${reportId}`;
277
- };
279
+ function createSbomCycloneDXUrl(config) {
280
+ return `${config.host}/Contrast/api/ng/${config.organizationId}/applications/${config.applicationId}/libraries/sbom/cyclonedx`;
281
+ }
278
282
  module.exports = HTTPClient;
279
283
  module.exports.pollForAuthUrl = pollForAuthUrl;
280
284
  module.exports.getServerlessHost = getServerlessHost;
@@ -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.libraryAnalysisError = exports.handleResponseErrors = exports.getErrorMessage = exports.generalError = exports.hostWarningError = exports.failOptionError = exports.proxyError = exports.forbiddenError = exports.badRequestError = exports.unauthenticatedError = exports.genericError = void 0;
6
+ exports.findCommandOnError = exports.libraryAnalysisError = exports.handleResponseErrors = exports.getErrorMessage = exports.generalError = exports.hostWarningError = 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) {
@@ -71,6 +71,7 @@ const badRequestError = (catalogue) => {
71
71
  exports.badRequestError = badRequestError;
72
72
  const forbiddenError = () => {
73
73
  generalError('forbiddenRequestErrorHeader', 'forbiddenRequestErrorMessage');
74
+ process.exit(1);
74
75
  };
75
76
  exports.forbiddenError = forbiddenError;
76
77
  const proxyError = () => {
@@ -106,3 +107,18 @@ const generalError = (header, message) => {
106
107
  console.log(finalMessage);
107
108
  };
108
109
  exports.generalError = generalError;
110
+ const findCommandOnError = (unknownOptions) => {
111
+ const commandKeywords = {
112
+ auth: 'auth',
113
+ audit: 'audit',
114
+ scan: 'scan',
115
+ lambda: 'lambda',
116
+ config: 'config'
117
+ };
118
+ const containsCommandKeyword = unknownOptions.some(command => commandKeywords[command]);
119
+ if (containsCommandKeyword) {
120
+ const foundCommands = unknownOptions.filter(command => commandKeywords[command]);
121
+ return foundCommands[0];
122
+ }
123
+ };
124
+ exports.findCommandOnError = findCommandOnError;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.isCorrectNodeVersion = exports.findLatestCLIVersion = void 0;
7
+ const latest_version_1 = __importDefault(require("latest-version"));
8
+ const constants_1 = require("../constants/constants");
9
+ const boxen_1 = __importDefault(require("boxen"));
10
+ const chalk_1 = __importDefault(require("chalk"));
11
+ const semver_1 = __importDefault(require("semver"));
12
+ async function findLatestCLIVersion(updateMessageHidden) {
13
+ if (!updateMessageHidden) {
14
+ const latestCLIVersion = await (0, latest_version_1.default)('@contrast/contrast');
15
+ if (semver_1.default.lt(constants_1.APP_VERSION, latestCLIVersion)) {
16
+ const updateAvailableMessage = `Update available ${chalk_1.default.yellow(constants_1.APP_VERSION)} → ${chalk_1.default.green(latestCLIVersion)}`;
17
+ const npmUpdateAvailableCommand = `Run ${chalk_1.default.cyan('npm i @contrast/contrast -g')} to update via npm`;
18
+ const homebrewUpdateAvailableCommand = `Run ${chalk_1.default.cyan('brew install contrastsecurity/tap/contrast')} to update via brew`;
19
+ console.log((0, boxen_1.default)(`${updateAvailableMessage}\n${npmUpdateAvailableCommand}\n\n${homebrewUpdateAvailableCommand}`, {
20
+ titleAlignment: 'center',
21
+ margin: 1,
22
+ padding: 1,
23
+ align: 'center'
24
+ }));
25
+ }
26
+ }
27
+ }
28
+ exports.findLatestCLIVersion = findLatestCLIVersion;
29
+ async function isCorrectNodeVersion(currentVersion) {
30
+ return semver_1.default.satisfies(currentVersion, '>=16.13.2 <17');
31
+ }
32
+ exports.isCorrectNodeVersion = isCorrectNodeVersion;