@contrast/contrast 1.0.10 → 1.0.11

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 (78) hide show
  1. package/README.md +1 -1
  2. package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +39 -28
  3. package/dist/audit/languageAnalysisEngine/report/models/reportGuidanceModel.js +6 -0
  4. package/dist/audit/languageAnalysisEngine/report/models/reportOutputModel.js +1 -2
  5. package/dist/audit/languageAnalysisEngine/report/models/severityCountModel.js +1 -0
  6. package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +11 -7
  7. package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +1 -2
  8. package/dist/commands/audit/auditConfig.js +3 -3
  9. package/dist/commands/audit/processAudit.js +4 -2
  10. package/dist/commands/auth/auth.js +1 -1
  11. package/dist/commands/config/config.js +2 -2
  12. package/dist/commands/scan/processScan.js +11 -4
  13. package/dist/commands/scan/sca/scaAnalysis.js +10 -3
  14. package/dist/common/HTTPClient.js +9 -0
  15. package/dist/common/fail.js +66 -0
  16. package/dist/common/versionChecker.js +1 -1
  17. package/dist/constants/constants.js +1 -1
  18. package/dist/constants/locales.js +6 -3
  19. package/dist/constants.js +39 -1
  20. package/dist/index.js +5 -2
  21. package/dist/scaAnalysis/common/scaParserForGoAndJava.js +32 -0
  22. package/dist/scaAnalysis/common/treeUpload.js +20 -5
  23. package/dist/scaAnalysis/dotnet/analysis.js +15 -3
  24. package/dist/scaAnalysis/go/goAnalysis.js +8 -2
  25. package/dist/scaAnalysis/java/analysis.js +10 -6
  26. package/dist/scaAnalysis/java/index.js +7 -1
  27. package/dist/scaAnalysis/java/javaBuildDepsParser.js +19 -3
  28. package/dist/scaAnalysis/python/analysis.js +43 -5
  29. package/dist/scaAnalysis/python/index.js +7 -2
  30. package/dist/scaAnalysis/ruby/analysis.js +14 -4
  31. package/dist/scan/formatScanOutput.js +6 -5
  32. package/dist/scan/populateProjectIdAndProjectName.js +5 -0
  33. package/dist/scan/scan.js +4 -0
  34. package/dist/scan/scanConfig.js +3 -3
  35. package/dist/scan/scanResults.js +39 -3
  36. package/dist/telemetry/telemetry.js +137 -0
  37. package/dist/utils/getConfig.js +2 -2
  38. package/dist/utils/parsedCLIOptions.js +3 -1
  39. package/dist/utils/requestUtils.js +7 -1
  40. package/package.json +1 -1
  41. package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +57 -39
  42. package/src/audit/languageAnalysisEngine/report/models/reportGuidanceModel.ts +5 -0
  43. package/src/audit/languageAnalysisEngine/report/models/reportOutputModel.ts +1 -7
  44. package/src/audit/languageAnalysisEngine/report/models/severityCountModel.ts +2 -0
  45. package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +15 -8
  46. package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +2 -2
  47. package/src/commands/audit/auditConfig.ts +10 -3
  48. package/src/commands/audit/processAudit.ts +16 -2
  49. package/src/commands/auth/auth.js +3 -1
  50. package/src/commands/config/config.js +4 -2
  51. package/src/commands/scan/processScan.js +18 -4
  52. package/src/commands/scan/sca/scaAnalysis.js +11 -3
  53. package/src/common/HTTPClient.js +14 -0
  54. package/src/common/fail.js +75 -0
  55. package/src/common/versionChecker.ts +1 -1
  56. package/src/constants/constants.js +1 -1
  57. package/src/constants/locales.js +8 -4
  58. package/src/constants.js +43 -1
  59. package/src/index.ts +17 -2
  60. package/src/scaAnalysis/common/scaParserForGoAndJava.js +41 -0
  61. package/src/scaAnalysis/common/treeUpload.js +21 -6
  62. package/src/scaAnalysis/dotnet/analysis.js +21 -3
  63. package/src/scaAnalysis/go/goAnalysis.js +9 -2
  64. package/src/scaAnalysis/java/analysis.js +11 -6
  65. package/src/scaAnalysis/java/index.js +9 -1
  66. package/src/scaAnalysis/java/javaBuildDepsParser.js +25 -6
  67. package/src/scaAnalysis/python/analysis.js +49 -5
  68. package/src/scaAnalysis/python/index.js +7 -2
  69. package/src/scaAnalysis/ruby/analysis.js +16 -4
  70. package/src/scan/formatScanOutput.ts +7 -5
  71. package/src/scan/populateProjectIdAndProjectName.js +5 -1
  72. package/src/scan/scan.ts +4 -0
  73. package/src/scan/scanConfig.js +5 -3
  74. package/src/scan/scanResults.js +46 -3
  75. package/src/telemetry/telemetry.ts +154 -0
  76. package/src/utils/getConfig.ts +4 -6
  77. package/src/utils/parsedCLIOptions.js +14 -1
  78. package/src/utils/requestUtils.js +8 -1
@@ -4,11 +4,15 @@ const oraFunctions = require('../utils/oraWrapper')
4
4
  const _ = require('lodash')
5
5
  const i18n = require('i18n')
6
6
  const oraWrapper = require('../utils/oraWrapper')
7
+ const readLine = require('readline')
7
8
 
8
9
  const getScanId = async (config, codeArtifactId, client) => {
9
10
  return client
10
11
  .getScanId(config, codeArtifactId)
11
12
  .then(res => {
13
+ if (res.statusCode == 429) {
14
+ throw new Error(i18n.__('exceededFreeTier'))
15
+ }
12
16
  return res.body.id
13
17
  })
14
18
  .catch(err => {
@@ -88,13 +92,51 @@ const returnScanResults = async (
88
92
  startScanSpinner,
89
93
  'Contrast Scan timed out at the specified ' + timeout + ' seconds.'
90
94
  )
91
- console.log('Please try again, allowing more time.')
92
- process.exit(1)
95
+
96
+ if (!config.isCI) {
97
+ const retry = await retryScanPrompt()
98
+ timeout = retry.timeout
99
+ }
93
100
  }
94
101
  }
95
102
  }
96
103
  }
97
104
 
105
+ const retryScanPrompt = async () => {
106
+ const rl = readLine.createInterface({
107
+ input: process.stdin,
108
+ output: process.stdout
109
+ })
110
+
111
+ return new Promise((resolve, reject) => {
112
+ requestUtils.timeOutError(30000, reject)
113
+
114
+ rl.question(
115
+ '🔁 Do you want to continue waiting on Scan? [Y/N]\n',
116
+ async input => {
117
+ if (input.toLowerCase() === 'yes' || input.toLowerCase() === 'y') {
118
+ console.log('Continuing wait for Scan')
119
+ rl.close()
120
+ resolve({ timeout: 300 })
121
+ } else if (
122
+ input.toLowerCase() === 'no' ||
123
+ input.toLowerCase() === 'n'
124
+ ) {
125
+ rl.close()
126
+ console.log('Contrast Scan Retry Cancelled: Exiting')
127
+ resolve(process.exit(1))
128
+ } else {
129
+ rl.close()
130
+ console.log('Invalid Input: Exiting')
131
+ resolve(process.exit(1))
132
+ }
133
+ }
134
+ )
135
+ }).catch(e => {
136
+ throw e
137
+ })
138
+ }
139
+
98
140
  const returnScanResultsInstances = async (config, scanId) => {
99
141
  const client = commonApi.getHttpClient(config)
100
142
  let result
@@ -118,5 +160,6 @@ module.exports = {
118
160
  getScanId: getScanId,
119
161
  returnScanResults: returnScanResults,
120
162
  pollScanResults: pollScanResults,
121
- returnScanResultsInstances: returnScanResultsInstances
163
+ returnScanResultsInstances: returnScanResultsInstances,
164
+ retryScanPrompt
122
165
  }
@@ -0,0 +1,154 @@
1
+ import { getHttpClient } from '../utils/commonApi'
2
+ import * as crypto from 'crypto'
3
+ import { ContrastConf } from '../utils/getConfig'
4
+
5
+ export const TELEMETRY_CLI_COMMANDS_EVENT = 'CLI_COMMANDS'
6
+ export const TELEMETRY_CLI_TIME_TO_AUTH_EVENT = 'CLI_TIME_TO_AUTH'
7
+
8
+ export const sendTelemetryConfigAsConfObj = async (
9
+ config: ContrastConf,
10
+ command: string,
11
+ argv: string[],
12
+ result: string,
13
+ language: string
14
+ ) => {
15
+ const hostParam = '--host'
16
+ const hostParamAlias = '-h'
17
+ const orgIdParam = '--organization-id'
18
+ const orgIdParamAlias = '-o'
19
+ const authParam = '--authorization'
20
+ const apiKeyParam = '--api-key'
21
+
22
+ let configToUse
23
+
24
+ if (
25
+ paramExists(argv, hostParam, hostParamAlias) &&
26
+ paramExists(argv, orgIdParam, orgIdParamAlias) &&
27
+ paramExists(argv, authParam, null) &&
28
+ paramExists(argv, apiKeyParam, null)
29
+ ) {
30
+ //if the user has passed the values as params
31
+ configToUse = {
32
+ host: findParamValueFromArgs(argv, hostParam, hostParamAlias),
33
+ organizationId: findParamValueFromArgs(argv, orgIdParam, orgIdParamAlias),
34
+ authorization: findParamValueFromArgs(argv, authParam, null),
35
+ apiKey: findParamValueFromArgs(argv, apiKeyParam, null)
36
+ }
37
+ } else if (
38
+ config &&
39
+ config.get('host') &&
40
+ config.get('organizationId') &&
41
+ config.get('authorization') &&
42
+ config.get('apiKey')
43
+ ) {
44
+ configToUse = {
45
+ host: config.get('host')?.slice(0, -1), //slice off extra / in url, will 404 on teamserver if we don't
46
+ organizationId: config.get('organizationId'),
47
+ authorization: config.get('authorization'),
48
+ apiKey: config.get('apiKey')
49
+ }
50
+ } else {
51
+ //return when unable to get config
52
+ return
53
+ }
54
+
55
+ return await sendTelemetryConfigAsObject(
56
+ configToUse,
57
+ command,
58
+ argv,
59
+ result,
60
+ language
61
+ )
62
+ }
63
+
64
+ export const sendTelemetryConfigAsObject = async (
65
+ config: any,
66
+ command: string,
67
+ argv: string[],
68
+ result: string,
69
+ language: string
70
+ ) => {
71
+ const obfuscatedParams = obfuscateParams(argv)
72
+
73
+ const requestBody = {
74
+ event: TELEMETRY_CLI_COMMANDS_EVENT,
75
+ details: {
76
+ ip_address: '',
77
+ account_name: '',
78
+ account_host: '',
79
+ company_domain: '',
80
+ command: `contrast ${command} ${obfuscatedParams}`,
81
+ app_id:
82
+ config && config.applicationId
83
+ ? sha1Base64Value(config.applicationId)
84
+ : 'undefined',
85
+ project_id:
86
+ config && config.projectId
87
+ ? sha1Base64Value(config.projectId)
88
+ : 'undefined',
89
+ language: language,
90
+ result: result,
91
+ additional_info: '',
92
+ timestamp: new Date().toUTCString()
93
+ }
94
+ }
95
+
96
+ return await sendTelemetryRequest(config, requestBody)
97
+ }
98
+
99
+ export const sendTelemetryRequest = async (config: any, requestBody: any) => {
100
+ const client = getHttpClient(config)
101
+ return client
102
+ .postTelemetry(config, requestBody)
103
+ .then((res: any) => {
104
+ if (res.statusCode !== 200 && config.debug === true) {
105
+ console.log('Telemetry failed to send with status', res.statusCode)
106
+ }
107
+ return { statusCode: res.statusCode, statusMessage: res.statusMessage }
108
+ })
109
+ .catch((err: any) => {
110
+ return
111
+ })
112
+ }
113
+
114
+ export const obfuscateParams = (argv: string[]) => {
115
+ return argv
116
+ .join(' ')
117
+ .replace(/--(authorization [A-Z0-9]+)/gi, '--authorization *****')
118
+ .replace(/-(o [A-Z0-9-]+)/gi, '-o *****')
119
+ .replace(/--(organization-id [A-Z0-9-]+)/gi, '--organization-id *****')
120
+ .replace(/--(api-key [A-Z0-9]+)/gi, '--api-key *****')
121
+ }
122
+
123
+ export const paramExists = (
124
+ argv: string[],
125
+ param: string,
126
+ paramAlias: string | null
127
+ ) => {
128
+ return argv.find((arg: string) => arg === param || arg === paramAlias)
129
+ }
130
+
131
+ export const findParamValueFromArgs = (
132
+ argv: string[],
133
+ param: string,
134
+ paramAlias: string | null
135
+ ) => {
136
+ let paramAsValue
137
+
138
+ argv.forEach((arg: string, index: number) => {
139
+ if (
140
+ arg === param ||
141
+ (arg === paramAlias &&
142
+ argv[index + 1] !== undefined &&
143
+ argv[index + 1] !== null)
144
+ ) {
145
+ paramAsValue = argv[index + 1]
146
+ }
147
+ })
148
+
149
+ return paramAsValue
150
+ }
151
+
152
+ export const sha1Base64Value = (value: any) => {
153
+ return crypto.createHash('sha1').update(value).digest('base64')
154
+ }
@@ -7,7 +7,7 @@ type ContrastConfOptions = Partial<{
7
7
  orgId: string
8
8
  authHeader: string
9
9
  numOfRuns: number
10
- updateMessageHidden: boolean
10
+ isCI: boolean
11
11
  }>
12
12
 
13
13
  type ContrastConf = Conf<ContrastConfOptions>
@@ -18,12 +18,10 @@ const localConfig = (name: string, version: string) => {
18
18
  })
19
19
  config.set('version', version)
20
20
 
21
- if (process.env.CONTRAST_CODSEC_DISABLE_UPDATE_MESSAGE) {
21
+ if (process.env.CONTRAST_CODSEC_CI) {
22
22
  config.set(
23
- 'updateMessageHidden',
24
- JSON.parse(
25
- process.env.CONTRAST_CODSEC_DISABLE_UPDATE_MESSAGE.toLowerCase()
26
- )
23
+ 'isCI',
24
+ JSON.parse(process.env.CONTRAST_CODSEC_CI.toLowerCase()) as boolean
27
25
  )
28
26
  }
29
27
 
@@ -1,6 +1,12 @@
1
1
  const commandLineArgs = require('command-line-args')
2
+ const { sendTelemetryConfigAsConfObj } = require('../telemetry/telemetry')
2
3
 
3
- const getCommandLineArgsCustom = (parameterList, optionDefinitions) => {
4
+ const getCommandLineArgsCustom = async (
5
+ contrastConf,
6
+ command,
7
+ parameterList,
8
+ optionDefinitions
9
+ ) => {
4
10
  try {
5
11
  return commandLineArgs(optionDefinitions, {
6
12
  argv: parameterList,
@@ -9,6 +15,13 @@ const getCommandLineArgsCustom = (parameterList, optionDefinitions) => {
9
15
  caseInsensitive: true
10
16
  })
11
17
  } catch (e) {
18
+ await sendTelemetryConfigAsConfObj(
19
+ contrastConf,
20
+ command,
21
+ parameterList,
22
+ 'FAILURE',
23
+ 'undefined'
24
+ )
12
25
  console.log(e.message.toString())
13
26
  process.exit(1)
14
27
  }
@@ -15,8 +15,15 @@ const sleep = ms => {
15
15
  return new Promise(resolve => setTimeout(resolve, ms))
16
16
  }
17
17
 
18
+ const timeOutError = (ms, reject) => {
19
+ return setTimeout(() => {
20
+ reject(new Error(`No input detected after 30s`))
21
+ }, ms)
22
+ }
23
+
18
24
  module.exports = {
19
25
  sendRequest: sendRequest,
20
26
  sleep: sleep,
21
- millisToSeconds: millisToSeconds
27
+ millisToSeconds: millisToSeconds,
28
+ timeOutError: timeOutError
22
29
  }