@contrast/contrast 1.0.0 → 1.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.
Files changed (201) hide show
  1. package/.prettierignore +2 -0
  2. package/README.md +120 -47
  3. package/dist/audit/AnalysisEngine.js +37 -0
  4. package/dist/audit/catalogueApplication/catalogueApplication.js +36 -0
  5. package/dist/audit/dotnetAnalysisEngine/index.js +25 -0
  6. package/dist/audit/dotnetAnalysisEngine/parseLockFileContents.js +35 -0
  7. package/dist/audit/dotnetAnalysisEngine/parseProjectFileContents.js +15 -0
  8. package/dist/audit/dotnetAnalysisEngine/readLockFileContents.js +18 -0
  9. package/dist/audit/dotnetAnalysisEngine/readProjectFileContents.js +14 -0
  10. package/dist/audit/dotnetAnalysisEngine/sanitizer.js +9 -0
  11. package/dist/audit/goAnalysisEngine/index.js +17 -0
  12. package/dist/audit/goAnalysisEngine/parseProjectFileContents.js +164 -0
  13. package/dist/audit/goAnalysisEngine/readProjectFileContents.js +21 -0
  14. package/dist/audit/goAnalysisEngine/sanitizer.js +5 -0
  15. package/dist/audit/javaAnalysisEngine/index.js +34 -0
  16. package/dist/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +153 -0
  17. package/dist/audit/javaAnalysisEngine/parseProjectFileContents.js +353 -0
  18. package/dist/audit/javaAnalysisEngine/readProjectFileContents.js +98 -0
  19. package/dist/audit/javaAnalysisEngine/sanitizer.js +5 -0
  20. package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +24 -0
  21. package/dist/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +24 -0
  22. package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasLockFile.js +35 -0
  23. package/dist/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +23 -0
  24. package/dist/audit/languageAnalysisEngine/commonApi.js +18 -0
  25. package/dist/audit/languageAnalysisEngine/constants.js +20 -0
  26. package/dist/audit/languageAnalysisEngine/filterProjectPath.js +20 -0
  27. package/dist/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +25 -0
  28. package/dist/audit/languageAnalysisEngine/getProjectRootFilenames.js +39 -0
  29. package/dist/audit/languageAnalysisEngine/index.js +39 -0
  30. package/dist/audit/languageAnalysisEngine/langugageAnalysisFactory.js +70 -0
  31. package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +121 -0
  32. package/dist/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +17 -0
  33. package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +257 -0
  34. package/dist/audit/languageAnalysisEngine/report/newReportingFeature.js +81 -0
  35. package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +133 -0
  36. package/dist/audit/languageAnalysisEngine/sendSnapshot.js +41 -0
  37. package/dist/audit/languageAnalysisEngine/util/capabilities.js +11 -0
  38. package/dist/audit/languageAnalysisEngine/util/generalAPI.js +39 -0
  39. package/dist/audit/languageAnalysisEngine/util/requestUtils.js +14 -0
  40. package/dist/audit/nodeAnalysisEngine/handleNPMLockFileV2.js +40 -0
  41. package/dist/audit/nodeAnalysisEngine/index.js +31 -0
  42. package/dist/audit/nodeAnalysisEngine/parseNPMLockFileContents.js +18 -0
  43. package/dist/audit/nodeAnalysisEngine/parseYarn2LockFileContents.js +51 -0
  44. package/dist/audit/nodeAnalysisEngine/parseYarnLockFileContents.js +18 -0
  45. package/dist/audit/nodeAnalysisEngine/readNPMLockFileContents.js +17 -0
  46. package/dist/audit/nodeAnalysisEngine/readProjectFileContents.js +14 -0
  47. package/dist/audit/nodeAnalysisEngine/readYarnLockFileContents.js +24 -0
  48. package/dist/audit/nodeAnalysisEngine/sanitizer.js +9 -0
  49. package/dist/audit/phpAnalysisEngine/index.js +23 -0
  50. package/dist/audit/phpAnalysisEngine/parseLockFileContents.js +52 -0
  51. package/dist/audit/phpAnalysisEngine/readLockFileContents.js +13 -0
  52. package/dist/audit/phpAnalysisEngine/readProjectFileContents.js +16 -0
  53. package/dist/audit/phpAnalysisEngine/sanitizer.js +5 -0
  54. package/dist/audit/pythonAnalysisEngine/index.js +25 -0
  55. package/dist/audit/pythonAnalysisEngine/parsePipfileLockContents.js +17 -0
  56. package/dist/audit/pythonAnalysisEngine/parseProjectFileContents.js +21 -0
  57. package/dist/audit/pythonAnalysisEngine/readPipfileLockFileContents.js +13 -0
  58. package/dist/audit/pythonAnalysisEngine/readPythonProjectFileContents.js +14 -0
  59. package/dist/audit/pythonAnalysisEngine/sanitizer.js +7 -0
  60. package/dist/audit/rubyAnalysisEngine/index.js +25 -0
  61. package/dist/audit/rubyAnalysisEngine/parseGemfileLockContents.js +176 -0
  62. package/dist/audit/rubyAnalysisEngine/parsedGemfile.js +22 -0
  63. package/dist/audit/rubyAnalysisEngine/readGemfileContents.js +14 -0
  64. package/dist/audit/rubyAnalysisEngine/readGemfileLockContents.js +14 -0
  65. package/dist/audit/rubyAnalysisEngine/sanitizer.js +6 -0
  66. package/dist/commands/audit/auditConfig.js +25 -0
  67. package/dist/commands/audit/auditController.js +31 -0
  68. package/dist/commands/audit/help.js +52 -0
  69. package/dist/commands/audit/processAudit.js +18 -0
  70. package/dist/commands/auth/auth.js +1 -1
  71. package/dist/commands/scan/processScan.js +19 -5
  72. package/dist/common/HTTPClient.js +101 -13
  73. package/dist/common/errorHandling.js +49 -1
  74. package/dist/common/findLatestCLIVersion.js +23 -0
  75. package/dist/constants/constants.js +1 -1
  76. package/dist/constants/lambda.js +32 -4
  77. package/dist/constants/locales.js +39 -16
  78. package/dist/constants.js +148 -20
  79. package/dist/index.js +7 -1
  80. package/dist/lambda/aws.js +14 -11
  81. package/dist/lambda/help.js +4 -0
  82. package/dist/lambda/lambda.js +50 -27
  83. package/dist/lambda/lambdaUtils.js +72 -0
  84. package/dist/lambda/logUtils.js +11 -1
  85. package/dist/lambda/scanDetailCompletion.js +4 -4
  86. package/dist/lambda/scanRequest.js +11 -5
  87. package/dist/lambda/utils.js +110 -53
  88. package/dist/scan/autoDetection.js +0 -32
  89. package/dist/scan/fileUtils.js +1 -1
  90. package/dist/scan/help.js +12 -40
  91. package/dist/scan/populateProjectIdAndProjectName.js +4 -0
  92. package/dist/scan/saveResults.js +15 -0
  93. package/dist/scan/scan.js +77 -42
  94. package/dist/scan/scanConfig.js +20 -0
  95. package/dist/scan/scanController.js +13 -15
  96. package/dist/scan/scanResults.js +18 -16
  97. package/dist/utils/commonApi.js +3 -3
  98. package/dist/utils/fileUtils.js +31 -0
  99. package/dist/utils/paramsUtil/commandlineParams.js +1 -20
  100. package/dist/utils/paramsUtil/genericCommandLineParams.js +12 -0
  101. package/dist/utils/paramsUtil/paramHandler.js +3 -6
  102. package/dist/utils/parsedCLIOptions.js +14 -8
  103. package/package.json +26 -21
  104. package/src/audit/AnalysisEngine.js +103 -0
  105. package/src/audit/catalogueApplication/catalogueApplication.js +42 -0
  106. package/src/audit/dotnetAnalysisEngine/index.js +26 -0
  107. package/src/audit/dotnetAnalysisEngine/parseLockFileContents.js +47 -0
  108. package/src/audit/dotnetAnalysisEngine/parseProjectFileContents.js +29 -0
  109. package/src/audit/dotnetAnalysisEngine/readLockFileContents.js +30 -0
  110. package/src/audit/dotnetAnalysisEngine/readProjectFileContents.js +26 -0
  111. package/src/audit/dotnetAnalysisEngine/sanitizer.js +11 -0
  112. package/src/audit/goAnalysisEngine/index.js +18 -0
  113. package/src/audit/goAnalysisEngine/parseProjectFileContents.js +209 -0
  114. package/src/audit/goAnalysisEngine/readProjectFileContents.js +31 -0
  115. package/src/audit/goAnalysisEngine/sanitizer.js +7 -0
  116. package/src/audit/javaAnalysisEngine/index.js +41 -0
  117. package/src/audit/javaAnalysisEngine/parseMavenProjectFileContents.js +222 -0
  118. package/src/audit/javaAnalysisEngine/parseProjectFileContents.js +420 -0
  119. package/src/audit/javaAnalysisEngine/readProjectFileContents.js +141 -0
  120. package/src/audit/javaAnalysisEngine/sanitizer.js +6 -0
  121. package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedLanguages.js +35 -0
  122. package/src/audit/languageAnalysisEngine/checkForMultipleIdentifiedProjectFiles.js +41 -0
  123. package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasLockFile.js +54 -0
  124. package/src/audit/languageAnalysisEngine/checkIdentifiedLanguageHasProjectFile.js +32 -0
  125. package/src/audit/languageAnalysisEngine/commonApi.js +20 -0
  126. package/src/audit/languageAnalysisEngine/constants.js +23 -0
  127. package/src/audit/languageAnalysisEngine/filterProjectPath.js +21 -0
  128. package/src/audit/languageAnalysisEngine/getIdentifiedLanguageInfo.js +41 -0
  129. package/src/audit/languageAnalysisEngine/getProjectRootFilenames.js +72 -0
  130. package/src/audit/languageAnalysisEngine/index.js +45 -0
  131. package/src/audit/languageAnalysisEngine/langugageAnalysisFactory.js +94 -0
  132. package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +177 -0
  133. package/src/audit/languageAnalysisEngine/report/checkIgnoreDevDep.js +27 -0
  134. package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.js +303 -0
  135. package/src/audit/languageAnalysisEngine/report/newReportingFeature.js +124 -0
  136. package/src/audit/languageAnalysisEngine/report/reportingFeature.js +190 -0
  137. package/src/audit/languageAnalysisEngine/sendSnapshot.js +51 -0
  138. package/src/audit/languageAnalysisEngine/util/capabilities.js +12 -0
  139. package/src/audit/languageAnalysisEngine/util/generalAPI.js +43 -0
  140. package/src/audit/languageAnalysisEngine/util/requestUtils.js +17 -0
  141. package/src/audit/nodeAnalysisEngine/handleNPMLockFileV2.js +49 -0
  142. package/src/audit/nodeAnalysisEngine/index.js +35 -0
  143. package/src/audit/nodeAnalysisEngine/parseNPMLockFileContents.js +20 -0
  144. package/src/audit/nodeAnalysisEngine/parseYarn2LockFileContents.js +63 -0
  145. package/src/audit/nodeAnalysisEngine/parseYarnLockFileContents.js +26 -0
  146. package/src/audit/nodeAnalysisEngine/readNPMLockFileContents.js +23 -0
  147. package/src/audit/nodeAnalysisEngine/readProjectFileContents.js +27 -0
  148. package/src/audit/nodeAnalysisEngine/readYarnLockFileContents.js +36 -0
  149. package/src/audit/nodeAnalysisEngine/sanitizer.js +11 -0
  150. package/src/audit/phpAnalysisEngine/index.js +27 -0
  151. package/src/audit/phpAnalysisEngine/parseLockFileContents.js +60 -0
  152. package/src/audit/phpAnalysisEngine/readLockFileContents.js +14 -0
  153. package/src/audit/phpAnalysisEngine/readProjectFileContents.js +25 -0
  154. package/src/audit/phpAnalysisEngine/sanitizer.js +4 -0
  155. package/src/audit/pythonAnalysisEngine/index.js +55 -0
  156. package/src/audit/pythonAnalysisEngine/parsePipfileLockContents.js +23 -0
  157. package/src/audit/pythonAnalysisEngine/parseProjectFileContents.js +33 -0
  158. package/src/audit/pythonAnalysisEngine/readPipfileLockFileContents.js +16 -0
  159. package/src/audit/pythonAnalysisEngine/readPythonProjectFileContents.js +22 -0
  160. package/src/audit/pythonAnalysisEngine/sanitizer.js +9 -0
  161. package/src/audit/rubyAnalysisEngine/index.js +30 -0
  162. package/src/audit/rubyAnalysisEngine/parseGemfileLockContents.js +215 -0
  163. package/src/audit/rubyAnalysisEngine/parsedGemfile.js +39 -0
  164. package/src/audit/rubyAnalysisEngine/readGemfileContents.js +18 -0
  165. package/src/audit/rubyAnalysisEngine/readGemfileLockContents.js +17 -0
  166. package/src/audit/rubyAnalysisEngine/sanitizer.js +8 -0
  167. package/src/commands/audit/auditConfig.ts +30 -0
  168. package/src/commands/audit/auditController.ts +31 -0
  169. package/src/commands/audit/help.ts +48 -0
  170. package/src/commands/audit/processAudit.ts +19 -0
  171. package/src/commands/auth/auth.js +1 -1
  172. package/src/commands/scan/processScan.js +20 -5
  173. package/src/common/HTTPClient.js +136 -14
  174. package/src/common/errorHandling.ts +56 -1
  175. package/src/common/findLatestCLIVersion.ts +27 -0
  176. package/src/constants/constants.js +1 -1
  177. package/src/constants/lambda.js +45 -4
  178. package/src/constants/locales.js +48 -20
  179. package/src/constants.js +168 -22
  180. package/src/index.ts +9 -2
  181. package/src/lambda/aws.ts +13 -12
  182. package/src/lambda/help.ts +4 -0
  183. package/src/lambda/lambda.ts +53 -34
  184. package/src/lambda/lambdaUtils.ts +111 -0
  185. package/src/lambda/logUtils.ts +19 -1
  186. package/src/lambda/scanDetailCompletion.ts +4 -4
  187. package/src/lambda/scanRequest.ts +13 -11
  188. package/src/lambda/utils.ts +149 -81
  189. package/src/scan/autoDetection.js +0 -29
  190. package/src/scan/fileUtils.js +1 -1
  191. package/src/scan/help.js +12 -45
  192. package/src/scan/populateProjectIdAndProjectName.js +4 -0
  193. package/src/scan/saveResults.js +15 -0
  194. package/src/scan/scan.js +95 -59
  195. package/src/scan/scanConfig.js +29 -0
  196. package/src/scan/scanController.js +13 -13
  197. package/src/scan/scanResults.js +21 -19
  198. package/src/utils/commonApi.js +2 -3
  199. package/src/utils/paramsUtil/commandlineParams.js +1 -26
  200. package/src/utils/paramsUtil/paramHandler.js +3 -7
  201. package/src/utils/parsedCLIOptions.js +11 -9
@@ -0,0 +1,48 @@
1
+ import commandLineUsage from 'command-line-usage'
2
+ import i18n from 'i18n'
3
+ import constants from '../../constants'
4
+
5
+ const auditUsageGuide = commandLineUsage([
6
+ {
7
+ header: i18n.__('auditHeader'),
8
+ content: [i18n.__('auditHeaderMessage')]
9
+ },
10
+ {
11
+ header: i18n.__('constantsPrerequisitesHeader'),
12
+ content: [
13
+ '{bold ' +
14
+ i18n.__('constantsAuditPrerequisitesContentSupportedLanguages') +
15
+ '}',
16
+ '{bold ' +
17
+ i18n.__('constantsAuditPrerequisitesContentJava') +
18
+ '}' +
19
+ i18n.__('constantsAuditPrerequisitesContentMessage'),
20
+ '',
21
+ '{italic ' + i18n.__('constantsJavaNote') + '}',
22
+ '{italic ' + i18n.__('constantsJavaNoteGradle') + '}',
23
+ '',
24
+ '{bold ' +
25
+ i18n.__('constantsAuditPrerequisitesContentDotNet') +
26
+ '}' +
27
+ i18n.__('constantsAuditPrerequisitesContentDotNetMessage'),
28
+ '{bold ' +
29
+ i18n.__('constantsAuditPrerequisitesContentLanguageNode') +
30
+ '}' +
31
+ i18n.__('constantsAuditPrerequisitesContentLanguageNodeMessage'),
32
+ '{bold ' +
33
+ i18n.__('constantsAuditPrerequisitesContentLanguageRuby') +
34
+ '}' +
35
+ i18n.__('constantsAuditPrerequisitesContentLanguageRubyMessage'),
36
+ '{bold ' +
37
+ i18n.__('constantsAuditPrerequisitesContentLanguagePython') +
38
+ '}' +
39
+ i18n.__('constantsAuditPrerequisitesContentLanguagePythonMessage')
40
+ ]
41
+ },
42
+ {
43
+ header: i18n.__('constantsAuditOptions'),
44
+ optionList: constants.commandLineDefinitions.auditOptionDefinitions
45
+ }
46
+ ])
47
+
48
+ export { auditUsageGuide }
@@ -0,0 +1,19 @@
1
+ import { startAudit } from './auditController'
2
+ import { getAuditConfig } from './auditConfig'
3
+ import { auditUsageGuide } from './help'
4
+
5
+ export type parameterInput = string[]
6
+
7
+ export const processAudit = async (argv: parameterInput) => {
8
+ if (argv.indexOf('--help') != -1) {
9
+ printHelpMessage()
10
+ process.exit(1)
11
+ }
12
+ const config = getAuditConfig(argv)
13
+ const auditResults = await startAudit(config)
14
+ //report here
15
+ }
16
+
17
+ const printHelpMessage = () => {
18
+ console.log(auditUsageGuide)
19
+ }
@@ -44,7 +44,7 @@ const isAuthComplete = async (token, timeout, config) => {
44
44
  let result = await pollAuthResult(token, client)
45
45
  if (result.statusCode === 200) {
46
46
  succeedSpinner(authSpinner, i18n.__('authSuccessMessage'))
47
- console.log(i18n.__('runScanMessage'))
47
+ console.log(i18n.__('runAuthSuccessMessage'))
48
48
  return result.body
49
49
  }
50
50
  let endTime = new Date() - startTime
@@ -1,22 +1,37 @@
1
1
  const { startScan } = require('../../scan/scanController')
2
- const paramHandler = require('../../utils/paramsUtil/paramHandler')
3
2
  const { formatScanOutput } = require('../../scan/scan')
4
3
  const { scanUsageGuide } = require('../../scan/help')
4
+ const scanConfig = require('../../scan/scanConfig')
5
+ const saveResults = require('../../scan/saveResults')
6
+ const commonApi = require('../../utils/commonApi')
7
+ const i18n = require('i18n')
5
8
 
6
- const processScan = async () => {
7
- let getScanSubCommands = paramHandler.getScanSubCommands()
8
- if (getScanSubCommands.help) {
9
+ const processScan = async argvMain => {
10
+ if (argvMain.indexOf('--help') !== -1) {
9
11
  printHelpMessage()
10
12
  process.exit(1)
11
13
  }
12
14
 
13
- let scanResults = await startScan()
15
+ let config = scanConfig.getScanConfig(argvMain)
16
+
17
+ let scanResults = await startScan(config)
14
18
  if (scanResults) {
15
19
  formatScanOutput(
16
20
  scanResults?.projectOverview,
17
21
  scanResults?.scanResultsInstances
18
22
  )
19
23
  }
24
+
25
+ if (config.save) {
26
+ if (config.save.toLowerCase() === 'sarif') {
27
+ const scanId = scanResults.scanDetail.id
28
+ const client = commonApi.getHttpClient(config)
29
+ const rawResults = await client.getSpecificScanResultSarif(config, scanId)
30
+ saveResults.writeResultsToFile(rawResults?.body)
31
+ } else {
32
+ console.log(i18n.__('scanNoFiletypeSpecifiedForSave'))
33
+ }
34
+ }
20
35
  }
21
36
 
22
37
  const printHelpMessage = () => {
@@ -6,10 +6,10 @@ const { AUTH_CALLBACK_URL } = require('../constants/constants')
6
6
  function HTTPClient(config) {
7
7
  const apiKey = config.apiKey
8
8
  const authToken = config.authorization
9
- // this.rejectUnauthorized = !additionalParams.ignore_cert_errors
9
+ this.rejectUnauthorized = !config.ignoreCertErrors
10
10
 
11
- const superApiKey = config.super_api_key
12
- const superAuthToken = config.super_authorization
11
+ const superApiKey = config.superApiKey
12
+ const superAuthToken = config.superAuthorization
13
13
 
14
14
  this.requestOptions = {
15
15
  forever: true,
@@ -91,6 +91,15 @@ HTTPClient.prototype.getSpecificScanResult = function getSpecificScanResult(
91
91
  return requestUtils.sendRequest({ method: 'get', options })
92
92
  }
93
93
 
94
+ HTTPClient.prototype.getSpecificScanResultSarif = function getSpecificScanResultSarif(
95
+ config,
96
+ scanId
97
+ ) {
98
+ const options = _.cloneDeep(this.requestOptions)
99
+ options.url = createRawOutputURL(config, scanId)
100
+ return requestUtils.sendRequest({ method: 'get', options })
101
+ }
102
+
94
103
  HTTPClient.prototype.getScanId = function getScanId(config, codeArtifactId) {
95
104
  const options = _.cloneDeep(this.requestOptions)
96
105
  let url = createGetScanIdURL(config)
@@ -119,8 +128,7 @@ HTTPClient.prototype.createProjectId = function createProjectId(config) {
119
128
 
120
129
  options.body = {
121
130
  name: config.name,
122
- archived: 'false',
123
- language: config.language
131
+ archived: 'false'
124
132
  }
125
133
  options.url = createHarmonyProjectsUrl(config)
126
134
  return requestUtils.sendRequest({ method: 'post', options })
@@ -159,6 +167,80 @@ HTTPClient.prototype.pollForAuth = function pollForAuth(token) {
159
167
  return requestUtils.sendRequest({ method: 'post', options })
160
168
  }
161
169
 
170
+ HTTPClient.prototype.catalogueCommand = function catalogueCommand(config) {
171
+ const options = _.cloneDeep(this.requestOptions)
172
+ let url = createAppCreateURL(config)
173
+ options.url = url
174
+
175
+ let requestBody = {}
176
+ requestBody.name = config.applicationName
177
+ requestBody.language = config.language.toUpperCase()
178
+ requestBody.appGroups = config.appGroups
179
+ requestBody.metadata = config.metadata
180
+ requestBody.tags = config.tags
181
+ requestBody.code = config.code
182
+ options.body = requestBody
183
+
184
+ return requestUtils.sendRequest({ method: 'post', options })
185
+ }
186
+
187
+ HTTPClient.prototype.sendSnapshot = function sendSnapshot(requestBody, config) {
188
+ const options = _.cloneDeep(this.requestOptions)
189
+ let url = createSnapshotURL(config)
190
+ options.url = url
191
+ options.body = requestBody
192
+ return requestUtils.sendRequest({ method: 'post', options })
193
+ }
194
+
195
+ HTTPClient.prototype.getReport = function getReport(config) {
196
+ const options = _.cloneDeep(this.requestOptions)
197
+ let url = createReportUrl(config)
198
+ options.url = url
199
+
200
+ return requestUtils.sendRequest({ method: 'get', options })
201
+ }
202
+
203
+ HTTPClient.prototype.getSpecificReport = function getSpecificReport(
204
+ config,
205
+ reportId
206
+ ) {
207
+ const options = _.cloneDeep(this.requestOptions)
208
+ let url = createSpecificReportUrl(config, reportId)
209
+ options.url = url
210
+
211
+ return requestUtils.sendRequest({ method: 'get', options })
212
+ }
213
+
214
+ HTTPClient.prototype.getLibraryVulnerabilities = function getLibraryVulnerabilities(
215
+ requestBody,
216
+ config
217
+ ) {
218
+ const options = _.cloneDeep(this.requestOptions)
219
+ let url = createLibraryVulnerabilitiesUrl(config)
220
+ options.url = url
221
+ options.body = requestBody
222
+
223
+ return requestUtils.sendRequest({ method: 'put', options })
224
+ }
225
+
226
+ HTTPClient.prototype.getAppId = function getAppId(config) {
227
+ const options = _.cloneDeep(this.requestOptions)
228
+ let url = createAppNameUrl(config)
229
+ options.url = url
230
+ return requestUtils.sendRequest({ method: 'get', options })
231
+ }
232
+
233
+ HTTPClient.prototype.getDependencyTree = function getReport(
234
+ orgUuid,
235
+ appId,
236
+ reportId
237
+ ) {
238
+ const options = _.cloneDeep(this.requestOptions)
239
+ let url = createGetDependencyTree(options.uri, orgUuid, appId, reportId)
240
+ options.url = url
241
+ return requestUtils.sendRequest({ method: 'get', options })
242
+ }
243
+
162
244
  // serverless - lambda
163
245
  function getServerlessHost(config = {}) {
164
246
  const originalHost = config?.host || config?.get('host')
@@ -195,10 +277,10 @@ function createScanResultsGetUrl(config, params, scanId, functionArn) {
195
277
 
196
278
  HTTPClient.prototype.postFunctionScan = async function postFunctionScan(
197
279
  config,
198
- parameters,
280
+ params,
199
281
  body
200
282
  ) {
201
- const url = createScanFunctionPostUrl(config, parameters)
283
+ const url = createScanFunctionPostUrl(config, params)
202
284
  const options = { ...this.requestOptions, body, url }
203
285
 
204
286
  return requestUtils.sendRequest({ method: 'post', options })
@@ -206,10 +288,10 @@ HTTPClient.prototype.postFunctionScan = async function postFunctionScan(
206
288
 
207
289
  HTTPClient.prototype.getScanResources = async function getScanResources(
208
290
  config,
209
- parameters,
291
+ params,
210
292
  scanId
211
293
  ) {
212
- const url = createScanResourcesGetUrl(config, parameters, scanId)
294
+ const url = createScanResourcesGetUrl(config, params, scanId)
213
295
  const options = { ...this.requestOptions, url }
214
296
 
215
297
  return requestUtils.sendRequest({ method: 'get', options })
@@ -217,27 +299,35 @@ HTTPClient.prototype.getScanResources = async function getScanResources(
217
299
 
218
300
  HTTPClient.prototype.getFunctionScanResults = async function getFunctionScanResults(
219
301
  config,
220
- parameters,
302
+ params,
221
303
  scanId,
222
304
  functionArn
223
305
  ) {
224
- const url = createScanResultsGetUrl(config, parameters, scanId, functionArn)
306
+ const url = createScanResultsGetUrl(config, params, scanId, functionArn)
225
307
  const options = { ...this.requestOptions, url }
226
308
 
227
309
  return requestUtils.sendRequest({ method: 'get', options })
228
310
  }
229
311
 
312
+ HTTPClient.prototype.checkLibrary = function checkLibrary(data) {
313
+ const options = _.cloneDeep(this.requestOptions)
314
+ let url = createDataUrl()
315
+ options.url = url
316
+ options.body = data
317
+ return requestUtils.sendRequest({ method: 'post', options })
318
+ }
319
+
230
320
  // scan
231
321
  const createGetScanIdURL = config => {
232
322
  return `${config.host}/Contrast/api/sast/v1/organizations/${config.organizationId}/projects/${config.projectId}/scans/`
233
323
  }
234
324
 
235
325
  const createScanResultsInstancesURL = (config, scanId) => {
236
- return `${config.host}/Contrast/api/sast/v1/organizations/${config.organizationId}/projects/${config.projectId}/scans/${scanId}/result-instances?sort=severity,asc`
326
+ return `${config.host}/Contrast/api/sast/v1/organizations/${config.organizationId}/projects/${config.projectId}/scans/${scanId}/result-instances/info?size=50&page=0&last=false&sort=severity,asc`
237
327
  }
238
328
 
239
- const createRawOutputURL = (config, codeArtifactId) => {
240
- return `${config.host}/Contrast/api/sast/v1/organizations/${config.organizationId}/projects/${config.projectId}/scans/${codeArtifactId}/raw-output`
329
+ const createRawOutputURL = (config, scanId) => {
330
+ return `${config.host}/Contrast/api/sast/v1/organizations/${config.organizationId}/projects/${config.projectId}/scans/${scanId}/raw-output`
241
331
  }
242
332
 
243
333
  const createSpecificScanResultURL = (config, scanId) => {
@@ -264,6 +354,38 @@ const pollForAuthUrl = () => {
264
354
  return `${AUTH_CALLBACK_URL}/auth/credentials`
265
355
  }
266
356
 
357
+ function createSnapshotURL(config) {
358
+ return `${config.host}/Contrast/api/ng/sca/organizations/${config.organizationId}/applications/${config.applicationId}/snapshots`
359
+ }
360
+
361
+ const createAppCreateURL = config => {
362
+ return `${config.host}/Contrast/api/ng/sca/organizations/${config.organizationId}/applications/create`
363
+ }
364
+
365
+ const createAppNameUrl = config => {
366
+ return `${config.host}/Contrast/api/ng/${config.organizationId}/applications/name?filterText=${config.applicationName}`
367
+ }
368
+
369
+ function createLibraryVulnerabilitiesUrl(config) {
370
+ return `${config.host}/Contrast/api/ng/${config.organizationId}/libraries/artifactsByGroupNameVersion`
371
+ }
372
+
373
+ function createReportUrl(config) {
374
+ return `${config.host}/Contrast/api/ng/sca/organizations/${config.organizationId}/applications/${config.applicationId}/reports`
375
+ }
376
+
377
+ function createSpecificReportUrl(config, reportId) {
378
+ return `${config.host}/Contrast/api/ng/sca/organizations/${config.organizationId}/applications/${config.applicationId}/reports/${reportId}?nodesToInclude=PROD`
379
+ }
380
+
381
+ function createDataUrl() {
382
+ return `https://ardy.contrastsecurity.com/production`
383
+ }
384
+
385
+ const createGetDependencyTree = (protocol, orgUuid, appId, reportId) => {
386
+ return `${protocol}/Contrast/api/ng/sca/organizations/${orgUuid}/applications/${appId}/reports/${reportId}`
387
+ }
388
+
267
389
  module.exports = HTTPClient
268
390
  module.exports.pollForAuthUrl = pollForAuthUrl
269
391
  module.exports.getServerlessHost = getServerlessHost
@@ -1,5 +1,58 @@
1
1
  import i18n from 'i18n'
2
2
 
3
+ const handleResponseErrors = (res: any, api: string) => {
4
+ if (res.statusCode === 400) {
5
+ api === 'catalogue' ? badRequestError(true) : badRequestError(false)
6
+ } else if (res.statusCode === 401) {
7
+ unauthenticatedError()
8
+ } else if (res.statusCode === 403) {
9
+ forbiddenError()
10
+ } else if (res.statusCode === 407) {
11
+ proxyError()
12
+ } else {
13
+ if (api === 'snapshot' || api === 'catalogue') {
14
+ snapshotFailureError()
15
+ }
16
+ if (api === 'vulnerabilities') {
17
+ vulnerabilitiesFailureError()
18
+ }
19
+ if (api === 'report') {
20
+ reportFailureError()
21
+ }
22
+ }
23
+ }
24
+
25
+ const libraryAnalysisError = () => {
26
+ console.log(i18n.__('libraryAnalysisError'))
27
+ }
28
+
29
+ const snapshotFailureError = () => {
30
+ console.log(
31
+ '\n ******************************** ' +
32
+ i18n.__('snapshotFailureHeader') +
33
+ ' *********************************\n' +
34
+ i18n.__('snapshotFailureMessage')
35
+ )
36
+ }
37
+
38
+ const vulnerabilitiesFailureError = () => {
39
+ console.log(
40
+ '\n ******************************** ' +
41
+ i18n.__('snapshotFailureHeader') +
42
+ ' *********************************\n' +
43
+ i18n.__('vulnerabilitiesFailureMessage')
44
+ )
45
+ }
46
+
47
+ const reportFailureError = () => {
48
+ console.log(
49
+ '\n ******************************** ' +
50
+ i18n.__('snapshotFailureHeader') +
51
+ ' *********************************\n' +
52
+ i18n.__('reportFailureMessage')
53
+ )
54
+ }
55
+
3
56
  const genericError = (missingCliOption: string) => {
4
57
  // prettier-ignore
5
58
  console.log(`*************************** ${i18n.__('yamlMissingParametersHeader')} ***************************\n${missingCliOption}`)
@@ -75,5 +128,7 @@ export {
75
128
  failOptionError,
76
129
  hostWarningError,
77
130
  generalError,
78
- getErrorMessage
131
+ getErrorMessage,
132
+ handleResponseErrors,
133
+ libraryAnalysisError
79
134
  }
@@ -0,0 +1,27 @@
1
+ import latestVersion from 'latest-version'
2
+ import { APP_VERSION } from '../constants/constants'
3
+ import boxen from 'boxen'
4
+ import chalk from 'chalk'
5
+ import semver from 'semver'
6
+
7
+ export default async function findLatestCLIVersion() {
8
+ const latestCLIVersion = await latestVersion('@contrast/contrast')
9
+
10
+ if (semver.lt(APP_VERSION, latestCLIVersion)) {
11
+ const updateAvailableMessage = `Update available ${chalk.yellow(
12
+ APP_VERSION
13
+ )} → ${chalk.green(latestCLIVersion)}`
14
+
15
+ const updateAvailableCommand = `Run ${chalk.cyan(
16
+ 'npm i @contrast/contrast'
17
+ )} to update`
18
+
19
+ console.log(
20
+ boxen(`${updateAvailableMessage}\n${updateAvailableCommand}`, {
21
+ margin: 1,
22
+ padding: 1,
23
+ align: 'center'
24
+ })
25
+ )
26
+ }
27
+ }
@@ -15,7 +15,7 @@ const HIGH = 'HIGH'
15
15
  const CRITICAL = 'CRITICAL'
16
16
 
17
17
  const APP_NAME = 'contrast'
18
- const APP_VERSION = '1.0.0'
18
+ const APP_VERSION = '1.0.1'
19
19
  const TIMEOUT = 120000
20
20
  const AUTH_UI_URL = 'https://cli-auth.contrastsecurity.com'
21
21
  const AUTH_CALLBACK_URL = 'https://cli-auth-api.contrastsecurity.com'
@@ -9,11 +9,52 @@ const lambda = {
9
9
  'Required parameter --function-name is missing.\nRun command with --help to see usage',
10
10
  failedToGetResults: 'Failed to get results',
11
11
  missingResults: 'Missing vulnerabilities',
12
- missingParameter: 'Required function parameter is missing', // should use it again
13
12
  awsError: 'AWS error',
14
- missingFlagArguments: 'The following flags are missing an arguments:\n%s',
13
+ missingFlagArguments:
14
+ 'The following flags are missing an arguments:\n{{flags}}',
15
15
  notSupportedFlags:
16
- 'The following flags are not supported:\n%s\nRun command with --help to see usage',
16
+ 'The following flags are not supported:\n{{flags}}\nRun command with --help to see usage',
17
+ layerNotFound:
18
+ 'The layer {{layerArn}} could not be found. The scan will continue without it',
19
+
20
+ // ====== general ===== //
21
+ noVulnerabilitiesFound: '👏 No vulnerabilities found',
22
+ scanCompleted: '----- Scan completed {{time}}s -----',
23
+ sendingScanRequest:
24
+ '{{icon}} Sending Lambda Function scan request to Contrast',
25
+ scanRequestedSuccessfully: '{{icon}} Scan requested successfully',
26
+ fetchingConfiguration:
27
+ '{{icon}} Fetching configuration and policies for Lambda Function {{functionName}}',
28
+ fetchedConfiguration: '{{icon}} Fetched configuration from AWS',
29
+
30
+ // ====== scan polling ===== //
31
+ scanStarted: 'Scan Started',
32
+ scanFailed: 'Scan Failed',
33
+ scanTimedOut: 'Scan timed out',
34
+
35
+ // ====== lambda utils ===== //
36
+ loadingFunctionList: 'Loading lambda function list',
37
+ functionsFound: '{{count}} functions found',
38
+ noFunctionsFound: 'No functions found',
39
+ failedToLoadFunctions: 'Faled to load lambda functions',
40
+ availableForScan: '{{icon}} {{count}} available for scan',
41
+ runtimeCount: '----- {{runtime}} ({{count}}) -----',
42
+
43
+ // ====== print vulnerabilities ===== //
44
+ whatHappenedTitle: 'What happened:',
45
+ whatHappenedItem: '{{policy}} have:\n{{comments}}\n',
46
+ recommendation: 'Recommendation:',
47
+ vulnerableDependency: 'Vulnerable dependency',
48
+ dependenciesCount: {
49
+ one: '1 Dependency',
50
+ other: '%s Dependencies'
51
+ },
52
+ foundVulnerabilities: {
53
+ one: 'Found 1 vulnerability',
54
+ other: 'Found %s vulnerabilities'
55
+ },
56
+ vulnerableDependencyDescriptions:
57
+ '{packageName} (v{version}) has {NUM} known {NUM, plural,one{CVE}other{CVEs}}\n {cves}',
17
58
 
18
59
  // ====== errorCodes ===== //
19
60
  something_went_wrong: 'Something went wrong',
@@ -22,7 +63,7 @@ const lambda = {
22
63
  inactive_account:
23
64
  'Scanning a function of an inactive account is not supported',
24
65
  not_supported_runtime:
25
- 'Scanning resource of runtime "%s" is not supported.\nSupported runtimes: %s',
66
+ 'Scanning resource of runtime "{{runtime}}" is not supported.\nSupported runtimes: {{supportedRuntimes}}',
26
67
  not_supported_onboard_account:
27
68
  'Scanning a function of onboard account is not supported',
28
69
  scan_lock:
@@ -159,12 +159,10 @@ const en_locales = () => {
159
159
  'Specify the sub project within your gradle application.',
160
160
  constantsScan: 'Upload java binaries to the static scan service',
161
161
  constantsWaitForScan: 'Waits for the result of the scan',
162
- constantsProjectName: 'The name of the scan project in Contrast',
163
- constantsFileName: 'The name of the file to Scan',
162
+ constantsProjectName:
163
+ 'Contrast project name. If not specified, Contrast uses contrast.settings to identify the project or creates a project.',
164
164
  constantsProjectId:
165
165
  'The ID associated with a scan project. Replace <ProjectID> with the ID for the scan project. To find the ID, select a scan project in Contrast and locate the last number in the URL.',
166
- constantsScanTimeout:
167
- 'Set a specific time span before the function times out. Default timeout is 300 seconds if scan_timeout is not set. The format of the value of the parameter is "20" seconds or "80" seconds.',
168
166
  constantsReport: 'Display vulnerability information for this application',
169
167
  constantsFail:
170
168
  'Set the process to fail if this option is set in combination with the --report and --cve_severity.',
@@ -182,18 +180,19 @@ const en_locales = () => {
182
180
  constantsPrerequisitesHeader: 'Pre-requisites',
183
181
  constantsPrerequisitesContent:
184
182
  'To scan a Java project you will need a .jar or .war file for analysis\n' +
185
- 'To scan a Javascript project you will need a .js or.zip file for analysis\n',
183
+ 'To scan a Javascript project you will need a .js or.zip file for analysis\n' +
184
+ 'To scan a .NET c# webforms project you will need a .exe or a .zip file for analysis\n',
186
185
  constantsUsage: 'Usage',
187
186
  constantsUsageCommandExample: 'contrast [command] [options]',
188
187
  constantsUsageCommandInfo:
189
- 'The file argument is optional. If no file is given, Contrast will search for a .jar, .war, .js or .zip file in the working directory.\n',
188
+ 'The file argument is optional. If no file is given, Contrast will search for a .jar, .war, .js, .exe or .zip file in the working directory.\n',
190
189
  constantsUsageCommandInfo24Hours:
191
190
  'Submitted files are encrypted during upload and deleted in 24 hours.',
192
191
  constantsAnd: 'AND',
193
192
  constantsJava:
194
193
  'AND Maven build platform, including the dependency plugin. For a Gradle project, use build.gradle. A gradle-wrapper.properties file is also required. Kotlin is also supported requiring a build.gradle.kts file.',
195
194
  constantsJavaNote:
196
- '*Please Note: Running "mvn dependency:tree" or "./gradlew dependencies" in the project directory locally must be successful.',
195
+ 'Note: Running "mvn dependency:tree" or "./gradlew dependencies" in the project directory locally must be successful.',
197
196
  constantsJavaNoteGradle:
198
197
  'We currently support v4.8 and upwards on Gradle projects',
199
198
  constantsDotNet:
@@ -268,6 +267,7 @@ const en_locales = () => {
268
267
  'Add the application code this application should use in the Contrast UI',
269
268
  constantsIgnoreCertErrors:
270
269
  ' For EOP users with a local Teamserver install, this will bypass the SSL certificate and recognise a self signed certificate.',
270
+ constantsSave: ' Saves the Scan Results JSON to file.',
271
271
  constantsIgnoreDev:
272
272
  'Combined with the --report command excludes developer dependencies from the vulnerabilities report. By default all dependencies are included in a report.',
273
273
  constantsCommands: 'Commands',
@@ -288,6 +288,8 @@ const en_locales = () => {
288
288
  specifyFileScanError:
289
289
  'Java Scan requires a .war or .jar file. Javascript Scan requires a .js or .zip file.\nTo start a Scan enter "contrast scan -f <path-to-file>"',
290
290
  populateProjectIdMessage: 'project ID is %s',
291
+ permissionsError:
292
+ 'You do not have the correct permissions here. \n Contact support@contrastsecurity.com to get this fixed.',
291
293
  scanErrorFileMessage:
292
294
  'We only accept the following file types: \nJava - .jar, .war \nJavaScript - .js or .zip files',
293
295
  helpAuthSummary:
@@ -304,31 +306,23 @@ const en_locales = () => {
304
306
  versionName: 'version',
305
307
  configName: 'config',
306
308
  helpName: 'help',
307
- scanOptionsFileName: '-f, --file',
308
- scanOptionsLanguage: '-l, --language',
309
- scanOptionsName: '-n, --name',
310
- scanOptionsTimeout: '-t, --time-out',
311
- scanOptionsVerbose: '-v, --verbose',
312
- scanOptionsFileNameSummary:
313
- 'Path of the file you want to scan. If no file is specified, Contrast searches for a .jar, .war, .js. or .zip file in the working directory.',
314
309
  scanOptionsLanguageSummaryOptional:
315
310
  'Language of file to send for analysis. ',
316
311
  scanOptionsLanguageSummaryRequired:
317
312
  'If you scan a .zip file or you use the --file option.',
318
- scanOptionsNameSummary:
319
- 'Contrast project name. If not specified, Contrast uses contrast.settings to identify the project or creates a project.',
320
313
  scanOptionsTimeoutSummary:
321
314
  'Time in seconds to wait for scan to complete. Default value is 300 seconds.',
322
- scanOptionsVerboseSummary: 'Returns extended information to the terminal.',
315
+ scanOptionsFileNameSummary:
316
+ 'Path of the file you want to scan. If no file is specified, Contrast searches for a .jar, .war, .js, .exe or .zip file in the working directory.',
317
+ scanOptionsVerboseSummary: ' Returns extended information to the terminal.',
323
318
  authSuccessMessage: 'Authentication successful',
324
- runScanMessage: 'Now run Contrast Scan',
319
+ runAuthSuccessMessage: 'Now you can use Contrast CLI',
325
320
  authWaitingMessage: 'Waiting for auth...',
326
321
  authTimedOutMessage: 'Auth Timed out, try again',
327
322
  zipErrorScan:
328
323
  'We only support zip files for JAVASCRIPT language, please set the flag --language JAVASCRIPT',
329
324
  unknownFileErrorScan: 'Unsupported file selected for Scan.',
330
325
  foundScanFile: 'found: %s',
331
- foundVulnerabilities: 'Found %s vulnerabilities',
332
326
  foundDetailedVulnerabilities:
333
327
  '%s Critical %s High %s Medium %s Low %s Note',
334
328
  requiredParams: 'All required parameters are not present.',
@@ -342,6 +336,7 @@ const en_locales = () => {
342
336
  lambdaPrerequisitesContent: 'contrast cli',
343
337
  scanFileNameOption: ' -f, --file',
344
338
  lambdaFunctionNameOption: ' -f, --function-name',
339
+ lambdaListFunctionsOption: ' -l, --list-functions',
345
340
  lambdaEndpointOption: '-e, --endpoint-url',
346
341
  lambdaRegionOption: '-r, --region',
347
342
  lambdaProfileOption: '-p, --profile',
@@ -349,6 +344,7 @@ const en_locales = () => {
349
344
  lambdaVerboseOption: '-v, --verbose',
350
345
  lambdaHelpOption: '-h, --help',
351
346
  lambdaFunctionNameSummery: 'Name of AWS lambda function to scan.',
347
+ lambdaListFunctionsSummery: 'List all available lambda functions to scan.',
352
348
  lambdaEndpointSummery: 'AWS Endpoint override, works like in AWS CLI.',
353
349
  lambdaRegionSummery:
354
350
  'Region override, default to AWS_DEAFAULT_REGION env var, works like in AWS CLI.',
@@ -371,7 +367,39 @@ const en_locales = () => {
371
367
  'An error has occurred when trying to get the Project Id please check your internet connection or provide the Project Id manually',
372
368
  internalServerErrorHeader: '500 error - Internal server error',
373
369
  resourceLockedErrorHeader: '423 error - Resource is locked',
374
-
370
+ auditHeader: 'Contrast Audit',
371
+ auditHeaderMessage: `
372
+ Performs software composition analysis (SCA) on your application/code time to show you the dependencies between open source libraries, including where vulnerabilities were introduced.\n
373
+ 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.`,
374
+ constantsAuditPrerequisitesContentSupportedLanguages:
375
+ 'Supported languages and their requirements are:',
376
+ constantsAuditPrerequisitesContentJava: 'Java: ',
377
+ constantsAuditPrerequisitesContentMessage: `
378
+ pom.xml AND Maven build platform, including the dependency plugin.
379
+ For a Gradle project (v4.8+) use build.gradle. A gradle-wrapper.properties file is also required.
380
+ Kotlin is also supported requiring a build.gradle.kts file.`,
381
+ constantsAuditPrerequisitesContentDotNet: '.NET framework and .NET core: ',
382
+ constantsAuditPrerequisitesContentDotNetMessage: `
383
+ MSBuild 15.0 or greater and have a packages.lock.json file are supported.\n
384
+ Note: If the packages.lock.json file is unavailable it can be generated by setting RestorePackagesWithLockFile to true within each *.csproj file and running dotnet build.\n`,
385
+ constantsAuditPrerequisitesContentLanguageNode: 'Node: ',
386
+ constantsAuditPrerequisitesContentLanguageRuby: 'Ruby: ',
387
+ constantsAuditPrerequisitesContentLanguagePython: 'Python: ',
388
+ constantsAuditPrerequisitesContentLanguageNodeMessage:
389
+ '*.package.json AND a lock file either *.package-lock.json or *.yarn.lock',
390
+ constantsAuditPrerequisitesContentLanguageRubyMessage:
391
+ 'gemfile AND gemfile.lock',
392
+ constantsAuditPrerequisitesContentLanguagePythonMessage:
393
+ 'pipfile AND pipfile.lock',
394
+ constantsAuditOptions: 'Audit Options',
395
+ auditOptionsIgnoreDevDependencies: '-igd, --ignore-dev',
396
+ auditOptionsIgnoreDevDependenciesDescription: 'ignores DevDependencies',
397
+ auditOptionsSave: '-s, --save',
398
+ auditOptionsSaveDescription:
399
+ 'saves the output in specified format Txt text, sbom',
400
+ scanNoVulnerabilitiesFound: '👏 No vulnerabilities found',
401
+ scanNoFiletypeSpecifiedForSave:
402
+ 'Please specify file type to save results to',
375
403
  ...lambda
376
404
  }
377
405
  }