@contrast/contrast 2.0.1 → 2.0.2-beta.0

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 (49) hide show
  1. package/dist/audit/report/reportingFeature.js +7 -0
  2. package/dist/cliConstants.js +9 -8
  3. package/dist/commands/audit/processAudit.js +0 -2
  4. package/dist/commands/github/fingerprintConfig.js +2 -1
  5. package/dist/commands/github/processFingerprint.js +17 -7
  6. package/dist/commands/github/projectGroup.js +110 -30
  7. package/dist/commands/github/repoServices.js +42 -4
  8. package/dist/common/HTTPClient.js +37 -16
  9. package/dist/common/baseRequest.js +74 -0
  10. package/dist/constants/constants.js +1 -1
  11. package/dist/scaAnalysis/common/auditReport.js +8 -1
  12. package/dist/scaAnalysis/common/scaServicesUpload.js +3 -1
  13. package/dist/scaAnalysis/go/goReadDepFile.js +5 -1
  14. package/dist/scaAnalysis/java/analysis.js +1 -1
  15. package/dist/scaAnalysis/java/javaBuildDepsParser.js +11 -1
  16. package/dist/scaAnalysis/legacy/legacyFlow.js +0 -6
  17. package/dist/scaAnalysis/processServicesFlow.js +38 -17
  18. package/dist/scaAnalysis/repoMode/mavenParser.js +19 -1
  19. package/dist/scaAnalysis/scaAnalysis.js +4 -8
  20. package/dist/scan/autoDetection.js +12 -5
  21. package/dist/scan/fileUtils.js +33 -19
  22. package/dist/utils/paramsUtil/paramHandler.js +11 -2
  23. package/dist/utils/validationCheck.js +5 -1
  24. package/package.json +6 -3
  25. package/src/audit/report/reportingFeature.ts +7 -0
  26. package/src/cliConstants.js +9 -8
  27. package/src/commands/audit/processAudit.js +0 -2
  28. package/src/commands/github/fingerprintConfig.js +2 -2
  29. package/src/commands/github/processFingerprint.js +21 -11
  30. package/src/commands/github/projectGroup.js +131 -35
  31. package/src/commands/github/repoServices.js +46 -4
  32. package/src/common/HTTPClient.js +46 -17
  33. package/src/common/baseRequest.ts +83 -0
  34. package/src/constants/constants.js +1 -1
  35. package/src/scaAnalysis/common/auditReport.js +8 -1
  36. package/src/scaAnalysis/common/scaServicesUpload.js +5 -1
  37. package/src/scaAnalysis/go/goReadDepFile.js +5 -1
  38. package/src/scaAnalysis/java/analysis.js +1 -1
  39. package/src/scaAnalysis/java/javaBuildDepsParser.js +17 -1
  40. package/src/scaAnalysis/legacy/legacyFlow.js +0 -5
  41. package/src/scaAnalysis/processServicesFlow.js +82 -24
  42. package/src/scaAnalysis/repoMode/mavenParser.js +24 -1
  43. package/src/scaAnalysis/scaAnalysis.js +9 -8
  44. package/src/scan/autoDetection.js +12 -5
  45. package/src/scan/fileUtils.js +33 -19
  46. package/src/utils/paramsUtil/paramHandler.js +16 -2
  47. package/src/utils/validationCheck.js +6 -1
  48. package/dist/utils/settingsHelper.js +0 -14
  49. package/src/utils/settingsHelper.js +0 -16
@@ -32,11 +32,6 @@ const legacyFlow = async (config, messageToSend) => {
32
32
  succeedSpinner(reportSpinner, i18n.__('auditSCAAnalysisComplete'))
33
33
 
34
34
  await vulnerabilityReportV2(config, snapshotResponse.id)
35
- if (config.save !== undefined) {
36
- await auditSave(config)
37
- } else {
38
- console.log('\nUse contrast audit --save to generate an SBOM')
39
- }
40
35
  const endTime = performance.now() - startTime
41
36
  const scanDurationMs = endTime - startTime
42
37
 
@@ -1,7 +1,8 @@
1
1
  const projectConfig = require('../commands/github/projectGroup')
2
+ const repoService = require('../commands/github/repoServices')
2
3
  const scaServicesUpload = require('../scaAnalysis/common/scaServicesUpload')
3
4
 
4
- const trackProcess = async (analysis, config, reportSpinner) => {
5
+ const dealWithNoProjectId = async (analysis, config, reportSpinner) => {
5
6
  await projectConfig.registerNewProjectGroup(config)
6
7
  let projectId = await projectConfig.getProjectIdByOrg(config)
7
8
  await projectConfig.registerProjectIdOnCliServices(config, projectId)
@@ -10,29 +11,83 @@ const trackProcess = async (analysis, config, reportSpinner) => {
10
11
  }
11
12
 
12
13
  const repoProcess = async (analysis, config, reportSpinner) => {
13
- let repoInfo = repoService.retrieveRepoId(config)
14
- if (repoInfo.repoId === '') {
15
- repoInfo = repoService.registerRepo(config)
14
+ if (config.debug || config.verbose) {
15
+ console.log('in repository process')
16
+ console.log('repository id: ', config.repositoryId)
17
+ }
18
+ if (config.repositoryId === '') {
19
+ console.log('Failed to retrieve Repository Id')
20
+ process.exit(1)
16
21
  }
17
- await projectConfig.registerProjectIdOnCliServices(config, repoInfo.projectId)
18
- return repoInfo
19
- }
20
22
 
21
- const dealWithNoProjectId = async (analysis, config, reportSpinner) => {
22
- // if (config.repo === '') {
23
- // return repoProcess(analysis, config, reportSpinner)
23
+ let repoInfo = await repoService.retrieveProjectInfoViaRepoId(config)
24
+
25
+ repoInfo = repoInfo.find(
26
+ element =>
27
+ config.fileName === element.path &&
28
+ config.fileName === element.name &&
29
+ config.projectGroupId === element.projectGroupId
30
+ )
31
+
32
+ // console.log('repoInfo', repoInfo)
33
+
34
+ // if(repoInfo !== undefined) {
35
+ // console.log('re-register / register first time')
36
+ // const language = repoInfo.language === 'JAVASCRIPT' ? 'NODE' : repoInfo.language
37
+ // const additionalData = {
38
+ // projectGroupId: repoInfo.projectGroupId,
39
+ // projectGroupName: repoInfo.name,
40
+ // projectLanguage: language,
41
+ // projectType: 'REPOSITORY'
42
+ // }
43
+ //
44
+ // // check project exists in sca / register (just in case, it failed in the past)
45
+ // await projectConfig.registerProjectIdOnCliServices(
46
+ // config,
47
+ // repoInfo.projectId,
48
+ // additionalData
49
+ // )
24
50
  // }
25
- if (config.track) {
26
- return trackProcess(analysis, config, reportSpinner)
27
- }
28
51
 
29
- if (!config.track) {
30
- return await scaServicesUpload.noProjectUpload(
31
- analysis,
52
+ if (
53
+ config.projectGroupId &&
54
+ !repoInfo?.projectId &&
55
+ (repoInfo === undefined || repoInfo.length === 0)
56
+ ) {
57
+ console.log(
58
+ '*** has projectGroupId, no projectId and repo has no project found that matches'
59
+ )
60
+ repoInfo = await projectConfig.registerProjectWithGroupProjectId(config)
61
+ console.log('new registered group', repoInfo)
62
+ const language =
63
+ repoInfo.language === 'JAVASCRIPT' ? 'NODE' : repoInfo.language
64
+
65
+ // const additionalData = {
66
+ // projectGroupId: repoInfo.projectGroupId,
67
+ // projectGroupName: repoInfo.name,
68
+ // projectLanguage: language,
69
+ // projectType: 'REPOSITORY'
70
+ // }
71
+
72
+ await projectConfig.registerProjectIdOnCliServices(
32
73
  config,
33
- reportSpinner
74
+ repoInfo.projectId
34
75
  )
35
76
  }
77
+ config.projectId = repoInfo.projectId
78
+ return await scaServicesUpload.scaTreeUpload(analysis, config, reportSpinner)
79
+ }
80
+
81
+ const trackProcess = async (analysis, config, reportSpinner) => {
82
+ let projectId = await projectConfig.getProjectIdByOrg(config)
83
+
84
+ if (projectId === '') {
85
+ return dealWithNoProjectId(analysis, config, reportSpinner)
86
+ }
87
+ config.projectId = projectId
88
+ // we can always register just in case but normally we exit when
89
+ await projectConfig.registerProjectIdOnCliServices(config, projectId)
90
+ return await scaServicesUpload.scaTreeUpload(analysis, config, reportSpinner)
36
91
  }
37
92
 
38
93
  const processUpload = async (analysis, config, reportSpinner) => {
@@ -40,15 +95,17 @@ const processUpload = async (analysis, config, reportSpinner) => {
40
95
  // if cli tracked but no projectId -> registerNewProjectGroup THEN scaTreeUpload
41
96
  // if cli not tracked and no projectID -> noProjectUpload
42
97
  // if cli not tracked and projectID -> scaTreeUpload}
43
- let projectId = await projectConfig.getProjectIdByOrg(config)
44
98
 
45
- if (projectId === '') {
46
- return dealWithNoProjectId(analysis, config, reportSpinner)
99
+ if (config.repositoryId) {
100
+ return repoProcess(analysis, config, reportSpinner)
47
101
  }
48
102
 
49
- if (projectId) {
50
- config.projectId = projectId
51
- return await scaServicesUpload.scaTreeUpload(
103
+ if (config.track) {
104
+ return trackProcess(analysis, config, reportSpinner)
105
+ }
106
+
107
+ if (!config.track) {
108
+ return await scaServicesUpload.noProjectUpload(
52
109
  analysis,
53
110
  config,
54
111
  reportSpinner
@@ -57,5 +114,6 @@ const processUpload = async (analysis, config, reportSpinner) => {
57
114
  }
58
115
 
59
116
  module.exports = {
60
- processUpload
117
+ processUpload,
118
+ repoProcess
61
119
  }
@@ -32,6 +32,7 @@ const parsePomFile = jsonPomFile => {
32
32
  let dependencyTree = {}
33
33
  let parsedVersion
34
34
  let dependencies
35
+
35
36
  jsonPomFile.project.hasOwnProperty('dependencies')
36
37
  ? (dependencies = jsonPomFile.project.dependencies[0].dependency)
37
38
  : (dependencies =
@@ -68,7 +69,29 @@ const parsePomFile = jsonPomFile => {
68
69
  }
69
70
  dependencyTree[depName] = parsedDependency
70
71
  }
71
- return dependencyTree
72
+
73
+ const retrieveParent = getParentDependency(jsonPomFile)
74
+
75
+ return {
76
+ parentPom: retrieveParent,
77
+ dependencyTree
78
+ }
79
+ }
80
+
81
+ const getParentDependency = jsonPomFile => {
82
+ let parent = {}
83
+ jsonPomFile.project.hasOwnProperty('parent')
84
+ ? (parent = buildParent(jsonPomFile.project.parent))
85
+ : (parent = undefined)
86
+ return parent
87
+ }
88
+
89
+ const buildParent = parent => {
90
+ return {
91
+ group: parent[0].groupId[0],
92
+ name: parent[0].artifactId[0],
93
+ version: parent[0].version[0]
94
+ }
72
95
  }
73
96
 
74
97
  const getVersion = (pomFile, dependencyWithoutVersion) => {
@@ -10,7 +10,6 @@ const autoDetection = require('../scan/autoDetection')
10
10
  const rootFile = require('../audit/languageAnalysisEngine/getProjectRootFilenames')
11
11
  const path = require('path')
12
12
  const i18n = require('i18n')
13
- const auditSave = require('../audit/save')
14
13
  const { auditUsageGuide } = require('../commands/audit/help')
15
14
  const repoMode = require('./repoMode')
16
15
  const { dotNetAnalysis } = require('./dotnet')
@@ -37,6 +36,8 @@ const processSca = async config => {
37
36
  process.exit(0)
38
37
  }
39
38
 
39
+ config.repo = config.repositoryId !== undefined
40
+
40
41
  const projectStats = await rootFile.getProjectStats(config.file)
41
42
  let pathWithFile = projectStats.isFile()
42
43
 
@@ -46,7 +47,7 @@ const processSca = async config => {
46
47
  : config.file
47
48
 
48
49
  filesFound = await autoDetection.autoDetectAuditFilesAndLanguages(config.file)
49
-
50
+ filesFound = await autoDetection.detectPackageManager(filesFound)
50
51
  autoDetection.dealWithMultiJava(filesFound)
51
52
 
52
53
  if (filesFound.length > 1 && pathWithFile) {
@@ -59,6 +60,7 @@ const processSca = async config => {
59
60
  //check we have the language and call the right analyser
60
61
  let messageToSend = undefined
61
62
  if (filesFound.length === 1) {
63
+ config.packageManager = filesFound[0]?.packageManager
62
64
  switch (Object.keys(filesFound[0])[0]) {
63
65
  case JAVA:
64
66
  config.language = JAVA
@@ -131,12 +133,11 @@ const processSca = async config => {
131
133
  const reportModelLibraryList = convertGenericToTypedReportModelSca(
132
134
  reportResponse.reportArray
133
135
  )
134
- auditReport.processAuditReport(config, reportModelLibraryList)
135
- if (config.save !== undefined) {
136
- await auditSave.auditSave(config, reportResponse.reportId)
137
- } else {
138
- console.log('Use contrast audit --save to generate an SBOM')
139
- }
136
+ await auditReport.processAuditReport(
137
+ config,
138
+ reportModelLibraryList,
139
+ reportResponse.reportId
140
+ )
140
141
 
141
142
  succeedSpinner(reportSpinner, i18n.__('auditSCAAnalysisComplete'))
142
143
 
@@ -9,11 +9,14 @@ const autoDetectFingerprintInfo = async (filePath, depth, config) => {
9
9
  let count = 0
10
10
  complexObj.forEach(i => {
11
11
  count++
12
- result.push({
13
- filePath: i,
14
- id: count.toString(),
15
- repositoryId: config.repositoryId
16
- })
12
+ if (!i.includes('package.json')) {
13
+ result.push({
14
+ filePath: i,
15
+ id: count.toString(),
16
+ repositoryId: config.repositoryId,
17
+ projectGroupId: config.projectGroupId
18
+ })
19
+ }
17
20
  })
18
21
 
19
22
  return result
@@ -43,15 +46,19 @@ const detectPackageManager = async array => {
43
46
  }
44
47
  if (i.filePath.includes('Pipfile')) {
45
48
  i['language'] = PYTHON
49
+ i['packageManager'] = 'PYPI'
46
50
  }
47
51
  if (i.filePath.includes('csproj')) {
48
52
  i['language'] = DOTNET
53
+ i['packageManager'] = 'NUGET'
49
54
  }
50
55
  if (i.filePath.includes('Gemfile')) {
51
56
  i['language'] = RUBY
57
+ i['packageManager'] = 'RUBYGEMS'
52
58
  }
53
59
  if (i.filePath.includes('go.mod')) {
54
60
  i['language'] = GO
61
+ i['packageManager'] = 'PKG'
55
62
  }
56
63
  })
57
64
  return array
@@ -18,6 +18,7 @@ const findAllFiles = async (filePath, depth = 2) => {
18
18
  '**/build.gradle',
19
19
  '**/build.gradle.kts',
20
20
  '**/package.json',
21
+ '**/package-lock.json',
21
22
  '**/yarn.lock',
22
23
  '**/Pipfile',
23
24
  '**/*.csproj',
@@ -51,94 +52,107 @@ const findFilesJava = async (languagesFound, filePath, depth = 1) => {
51
52
  )
52
53
 
53
54
  if (result.length > 0) {
54
- return languagesFound.push({ JAVA: result, language: 'JAVA' })
55
+ let lockFile = result.find(i => i.includes('pom') || i.includes('gradle'))
56
+ return languagesFound.push({
57
+ JAVA: result,
58
+ language: 'JAVA',
59
+ filePath: lockFile
60
+ })
55
61
  }
56
62
  return languagesFound
57
63
  }
58
64
 
59
- const findFilesJavascript = async (languagesFound, filePath) => {
65
+ const findFilesJavascript = async (languagesFound, filePath, depth = 1) => {
60
66
  const result = await fg(
61
67
  ['**/package.json', '**/yarn.lock', '**/package-lock.json'],
62
68
  {
63
69
  dot: false,
64
- deep: 1,
70
+ deep: depth,
65
71
  onlyFiles: true,
66
72
  cwd: filePath ? filePath : process.cwd()
67
73
  }
68
74
  )
69
75
 
70
76
  if (result.length > 0) {
71
- return languagesFound.push({ JAVASCRIPT: result, language: 'JAVASCRIPT' })
77
+ let lockFile = result.find(i => i.includes('lock'))
78
+ return languagesFound.push({
79
+ JAVASCRIPT: result,
80
+ language: 'JAVASCRIPT',
81
+ filePath: lockFile
82
+ })
72
83
  }
73
84
  return languagesFound
74
85
  }
75
86
 
76
- const findFilesPython = async (languagesFound, filePath) => {
87
+ const findFilesPython = async (languagesFound, filePath, depth = 1) => {
77
88
  const result = await fg(['**/Pipfile.lock', '**/Pipfile'], {
78
89
  dot: false,
79
- deep: 3,
90
+ deep: depth,
80
91
  onlyFiles: true,
81
92
  cwd: filePath ? filePath : process.cwd()
82
93
  })
83
94
 
84
95
  if (result.length > 0) {
85
- return languagesFound.push({ PYTHON: result })
96
+ return languagesFound.push({ PYTHON: result, filePath: 'Pipfile' })
86
97
  }
87
98
  return languagesFound
88
99
  }
89
100
 
90
- const findFilesGo = async (languagesFound, filePath) => {
101
+ const findFilesGo = async (languagesFound, filePath, depth = 1) => {
91
102
  const result = await fg(['**/go.mod'], {
92
103
  dot: false,
93
- deep: 3,
104
+ deep: depth,
94
105
  onlyFiles: true,
95
106
  cwd: filePath ? filePath : process.cwd()
96
107
  })
97
108
 
98
109
  if (result.length > 0) {
99
- return languagesFound.push({ GO: result })
110
+ return languagesFound.push({ GO: result, filePath: 'go.mod' })
100
111
  }
101
112
  return languagesFound
102
113
  }
103
114
 
104
- const findFilesRuby = async (languagesFound, filePath) => {
115
+ const findFilesRuby = async (languagesFound, filePath, depth = 1) => {
105
116
  const result = await fg(['**/Gemfile', '**/Gemfile.lock'], {
106
117
  dot: false,
107
- deep: 3,
118
+ deep: depth,
108
119
  onlyFiles: true,
109
120
  cwd: filePath ? filePath : process.cwd()
110
121
  })
111
122
 
112
123
  if (result.length > 0) {
113
- return languagesFound.push({ RUBY: result })
124
+ return languagesFound.push({ RUBY: result, filePath: 'Gemfile' })
114
125
  }
115
126
  return languagesFound
116
127
  }
117
128
 
118
- const findFilesPhp = async (languagesFound, filePath) => {
129
+ const findFilesPhp = async (languagesFound, filePath, depth = 1) => {
119
130
  const result = await fg(['**/composer.json', '**/composer.lock'], {
120
131
  dot: false,
121
- deep: 3,
132
+ deep: depth,
122
133
  onlyFiles: true,
123
134
  cwd: filePath ? filePath : process.cwd()
124
135
  })
125
136
 
126
137
  if (result.length > 0) {
127
- return languagesFound.push({ PHP: result })
138
+ return languagesFound.push({ PHP: result, filePath: 'composer.lock' })
128
139
  }
129
140
  return languagesFound
130
141
  }
131
142
 
132
- const findFilesDotNet = async (languagesFound, filePath) => {
143
+ const findFilesDotNet = async (languagesFound, filePath, depth = 1) => {
133
144
  const result = await fg(['**/*.csproj', '**/packages.lock.json'], {
134
145
  dot: false,
135
- deep: 3,
146
+ deep: depth,
136
147
  onlyFiles: true,
137
148
  cwd: filePath ? filePath : process.cwd()
138
149
  })
139
150
 
140
151
  if (result.length > 0) {
141
- return languagesFound.push({ DOTNET: result })
152
+ return languagesFound.push({
153
+ DOTNET: result,
154
+ filePath: 'packages.lock.json'
155
+ })
142
156
  }
143
157
  return languagesFound
144
158
  }
@@ -1,7 +1,10 @@
1
1
  const commandlineAuth = require('./commandlineParams')
2
2
  const configStoreParams = require('./configStoreParams')
3
3
  const envVariableParams = require('./envVariableParams')
4
- const { validateAuthParams } = require('../validationCheck')
4
+ const {
5
+ validateAuthParams,
6
+ validateFingerprintParams
7
+ } = require('../validationCheck')
5
8
  const i18n = require('i18n')
6
9
 
7
10
  const getAuth = params => {
@@ -21,4 +24,15 @@ const getAuth = params => {
21
24
  }
22
25
  }
23
26
 
24
- module.exports = { getAuth }
27
+ const getFingerprint = params => {
28
+ if (validateFingerprintParams(params)) {
29
+ return params
30
+ } else {
31
+ console.log(
32
+ 'missing fingerprint params please check repository-url and repository-name'
33
+ )
34
+ process.exit(1)
35
+ }
36
+ }
37
+
38
+ module.exports = { getAuth, getFingerprint }
@@ -27,8 +27,13 @@ const validateAuthParams = params => {
27
27
  )
28
28
  }
29
29
 
30
+ const validateFingerprintParams = params => {
31
+ return !!(params.repositoryUrl && params.repositoryName)
32
+ }
33
+
30
34
  module.exports = {
31
35
  checkConfigHasRequiredValues: checkConfigHasRequiredValues,
32
36
  validateAuthParams: validateAuthParams,
33
- validateRequiredScanParams: validateRequiredScanParams
37
+ validateRequiredScanParams: validateRequiredScanParams,
38
+ validateFingerprintParams: validateFingerprintParams
34
39
  }
@@ -1,14 +0,0 @@
1
- "use strict";
2
- const generalAPI = require('./generalAPI');
3
- const { SAAS } = require('../constants/constants');
4
- const getSettings = async (config) => {
5
- config.isEOP =
6
- (await generalAPI.getMode(config)).toUpperCase() === SAAS ? false : true;
7
- if (config.legacy === undefined) {
8
- config.legacy = config.isEOP;
9
- }
10
- return config;
11
- };
12
- module.exports = {
13
- getSettings
14
- };
@@ -1,16 +0,0 @@
1
- const generalAPI = require('./generalAPI')
2
- const { SAAS } = require('../constants/constants')
3
-
4
- const getSettings = async config => {
5
- config.isEOP =
6
- (await generalAPI.getMode(config)).toUpperCase() === SAAS ? false : true
7
-
8
- if (config.legacy === undefined) {
9
- config.legacy = config.isEOP
10
- }
11
- return config
12
- }
13
-
14
- module.exports = {
15
- getSettings
16
- }