@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,103 @@
1
+ /**
2
+ * The 'AnalysisEngine' type represents a simple state machine that can be used
3
+ * to move through a list of steps sequentially to analyze a project. Consumers
4
+ * construct their own steps and add them to the state machine in their desired
5
+ * order. Upon completion the state machine can callback to the consumer that
6
+ * originally invoked them with the results of the analysis.
7
+ */
8
+ class AnalysisEngine {
9
+ /**
10
+ * Constructor that creates a new state machine instance. Accepts an optional
11
+ * argument that initializes the internal state.
12
+ *
13
+ * @param {Object} initAnalysis - state used to initialize internal state
14
+ *
15
+ * @example
16
+ * const ae = new AnalysisEngine()
17
+ * const ae = new AnalysisEngine({ someInfo: [1, 2, 3] })
18
+ */
19
+ constructor(initAnalysis = {}) {
20
+ this.analyzers = []
21
+ this.analysis = { ...initAnalysis }
22
+ }
23
+
24
+ /**
25
+ * Takes either a function or a list of functions and adds them in sequential
26
+ * order to a list. The list will be executed at a later time as the steps of
27
+ * the state machine.
28
+ *
29
+ * Functions must follow the signature (analysis, next) where:
30
+ * 'analysis' is an object that represents the current internal state
31
+ * 'next' is a function to be invoked when the step is complete
32
+ *
33
+ * The function signature of 'next' is (err) where:
34
+ * 'err' is an Error that occurred during the previous step invoked
35
+ *
36
+ * @param {function(analysis: object, next: function)|function[]} analyzer -
37
+ * the analyzer(s) to be added to the list of steps in sequential order
38
+ *
39
+ * @example
40
+ * const myAnalyzer = (analysis, next) => {
41
+ * // Perform business logic
42
+ * // Add results to 'analysis'
43
+ * analysis.result = ...
44
+ *
45
+ * // Signal the next analyzer/step to be invoked
46
+ * next()
47
+ * }
48
+ *
49
+ * ae.use(myAnalyzer)
50
+ */
51
+ use(analyzer) {
52
+ if (Array.isArray(analyzer)) {
53
+ this.analyzers = [...this.analyzers, ...analyzer]
54
+ return
55
+ }
56
+
57
+ this.analyzers.push(analyzer)
58
+ }
59
+
60
+ /**
61
+ * Starts the execution of the state machine given the steps it is to use.
62
+ * When complete it callbacks back to the consumer that invoked it. The
63
+ * callbacks signature is (err, analysis) where:
64
+ * 'err' is an Error from one of the steps that prevented completion
65
+ * 'analysis' is the final internal state
66
+ *
67
+ * @param {function(err: Error, analysis: object)} callback - callback to be
68
+ * invoked when state machine complete or fails prematurely
69
+ * @param config:object containing config - needed for Java analysis - optional for other languages
70
+ */
71
+ analyze(callback, config) {
72
+ let i = 0
73
+
74
+ const next = err => {
75
+ // If one of the analyzers encountered an error then callback
76
+ if (err) {
77
+ return setImmediate(() => callback(err, this.analysis))
78
+ }
79
+
80
+ // If there are no more analyzers to invoke then callback
81
+ if (i >= this.analyzers.length) {
82
+ return setImmediate(() => callback(null, this.analysis))
83
+ }
84
+
85
+ // Invoke the next analyzer
86
+ const analyzer = this.analyzers[i]
87
+ i++
88
+
89
+ setImmediate(() => {
90
+ // Protect ourselves from any uncaught errors thrown by analyzers
91
+ try {
92
+ analyzer(this.analysis, next, config)
93
+ } catch (uncaughtErr) {
94
+ next(uncaughtErr)
95
+ }
96
+ })
97
+ }
98
+
99
+ next()
100
+ }
101
+ }
102
+
103
+ module.exports = exports = AnalysisEngine
@@ -0,0 +1,42 @@
1
+ const i18n = require('i18n')
2
+ const { getHttpClient, handleResponseErrors } = require('../../utils/commonApi')
3
+
4
+ const locationOfApp = (config, appId) => {
5
+ return `${config.host}/Contrast/static/ng/index.html#/${config.organizationId}/applications/${appId}`
6
+ }
7
+
8
+ const displaySuccessMessage = (config, appId) => {
9
+ console.log(
10
+ '\n **************************' +
11
+ i18n.__('successHeader') +
12
+ '************************** \n'
13
+ )
14
+ console.log('\n' + i18n.__('catalogueSuccessCommand') + appId + '\n')
15
+ console.log(locationOfApp(config, appId))
16
+ console.log(
17
+ '\n *********************************************************** \n'
18
+ )
19
+ }
20
+
21
+ const catalogueApplication = async config => {
22
+ const client = getHttpClient(config)
23
+ let appId
24
+ await client
25
+ .catalogueCommand(config)
26
+ .then(res => {
27
+ if (res.statusCode === 201) {
28
+ displaySuccessMessage(config, res.body.application.app_id)
29
+ appId = res.body.application.app_id
30
+ } else {
31
+ handleResponseErrors(res, 'catalogue')
32
+ }
33
+ })
34
+ .catch(err => {
35
+ console.log(err)
36
+ })
37
+ return appId
38
+ }
39
+
40
+ module.exports = {
41
+ catalogueApplication: catalogueApplication
42
+ }
@@ -0,0 +1,26 @@
1
+ const AnalysisEngine = require('../AnalysisEngine')
2
+ const readProjectFileContents = require('./readProjectFileContents')
3
+ const parseProjectFileContents = require('./parseProjectFileContents')
4
+ const readLockFileContents = require('./readLockFileContents')
5
+ const parseLockFileContents = require('./parseLockFileContents')
6
+ const sanitizer = require('./sanitizer')
7
+ const i18n = require('i18n')
8
+
9
+ module.exports = exports = (language, config, callback) => {
10
+ const ae = new AnalysisEngine({ language, config, dotnet: {} })
11
+ ae.use([
12
+ readProjectFileContents,
13
+ parseProjectFileContents,
14
+ readLockFileContents,
15
+ parseLockFileContents,
16
+ sanitizer
17
+ ])
18
+
19
+ ae.analyze((err, analysis) => {
20
+ if (err) {
21
+ callback(new Error(i18n.__('dotnetAnalysisFailure') + err.message))
22
+ return
23
+ }
24
+ callback(null, analysis)
25
+ })
26
+ }
@@ -0,0 +1,47 @@
1
+ const i18n = require('i18n')
2
+
3
+ module.exports = exports = ({ language: { lockFilePath }, dotnet }, next) => {
4
+ const { rawLockFileContents } = dotnet
5
+
6
+ // If we never read the lock file then pass priority
7
+ if (!rawLockFileContents) {
8
+ next()
9
+
10
+ return
11
+ }
12
+
13
+ try {
14
+ let count = 0 // Used to test if some nodes are deleted
15
+ dotnet.lockFile = JSON.parse(rawLockFileContents)
16
+
17
+ for (const dependenciesNode in dotnet.lockFile.dependencies) {
18
+ for (const innerNode in dotnet.lockFile.dependencies[dependenciesNode]) {
19
+ const nodeValidation = JSON.stringify(
20
+ dotnet.lockFile.dependencies[dependenciesNode][innerNode]
21
+ )
22
+ if (nodeValidation.includes('"type":"Project"')) {
23
+ count += 1
24
+ delete dotnet.lockFile.dependencies[dependenciesNode][innerNode]
25
+ dotnet.additionalInfo = 'dependenciesNote'
26
+ }
27
+ }
28
+ }
29
+
30
+ // If dependencies removed wait for json to be displayed and flag warning
31
+ if (count > 0) {
32
+ const multiLevelProjectWarning = () => {
33
+ console.log('')
34
+ console.log(i18n.__('dependenciesNote'))
35
+ }
36
+ setTimeout(multiLevelProjectWarning, 7000)
37
+ }
38
+ } catch (err) {
39
+ next(
40
+ new Error(i18n.__('dotnetParseLockfile', lockFilePath) + `${err.message}`)
41
+ )
42
+
43
+ return
44
+ }
45
+
46
+ next()
47
+ }
@@ -0,0 +1,29 @@
1
+ const xml2js = require('xml2js')
2
+ const i18n = require('i18n')
3
+
4
+ module.exports = exports = (
5
+ { language: { projectFilePath }, dotnet },
6
+ next
7
+ ) => {
8
+ const { rawProjectFileContents } = dotnet
9
+
10
+ // Read the .NET project file contents. We are reading into memory presuming
11
+ // that the contents of the file aren't large which may be bad... Could look
12
+ // into streaming in the future
13
+ // explicitArray: false - to not abuse of arrays, with this option we are able to read JSON properties in an easier way
14
+ // mergeAttrs: true - to merge attributes and child elements as properties of the parent
15
+ const parser = new xml2js.Parser({ explicitArray: false, mergeAttrs: true })
16
+ parser.parseString(rawProjectFileContents, (err, projectFileXML) => {
17
+ if (err) {
18
+ next(
19
+ new Error(i18n.__('dotnetParseProjectFile', projectFilePath) + `${err}`)
20
+ )
21
+
22
+ return
23
+ }
24
+
25
+ dotnet.projectFile = projectFileXML
26
+
27
+ next()
28
+ })
29
+ }
@@ -0,0 +1,30 @@
1
+ const fs = require('fs')
2
+ const i18n = require('i18n')
3
+
4
+ module.exports = exports = (analysis, next) => {
5
+ const {
6
+ language: { lockFilePath },
7
+ dotnet
8
+ } = analysis
9
+
10
+ // Make sure to check to see if there was a lock file detected as its not
11
+ // required
12
+ if (!lockFilePath) {
13
+ next()
14
+ return
15
+ }
16
+
17
+ // we're working on the assumtion that a dotNet project will only ever have one lock file
18
+ //while other language may have more
19
+ try {
20
+ dotnet.rawLockFileContents = fs.readFileSync(lockFilePath)
21
+ } catch (err) {
22
+ next(
23
+ new Error(i18n.__('dotnetReadLockfile', lockFilePath) + `${err.message}`)
24
+ )
25
+
26
+ return
27
+ }
28
+
29
+ next()
30
+ }
@@ -0,0 +1,26 @@
1
+ const fs = require('fs')
2
+ const i18n = require('i18n')
3
+
4
+ module.exports = exports = (analysis, next) => {
5
+ const {
6
+ language: { projectFilePath },
7
+ dotnet
8
+ } = analysis
9
+
10
+ // Read the .NET project file contents. We are reading into memory presuming
11
+ // that the contents of the file aren't large which may be bad... Could look
12
+ // into streaming in the future
13
+ try {
14
+ dotnet.rawProjectFileContents = fs.readFileSync(projectFilePath)
15
+ } catch (err) {
16
+ next(
17
+ new Error(
18
+ i18n.__('dotnetReadProjectFile', projectFilePath) + `${err.message}`
19
+ )
20
+ )
21
+
22
+ return
23
+ }
24
+
25
+ next()
26
+ }
@@ -0,0 +1,11 @@
1
+ module.exports = exports = ({ dotnet }, next) => {
2
+ // Remove anything sensitive or unnecessary from being sent to the backend as
3
+ // a result of our .NET project analysis
4
+ delete dotnet.rawProjectFileContents
5
+ delete dotnet.parsedProjectFileContents
6
+ delete dotnet.projectFileXML
7
+ delete dotnet.packageReferences
8
+ delete dotnet.rawLockFileContents
9
+
10
+ next()
11
+ }
@@ -0,0 +1,18 @@
1
+ const AnalysisEngine = require('../AnalysisEngine')
2
+ const readProjectFileContents = require('./readProjectFileContents')
3
+ const parseProjectFileContents = require('./parseProjectFileContents')
4
+ const sanitizer = require('./sanitizer')
5
+ const i18n = require('i18n')
6
+
7
+ module.exports = exports = (language, config, callback) => {
8
+ const ae = new AnalysisEngine({ language, config, go: {} })
9
+ ae.use([readProjectFileContents, parseProjectFileContents, sanitizer])
10
+
11
+ ae.analyze((err, analysis) => {
12
+ if (err) {
13
+ callback(new Error(i18n.__('goAnalysisError') + `${err.message}`))
14
+ return
15
+ }
16
+ callback(null, analysis)
17
+ })
18
+ }
@@ -0,0 +1,209 @@
1
+ const i18n = require('i18n')
2
+ const crypto = require('crypto')
3
+
4
+ module.exports = exports = ({ go }, next) => {
5
+ const { modGraphOutput } = go
6
+ try {
7
+ go.goDependencyTrees = parseGo(modGraphOutput)
8
+ } catch (err) {
9
+ next(new Error(i18n.__('goParseProjectFile') + `${err.message}`))
10
+ return
11
+ }
12
+ next()
13
+ }
14
+
15
+ const splitAllLinesIntoArray = modGraphOutput => {
16
+ return modGraphOutput.split(/\r\n|\r|\n/)
17
+ }
18
+
19
+ const parseGo = modGraphOutput => {
20
+ let splitLines = splitAllLinesIntoArray(modGraphOutput)
21
+ const directDepNames = getDirectDepNames(splitLines)
22
+ const uniqueTransitiveDepNames = getAllUniqueTransitiveDepNames(
23
+ splitLines,
24
+ directDepNames
25
+ )
26
+
27
+ let rootNodes = createRootNodes(splitLines)
28
+
29
+ createTransitiveDeps(uniqueTransitiveDepNames, splitLines, rootNodes)
30
+
31
+ //console.log(rootNodes)
32
+
33
+ return rootNodes
34
+ }
35
+
36
+ const getAllDepsOfADepAsEdge = (dep, deps) => {
37
+ let edges = {}
38
+
39
+ const depRows = deps.filter(line => {
40
+ return line.startsWith(dep)
41
+ })
42
+
43
+ depRows.forEach(dep => {
44
+ const edgeName = dep.split(' ')[1]
45
+ edges[edgeName] = edgeName
46
+ })
47
+
48
+ return edges
49
+ }
50
+
51
+ const getAllDepsOfADepAsName = (dep, deps) => {
52
+ let edges = []
53
+
54
+ const depRows = deps.filter(line => {
55
+ return line.startsWith(dep)
56
+ })
57
+
58
+ depRows.forEach(dep => {
59
+ const edgeName = dep.split(' ')[1]
60
+ edges.push(edgeName)
61
+ })
62
+
63
+ return edges
64
+ }
65
+
66
+ const createRootNodes = deps => {
67
+ let rootDep = {}
68
+ const rootDeps = getRootDeps(deps)
69
+
70
+ const edges = rootDeps.map(dep => {
71
+ return dep.split(' ')[1]
72
+ })
73
+
74
+ rootDep[rootDeps[0].split(' ')[0]] = {}
75
+
76
+ edges.forEach(edge => {
77
+ const splitEdge = edge.split('@')
78
+ const splitGroupName = splitEdge[0].split('/')
79
+ const name = splitGroupName.pop()
80
+ const lastSlash = splitEdge[0].lastIndexOf('/')
81
+ let group = splitEdge[0].substring(0, lastSlash)
82
+ const hash = getHash(splitEdge[0])
83
+
84
+ group = checkGroupExists(group, name)
85
+
86
+ //get the edges of the root dependency
87
+ const edgesOfDep = getAllDepsOfADepAsEdge(edge, deps)
88
+
89
+ rootDep[rootDeps[0].split(' ')[0]][edge] = {
90
+ artifactID: name,
91
+ group: group,
92
+ version: splitEdge[1],
93
+ scope: '"compile',
94
+ type: 'direct',
95
+ hash: hash,
96
+ edges: edgesOfDep
97
+ }
98
+ })
99
+ return rootDep
100
+ }
101
+
102
+ const getRootDeps = deps => {
103
+ const rootDeps = deps.filter(dep => {
104
+ const parentDep = dep.split(' ')[0]
105
+ if (parentDep.split('@v').length === 1) {
106
+ return dep
107
+ }
108
+ })
109
+ return rootDeps
110
+ }
111
+
112
+ const getHash = library => {
113
+ let shaSum = crypto.createHash('sha1')
114
+ shaSum.update(library)
115
+ return shaSum.digest('hex')
116
+ }
117
+
118
+ const getDirectDepNames = deps => {
119
+ const directDepNames = []
120
+
121
+ deps.forEach(dep => {
122
+ const parentDep = dep.split(' ')[0]
123
+ if (parentDep.split('@v').length === 1) {
124
+ dep.split(' ')[1] !== undefined
125
+ ? directDepNames.push(dep.split(' ')[1])
126
+ : null
127
+ }
128
+ })
129
+ return directDepNames
130
+ }
131
+
132
+ const getAllUniqueTransitiveDepNames = (deps, directDepNames) => {
133
+ let uniqueDeps = []
134
+
135
+ deps.forEach(dep => {
136
+ const parentDep = dep.split(' ')[0]
137
+ if (parentDep.split('@v').length !== 1) {
138
+ if (!directDepNames.includes(parentDep)) {
139
+ if (!uniqueDeps.includes(parentDep)) {
140
+ parentDep.length > 1 ? uniqueDeps.push(parentDep) : null
141
+ }
142
+ }
143
+ }
144
+ })
145
+ return uniqueDeps
146
+ }
147
+
148
+ const checkGroupExists = (group, name) => {
149
+ if (group === null || group === '') {
150
+ return name
151
+ }
152
+ return group
153
+ }
154
+
155
+ const createTransitiveDeps = (transitiveDeps, splitLines, rootNodes) => {
156
+ transitiveDeps.forEach(dep => {
157
+ //create transitive dep
158
+ const splitEdge = dep.split('@')
159
+ const splitGroupName = splitEdge[0].split('/')
160
+ const name = splitGroupName.pop()
161
+ const lastSlash = splitEdge[0].lastIndexOf('/')
162
+ let group = splitEdge[0].substring(0, lastSlash)
163
+ const hash = getHash(splitEdge[0])
164
+
165
+ group = checkGroupExists(group, name)
166
+
167
+ const transitiveDep = {
168
+ artifactID: name,
169
+ group: group,
170
+ version: splitEdge[1],
171
+ scope: 'compile',
172
+ type: 'transitive',
173
+ hash: hash,
174
+ edges: {}
175
+ }
176
+
177
+ //add edges to transitiveDep
178
+ const edges = getAllDepsOfADepAsEdge(dep, splitLines)
179
+ transitiveDep.edges = edges
180
+
181
+ //add all edges as a transitive dependency to rootNodes
182
+ const edgesAsName = getAllDepsOfADepAsName(dep, splitLines)
183
+
184
+ edgesAsName.forEach(dep => {
185
+ const splitEdge = dep.split('@')
186
+ const splitGroupName = splitEdge[0].split('/')
187
+ const name = splitGroupName.pop()
188
+ const lastSlash = splitEdge[0].lastIndexOf('/')
189
+ let group = splitEdge[0].substring(0, lastSlash)
190
+ const hash = getHash(splitEdge[0])
191
+
192
+ group = checkGroupExists(group, name)
193
+
194
+ const transitiveDep = {
195
+ artifactID: name,
196
+ group: group,
197
+ version: splitEdge[1],
198
+ scope: 'compile',
199
+ type: 'transitive',
200
+ hash: hash,
201
+ edges: {}
202
+ }
203
+ rootNodes[Object.keys(rootNodes)[0]][dep] = transitiveDep
204
+ })
205
+
206
+ //add transitive dependency to rootNodes
207
+ rootNodes[Object.keys(rootNodes)[0]][dep] = transitiveDep
208
+ })
209
+ }
@@ -0,0 +1,31 @@
1
+ const child_process = require('child_process')
2
+ const i18n = require('i18n')
3
+
4
+ module.exports = exports = async (
5
+ { language: { projectFilePath }, go },
6
+ next
7
+ ) => {
8
+ let cmdStdout
9
+ let cwd
10
+ try {
11
+ cwd = projectFilePath.replace('go.mod', '')
12
+ // A sample of this output can be found
13
+ // in the go test folder data/goModGraphResults.text
14
+ cmdStdout = child_process.execSync('go mod graph', { cwd })
15
+
16
+ go.modGraphOutput = cmdStdout.toString()
17
+
18
+ next()
19
+ } catch (err) {
20
+ if (err.message === 'spawnSync /bin/sh ENOENT') {
21
+ err.message =
22
+ '\n\n*************** No transitive dependencies ***************\n\nWe are unable to build a dependency tree view from your repository as there were no transitive dependencies found.'
23
+ }
24
+ next(
25
+ new Error(
26
+ i18n.__('goReadProjectFile', cwd, `${err.message ? err.message : ''}`)
27
+ )
28
+ )
29
+ return
30
+ }
31
+ }
@@ -0,0 +1,7 @@
1
+ module.exports = exports = ({ go }, next) => {
2
+ // Remove anything sensitive or unnecessary from being sent to the backend as
3
+ // a result of our Go project analysis
4
+ delete go.modGraphOutput
5
+
6
+ next()
7
+ }
@@ -0,0 +1,41 @@
1
+ const AnalysisEngine = require('../AnalysisEngine')
2
+
3
+ const readProjectFileContents = require('./readProjectFileContents')
4
+ const parseMavenProjectFileContents = require('./parseMavenProjectFileContents')
5
+ const parseProjectFileContents = require('./parseProjectFileContents')
6
+ const sanitizer = require('./sanitizer')
7
+ const i18n = require('i18n')
8
+
9
+ module.exports = exports = (language, config, callback) => {
10
+ const ae = new AnalysisEngine({ language, config, java: {} })
11
+
12
+ // Remove ".kts" from filename to look the same as a Gradle projectFileName so we can support Kotlin
13
+ language.projectFilePath = language.projectFilePath.replace(
14
+ 'build.gradle.kts',
15
+ 'build.gradle'
16
+ )
17
+
18
+ if (config['beta_unified_java_parser']) {
19
+ console.log('Using new parser...')
20
+ ae.use([readProjectFileContents, parseProjectFileContents, sanitizer])
21
+ } else if (
22
+ language.projectFilePath.endsWith('pom.xml') &&
23
+ !config['beta_unified_java_parser']
24
+ ) {
25
+ ae.use([readProjectFileContents, parseMavenProjectFileContents, sanitizer])
26
+ } else {
27
+ ae.use([
28
+ readProjectFileContents,
29
+ parseMavenProjectFileContents,
30
+ parseProjectFileContents,
31
+ sanitizer
32
+ ])
33
+ }
34
+ ae.analyze((err, analysis) => {
35
+ if (err) {
36
+ console.log(i18n.__('javaAnalysisError'), err.message)
37
+ return
38
+ }
39
+ callback(null, analysis, config)
40
+ }, config)
41
+ }