@contrast/contrast 1.0.5 → 1.0.6
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.
- package/.prettierignore +1 -0
- package/dist/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +5 -1
- package/dist/audit/languageAnalysisEngine/report/commonReportingFunctions.js +66 -13
- package/dist/audit/languageAnalysisEngine/report/models/reportOutputModel.js +24 -0
- package/dist/audit/languageAnalysisEngine/report/models/reportSeverityModel.js +3 -1
- package/dist/audit/languageAnalysisEngine/report/models/severityCountModel.js +13 -0
- package/dist/audit/languageAnalysisEngine/report/reportingFeature.js +1 -1
- package/dist/audit/languageAnalysisEngine/report/utils/reportUtils.js +59 -45
- package/dist/commands/audit/auditController.js +1 -1
- package/dist/commands/scan/processScan.js +1 -1
- package/dist/commands/scan/sca/scaAnalysis.js +12 -7
- package/dist/constants/constants.js +13 -3
- package/dist/scaAnalysis/common/formatMessage.js +9 -1
- package/dist/scaAnalysis/common/treeUpload.js +2 -3
- package/dist/scaAnalysis/go/goAnalysis.js +17 -0
- package/dist/scaAnalysis/go/goParseDeps.js +158 -0
- package/dist/scaAnalysis/go/goReadDepFile.js +23 -0
- package/dist/scaAnalysis/java/analysis.js +6 -14
- package/dist/scaAnalysis/java/index.js +5 -5
- package/dist/scaAnalysis/java/javaBuildDepsParser.js +14 -1
- package/dist/scan/formatScanOutput.js +10 -7
- package/dist/scan/scan.js +4 -3
- package/dist/scan/scanController.js +11 -4
- package/dist/scan/scanResults.js +15 -5
- package/dist/utils/oraWrapper.js +5 -1
- package/package.json +1 -1
- package/src/audit/languageAnalysisEngine/reduceIdentifiedLanguages.js +6 -5
- package/src/audit/languageAnalysisEngine/report/commonReportingFunctions.ts +117 -18
- package/src/audit/languageAnalysisEngine/report/models/reportOutputModel.ts +29 -0
- package/src/audit/languageAnalysisEngine/report/models/reportSeverityModel.ts +7 -3
- package/src/audit/languageAnalysisEngine/report/models/severityCountModel.ts +16 -0
- package/src/audit/languageAnalysisEngine/report/reportingFeature.ts +2 -2
- package/src/audit/languageAnalysisEngine/report/utils/reportUtils.ts +74 -68
- package/src/commands/audit/auditController.ts +1 -2
- package/src/commands/scan/processScan.js +2 -1
- package/src/commands/scan/sca/scaAnalysis.js +12 -10
- package/src/constants/constants.js +13 -3
- package/src/scaAnalysis/common/formatMessage.js +11 -1
- package/src/scaAnalysis/common/treeUpload.js +2 -6
- package/src/scaAnalysis/go/goAnalysis.js +20 -0
- package/src/scaAnalysis/go/goParseDeps.js +203 -0
- package/src/scaAnalysis/go/goReadDepFile.js +32 -0
- package/src/scaAnalysis/java/analysis.js +8 -24
- package/src/scaAnalysis/java/index.js +5 -5
- package/src/scaAnalysis/java/javaBuildDepsParser.js +15 -2
- package/src/scan/formatScanOutput.ts +17 -8
- package/src/scan/scan.ts +7 -6
- package/src/scan/scanController.js +13 -6
- package/src/scan/scanResults.js +21 -10
- package/src/utils/oraWrapper.js +6 -1
|
@@ -4,91 +4,97 @@ import {
|
|
|
4
4
|
} from '../models/reportLibraryModel'
|
|
5
5
|
import { ReportSeverityModel } from '../models/reportSeverityModel'
|
|
6
6
|
import languageAnalysisEngine from '../../../languageAnalysisEngine/constants'
|
|
7
|
+
import {
|
|
8
|
+
CRITICAL_COLOUR,
|
|
9
|
+
CRITICAL_PRIORITY,
|
|
10
|
+
HIGH_COLOUR,
|
|
11
|
+
HIGH_PRIORITY,
|
|
12
|
+
LOW_COLOUR,
|
|
13
|
+
LOW_PRIORITY,
|
|
14
|
+
MEDIUM_COLOUR,
|
|
15
|
+
MEDIUM_PRIORITY,
|
|
16
|
+
NOTE_COLOUR,
|
|
17
|
+
NOTE_PRIORITY
|
|
18
|
+
} from '../../../../constants/constants'
|
|
19
|
+
import { orderBy } from 'lodash'
|
|
20
|
+
import {SeverityCountModel} from "../models/severityCountModel";
|
|
7
21
|
const {
|
|
8
22
|
supportedLanguages: { GO }
|
|
9
23
|
} = languageAnalysisEngine
|
|
10
24
|
|
|
11
25
|
export function findHighestSeverityCVE(cveArray: ReportCVEModel[]) {
|
|
26
|
+
const mappedToReportSeverityModels = cveArray.map(cve => findCVESeverity(cve))
|
|
27
|
+
|
|
28
|
+
//order and get first
|
|
29
|
+
return orderBy(mappedToReportSeverityModels, cve => cve?.priority)[0]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
export function findCVESeveritiesAndOrderByHighestPriority(cves: ReportCVEModel[]) {
|
|
34
|
+
return orderBy(cves.map(cve => findCVESeverity(cve)), ['priority'], ['asc'])
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function findCVESeverity(cve: ReportCVEModel) {
|
|
38
|
+
const cveName = cve.name as string
|
|
39
|
+
if (cve.cvss3SeverityCode === 'CRITICAL' || cve.severityCode === 'CRITICAL') {
|
|
40
|
+
return new ReportSeverityModel('CRITICAL', CRITICAL_PRIORITY, CRITICAL_COLOUR, cveName)
|
|
41
|
+
} else if (cve.cvss3SeverityCode === 'HIGH' || cve.severityCode === 'HIGH') {
|
|
42
|
+
return new ReportSeverityModel('HIGH', HIGH_PRIORITY, HIGH_COLOUR, cveName)
|
|
43
|
+
} else if (cve.cvss3SeverityCode === 'MEDIUM' || cve.severityCode === 'MEDIUM') {
|
|
44
|
+
return new ReportSeverityModel('MEDIUM', MEDIUM_PRIORITY, MEDIUM_COLOUR, cveName)
|
|
45
|
+
} else if (cve.cvss3SeverityCode === 'LOW' || cve.severityCode === 'LOW') {
|
|
46
|
+
return new ReportSeverityModel('LOW', LOW_PRIORITY, LOW_COLOUR, cveName)
|
|
47
|
+
} else if (cve.cvss3SeverityCode === 'NOTE' || cve.severityCode === 'NOTE') {
|
|
48
|
+
return new ReportSeverityModel('NOTE', NOTE_PRIORITY, NOTE_COLOUR, cveName)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function convertGenericToTypedLibraries(libraries: any) {
|
|
53
|
+
return Object.entries(libraries).map(([name, cveArray]) => {
|
|
54
|
+
return new ReportLibraryModel(name, cveArray as ReportCVEModel[])
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function severityCountAllLibraries(vulnerableLibraries: ReportLibraryModel[]) {
|
|
59
|
+
const severityCount = new SeverityCountModel()
|
|
60
|
+
vulnerableLibraries.forEach(lib => severityCountAllCVEs(lib.cveArray, severityCount))
|
|
61
|
+
return severityCount
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function severityCountAllCVEs(cveArray: ReportCVEModel[], severityCount: SeverityCountModel) {
|
|
65
|
+
const severityCountInner = severityCount
|
|
66
|
+
cveArray.forEach(cve => severityCountSingleCVE(cve, severityCountInner))
|
|
67
|
+
return severityCountInner
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function severityCountSingleCVE(cve: ReportCVEModel, severityCount: SeverityCountModel) {
|
|
12
71
|
if (
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
cve.cvss3SeverityCode === 'CRITICAL' || cve.severityCode === 'CRITICAL'
|
|
16
|
-
)
|
|
72
|
+
cve.cvss3SeverityCode === 'CRITICAL' ||
|
|
73
|
+
cve.severityCode === 'CRITICAL'
|
|
17
74
|
) {
|
|
18
|
-
|
|
75
|
+
severityCount.critical += 1
|
|
19
76
|
} else if (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
)
|
|
77
|
+
cve.cvss3SeverityCode === 'HIGH' ||
|
|
78
|
+
cve.severityCode === 'HIGH'
|
|
23
79
|
) {
|
|
24
|
-
|
|
80
|
+
severityCount.high += 1
|
|
25
81
|
} else if (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
)
|
|
82
|
+
cve.cvss3SeverityCode === 'MEDIUM' ||
|
|
83
|
+
cve.severityCode === 'MEDIUM'
|
|
29
84
|
) {
|
|
30
|
-
|
|
85
|
+
severityCount.medium += 1
|
|
31
86
|
} else if (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
)
|
|
87
|
+
cve.cvss3SeverityCode === 'LOW' ||
|
|
88
|
+
cve.severityCode === 'LOW'
|
|
35
89
|
) {
|
|
36
|
-
|
|
90
|
+
severityCount.low += 1
|
|
37
91
|
} else if (
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
)
|
|
92
|
+
cve.cvss3SeverityCode === 'NOTE' ||
|
|
93
|
+
cve.severityCode === 'NOTE'
|
|
41
94
|
) {
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function convertGenericToTypedLibraries(libraries: any) {
|
|
47
|
-
return Object.entries(libraries).map(([name, cveArray]) => {
|
|
48
|
-
return new ReportLibraryModel(name, cveArray as ReportCVEModel[])
|
|
49
|
-
})
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function severityCount(vulnerableLibraries: ReportLibraryModel[]) {
|
|
53
|
-
const severityCount = {
|
|
54
|
-
critical: 0,
|
|
55
|
-
high: 0,
|
|
56
|
-
medium: 0,
|
|
57
|
-
low: 0,
|
|
58
|
-
note: 0
|
|
95
|
+
severityCount.note += 1
|
|
59
96
|
}
|
|
60
97
|
|
|
61
|
-
vulnerableLibraries.forEach(lib => {
|
|
62
|
-
lib.cveArray.forEach(cve => {
|
|
63
|
-
if (
|
|
64
|
-
cve.cvss3SeverityCode === 'CRITICAL' ||
|
|
65
|
-
cve.severityCode === 'CRITICAL'
|
|
66
|
-
) {
|
|
67
|
-
severityCount['critical'] += 1
|
|
68
|
-
} else if (
|
|
69
|
-
cve.cvss3SeverityCode === 'HIGH' ||
|
|
70
|
-
cve.severityCode === 'HIGH'
|
|
71
|
-
) {
|
|
72
|
-
severityCount['high'] += 1
|
|
73
|
-
} else if (
|
|
74
|
-
cve.cvss3SeverityCode === 'MEDIUM' ||
|
|
75
|
-
cve.severityCode === 'MEDIUM'
|
|
76
|
-
) {
|
|
77
|
-
severityCount['medium'] += 1
|
|
78
|
-
} else if (
|
|
79
|
-
cve.cvss3SeverityCode === 'LOW' ||
|
|
80
|
-
cve.severityCode === 'LOW'
|
|
81
|
-
) {
|
|
82
|
-
severityCount['low'] += 1
|
|
83
|
-
} else if (
|
|
84
|
-
cve.cvss3SeverityCode === 'NOTE' ||
|
|
85
|
-
cve.severityCode === 'NOTE'
|
|
86
|
-
) {
|
|
87
|
-
severityCount['note'] += 1
|
|
88
|
-
}
|
|
89
|
-
})
|
|
90
|
-
})
|
|
91
|
-
|
|
92
98
|
return severityCount
|
|
93
99
|
}
|
|
94
100
|
|
|
@@ -10,7 +10,6 @@ export const dealWithNoAppId = async (config: { [x: string]: string }) => {
|
|
|
10
10
|
try {
|
|
11
11
|
// @ts-ignore
|
|
12
12
|
appID = await commonApi.returnAppId(config)
|
|
13
|
-
// console.log('appid', appID)
|
|
14
13
|
if (!appID && config.applicationName) {
|
|
15
14
|
return await catalogueApplication(config)
|
|
16
15
|
}
|
|
@@ -23,7 +22,7 @@ export const dealWithNoAppId = async (config: { [x: string]: string }) => {
|
|
|
23
22
|
// @ts-ignore
|
|
24
23
|
if (e.toString().includes('tunneling socket could not be established')) {
|
|
25
24
|
// @ts-ignore
|
|
26
|
-
console.log(e.message)
|
|
25
|
+
console.log(e.message.toString())
|
|
27
26
|
console.log(
|
|
28
27
|
'There seems to be an issue with your proxy, please check and try again'
|
|
29
28
|
)
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
const autoDetection = require('../../../scan/autoDetection')
|
|
2
|
-
const
|
|
3
|
-
const
|
|
2
|
+
const javaAnalysis = require('../../../scaAnalysis/java')
|
|
3
|
+
const treeUpload = require('../../../scaAnalysis/common/treeUpload')
|
|
4
4
|
const {
|
|
5
5
|
manualDetectAuditFilesAndLanguages
|
|
6
6
|
} = require('../../../scan/autoDetection')
|
|
7
|
-
const
|
|
7
|
+
const auditController = require('../../audit/auditController')
|
|
8
8
|
const {
|
|
9
|
-
supportedLanguages: { JAVA }
|
|
9
|
+
supportedLanguages: { JAVA, GO }
|
|
10
10
|
} = require('../../../audit/languageAnalysisEngine/constants')
|
|
11
|
+
const goAnalysis = require('../../../scaAnalysis/go/goAnalysis')
|
|
11
12
|
|
|
12
13
|
const processSca = async config => {
|
|
13
14
|
let filesFound
|
|
@@ -24,7 +25,7 @@ const processSca = async config => {
|
|
|
24
25
|
if (filesFound.length === 1) {
|
|
25
26
|
switch (Object.keys(filesFound[0])[0]) {
|
|
26
27
|
case JAVA:
|
|
27
|
-
messageToSend =
|
|
28
|
+
messageToSend = javaAnalysis.javaAnalysis(config, filesFound[0])
|
|
28
29
|
config.language = JAVA
|
|
29
30
|
break
|
|
30
31
|
// case 'javascript':
|
|
@@ -42,9 +43,10 @@ const processSca = async config => {
|
|
|
42
43
|
// case 'php':
|
|
43
44
|
// // code block
|
|
44
45
|
// break;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
case GO:
|
|
47
|
+
messageToSend = goAnalysis.goAnalysis(config, filesFound[0])
|
|
48
|
+
config.language = GO
|
|
49
|
+
break
|
|
48
50
|
default:
|
|
49
51
|
//something is wrong
|
|
50
52
|
console.log('language detected not supported')
|
|
@@ -52,11 +54,11 @@ const processSca = async config => {
|
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
if (!config.applicationId) {
|
|
55
|
-
config.applicationId = await dealWithNoAppId(config)
|
|
57
|
+
config.applicationId = await auditController.dealWithNoAppId(config)
|
|
56
58
|
}
|
|
57
59
|
//send message to TS
|
|
58
60
|
console.log('processing dependencies')
|
|
59
|
-
const response = await commonSendSnapShot(messageToSend, config)
|
|
61
|
+
const response = await treeUpload.commonSendSnapShot(messageToSend, config)
|
|
60
62
|
} else {
|
|
61
63
|
if (filesFound.length === 0) {
|
|
62
64
|
console.log('no compatible dependency files detected. Continuing...')
|
|
@@ -13,13 +13,18 @@ const MEDIUM = 'MEDIUM'
|
|
|
13
13
|
const HIGH = 'HIGH'
|
|
14
14
|
const CRITICAL = 'CRITICAL'
|
|
15
15
|
const APP_NAME = 'contrast'
|
|
16
|
-
const APP_VERSION = '1.0.
|
|
16
|
+
const APP_VERSION = '1.0.6'
|
|
17
17
|
const TIMEOUT = 120000
|
|
18
18
|
const HIGH_COLOUR = '#ff9900'
|
|
19
19
|
const CRITICAL_COLOUR = '#e35858'
|
|
20
20
|
const MEDIUM_COLOUR = '#f1c232'
|
|
21
|
-
const LOW_COLOUR = '#
|
|
21
|
+
const LOW_COLOUR = '#b7b7b7'
|
|
22
22
|
const NOTE_COLOUR = '#999999'
|
|
23
|
+
const CRITICAL_PRIORITY = 1
|
|
24
|
+
const HIGH_PRIORITY = 2
|
|
25
|
+
const MEDIUM_PRIORITY = 3
|
|
26
|
+
const LOW_PRIORITY = 4
|
|
27
|
+
const NOTE_PRIORITY = 5
|
|
23
28
|
|
|
24
29
|
const AUTH_UI_URL = 'https://cli-auth.contrastsecurity.com'
|
|
25
30
|
const AUTH_CALLBACK_URL = 'https://cli-auth-api.contrastsecurity.com'
|
|
@@ -43,5 +48,10 @@ module.exports = {
|
|
|
43
48
|
MEDIUM_COLOUR,
|
|
44
49
|
LOW_COLOUR,
|
|
45
50
|
NOTE_COLOUR,
|
|
46
|
-
CE_URL
|
|
51
|
+
CE_URL,
|
|
52
|
+
CRITICAL_PRIORITY,
|
|
53
|
+
HIGH_PRIORITY,
|
|
54
|
+
MEDIUM_PRIORITY,
|
|
55
|
+
LOW_PRIORITY,
|
|
56
|
+
NOTE_PRIORITY
|
|
47
57
|
}
|
|
@@ -5,6 +5,16 @@ const createJavaTSMessage = javaTree => {
|
|
|
5
5
|
}
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
|
+
|
|
9
|
+
const createGoTSMessage = goTree => {
|
|
10
|
+
return {
|
|
11
|
+
go: {
|
|
12
|
+
goDependencyTrees: goTree
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
8
17
|
module.exports = {
|
|
9
|
-
createJavaTSMessage
|
|
18
|
+
createJavaTSMessage,
|
|
19
|
+
createGoTSMessage
|
|
10
20
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const { getHttpClient } = require('../../utils/commonApi')
|
|
2
|
-
const { handleResponseErrors } = require('../../common/errorHandling')
|
|
3
2
|
const { APP_VERSION } = require('../../constants/constants')
|
|
4
3
|
|
|
5
4
|
const commonSendSnapShot = async (analysis, config) => {
|
|
@@ -9,19 +8,16 @@ const commonSendSnapShot = async (analysis, config) => {
|
|
|
9
8
|
snapshot: analysis
|
|
10
9
|
}
|
|
11
10
|
|
|
12
|
-
//console.log(JSON.stringify(analysis))
|
|
13
|
-
|
|
14
|
-
//console.log(JSON.stringify(requestBody))
|
|
15
11
|
const client = getHttpClient(config)
|
|
16
12
|
return client
|
|
17
13
|
.sendSnapshot(requestBody, config)
|
|
18
14
|
.then(res => {
|
|
19
15
|
if (res.statusCode === 201) {
|
|
20
|
-
console.log('
|
|
16
|
+
console.log('dependencies processed successfully')
|
|
21
17
|
return res.body
|
|
22
18
|
} else {
|
|
23
19
|
console.log(res.statusCode)
|
|
24
|
-
|
|
20
|
+
console.log('error processing dependencies')
|
|
25
21
|
}
|
|
26
22
|
})
|
|
27
23
|
.catch(err => {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const { createGoTSMessage } = require('../common/formatMessage')
|
|
2
|
+
const goReadDepFile = require('./goReadDepFile')
|
|
3
|
+
const goParseDeps = require('./goParseDeps')
|
|
4
|
+
|
|
5
|
+
const goAnalysis = (config, languageFiles) => {
|
|
6
|
+
try {
|
|
7
|
+
const rawGoDependencies = goReadDepFile.getGoDependencies(config)
|
|
8
|
+
const parsedGoDependencies = goParseDeps.parseGoDependencies(
|
|
9
|
+
rawGoDependencies
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
return createGoTSMessage(parsedGoDependencies)
|
|
13
|
+
} catch (e) {
|
|
14
|
+
console.log(e.message.toString())
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = {
|
|
19
|
+
goAnalysis
|
|
20
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
const crypto = require('crypto')
|
|
2
|
+
|
|
3
|
+
const parseGoDependencies = goDeps => {
|
|
4
|
+
return parseGo(goDeps)
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const parseGo = modGraphOutput => {
|
|
8
|
+
let splitLines = splitAllLinesIntoArray(modGraphOutput)
|
|
9
|
+
const directDepNames = getDirectDepNames(splitLines)
|
|
10
|
+
const uniqueTransitiveDepNames = getAllUniqueTransitiveDepNames(
|
|
11
|
+
splitLines,
|
|
12
|
+
directDepNames
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
let rootNodes = createRootNodes(splitLines)
|
|
16
|
+
|
|
17
|
+
createTransitiveDeps(uniqueTransitiveDepNames, splitLines, rootNodes)
|
|
18
|
+
|
|
19
|
+
return rootNodes
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const splitAllLinesIntoArray = modGraphOutput => {
|
|
23
|
+
return modGraphOutput.split(/\r\n|\r|\n/)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const getAllDepsOfADepAsEdge = (dep, deps) => {
|
|
27
|
+
let edges = {}
|
|
28
|
+
|
|
29
|
+
const depRows = deps.filter(line => {
|
|
30
|
+
return line.startsWith(dep)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
depRows.forEach(dep => {
|
|
34
|
+
const edgeName = dep.split(' ')[1]
|
|
35
|
+
edges[edgeName] = edgeName
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
return edges
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const getAllDepsOfADepAsName = (dep, deps) => {
|
|
42
|
+
let edges = []
|
|
43
|
+
|
|
44
|
+
const depRows = deps.filter(line => {
|
|
45
|
+
return line.startsWith(dep)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
depRows.forEach(dep => {
|
|
49
|
+
const edgeName = dep.split(' ')[1]
|
|
50
|
+
edges.push(edgeName)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
return edges
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const createRootNodes = deps => {
|
|
57
|
+
let rootDep = {}
|
|
58
|
+
const rootDeps = getRootDeps(deps)
|
|
59
|
+
|
|
60
|
+
const edges = rootDeps.map(dep => {
|
|
61
|
+
return dep.split(' ')[1]
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
rootDep[rootDeps[0].split(' ')[0]] = {}
|
|
65
|
+
|
|
66
|
+
edges.forEach(edge => {
|
|
67
|
+
const splitEdge = edge.split('@')
|
|
68
|
+
const splitGroupName = splitEdge[0].split('/')
|
|
69
|
+
const name = splitGroupName.pop()
|
|
70
|
+
const lastSlash = splitEdge[0].lastIndexOf('/')
|
|
71
|
+
let group = splitEdge[0].substring(0, lastSlash)
|
|
72
|
+
const hash = getHash(splitEdge[0])
|
|
73
|
+
|
|
74
|
+
group = checkGroupExists(group, name)
|
|
75
|
+
|
|
76
|
+
//get the edges of the root dependency
|
|
77
|
+
const edgesOfDep = getAllDepsOfADepAsEdge(edge, deps)
|
|
78
|
+
|
|
79
|
+
rootDep[rootDeps[0].split(' ')[0]][edge] = {
|
|
80
|
+
artifactID: name,
|
|
81
|
+
group: group,
|
|
82
|
+
version: splitEdge[1],
|
|
83
|
+
scope: '"compile',
|
|
84
|
+
type: 'direct',
|
|
85
|
+
hash: hash,
|
|
86
|
+
edges: edgesOfDep
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
return rootDep
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const getRootDeps = deps => {
|
|
93
|
+
const rootDeps = deps.filter(dep => {
|
|
94
|
+
const parentDep = dep.split(' ')[0]
|
|
95
|
+
if (parentDep.split('@v').length === 1) {
|
|
96
|
+
return dep
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
return rootDeps
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const getHash = library => {
|
|
103
|
+
let shaSum = crypto.createHash('sha1')
|
|
104
|
+
shaSum.update(library)
|
|
105
|
+
return shaSum.digest('hex')
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const getDirectDepNames = deps => {
|
|
109
|
+
const directDepNames = []
|
|
110
|
+
|
|
111
|
+
deps.forEach(dep => {
|
|
112
|
+
const parentDep = dep.split(' ')[0]
|
|
113
|
+
if (parentDep.split('@v').length === 1) {
|
|
114
|
+
dep.split(' ')[1] !== undefined
|
|
115
|
+
? directDepNames.push(dep.split(' ')[1])
|
|
116
|
+
: null
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
return directDepNames
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const getAllUniqueTransitiveDepNames = (deps, directDepNames) => {
|
|
123
|
+
let uniqueDeps = []
|
|
124
|
+
|
|
125
|
+
deps.forEach(dep => {
|
|
126
|
+
const parentDep = dep.split(' ')[0]
|
|
127
|
+
if (parentDep.split('@v').length !== 1) {
|
|
128
|
+
if (!directDepNames.includes(parentDep)) {
|
|
129
|
+
if (!uniqueDeps.includes(parentDep)) {
|
|
130
|
+
parentDep.length > 1 ? uniqueDeps.push(parentDep) : null
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
})
|
|
135
|
+
return uniqueDeps
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const checkGroupExists = (group, name) => {
|
|
139
|
+
if (group === null || group === '') {
|
|
140
|
+
return name
|
|
141
|
+
}
|
|
142
|
+
return group
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const createTransitiveDeps = (transitiveDeps, splitLines, rootNodes) => {
|
|
146
|
+
transitiveDeps.forEach(dep => {
|
|
147
|
+
//create transitive dep
|
|
148
|
+
const splitEdge = dep.split('@')
|
|
149
|
+
const splitGroupName = splitEdge[0].split('/')
|
|
150
|
+
const name = splitGroupName.pop()
|
|
151
|
+
const lastSlash = splitEdge[0].lastIndexOf('/')
|
|
152
|
+
let group = splitEdge[0].substring(0, lastSlash)
|
|
153
|
+
const hash = getHash(splitEdge[0])
|
|
154
|
+
|
|
155
|
+
group = checkGroupExists(group, name)
|
|
156
|
+
|
|
157
|
+
const transitiveDep = {
|
|
158
|
+
artifactID: name,
|
|
159
|
+
group: group,
|
|
160
|
+
version: splitEdge[1],
|
|
161
|
+
scope: 'compile',
|
|
162
|
+
type: 'transitive',
|
|
163
|
+
hash: hash,
|
|
164
|
+
edges: {}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
//add edges to transitiveDep
|
|
168
|
+
const edges = getAllDepsOfADepAsEdge(dep, splitLines)
|
|
169
|
+
transitiveDep.edges = edges
|
|
170
|
+
|
|
171
|
+
//add all edges as a transitive dependency to rootNodes
|
|
172
|
+
const edgesAsName = getAllDepsOfADepAsName(dep, splitLines)
|
|
173
|
+
|
|
174
|
+
edgesAsName.forEach(dep => {
|
|
175
|
+
const splitEdge = dep.split('@')
|
|
176
|
+
const splitGroupName = splitEdge[0].split('/')
|
|
177
|
+
const name = splitGroupName.pop()
|
|
178
|
+
const lastSlash = splitEdge[0].lastIndexOf('/')
|
|
179
|
+
let group = splitEdge[0].substring(0, lastSlash)
|
|
180
|
+
const hash = getHash(splitEdge[0])
|
|
181
|
+
|
|
182
|
+
group = checkGroupExists(group, name)
|
|
183
|
+
|
|
184
|
+
const transitiveDep = {
|
|
185
|
+
artifactID: name,
|
|
186
|
+
group: group,
|
|
187
|
+
version: splitEdge[1],
|
|
188
|
+
scope: 'compile',
|
|
189
|
+
type: 'transitive',
|
|
190
|
+
hash: hash,
|
|
191
|
+
edges: {}
|
|
192
|
+
}
|
|
193
|
+
rootNodes[Object.keys(rootNodes)[0]][dep] = transitiveDep
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
//add transitive dependency to rootNodes
|
|
197
|
+
rootNodes[Object.keys(rootNodes)[0]][dep] = transitiveDep
|
|
198
|
+
})
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
module.exports = {
|
|
202
|
+
parseGoDependencies
|
|
203
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const child_process = require('child_process')
|
|
2
|
+
const i18n = require('i18n')
|
|
3
|
+
|
|
4
|
+
const getGoDependencies = config => {
|
|
5
|
+
let cmdStdout
|
|
6
|
+
let cwd = config.projectPath
|
|
7
|
+
? config.projectPath.replace('go.mod', '')
|
|
8
|
+
: process.cwd()
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
// A sample of this output can be found
|
|
12
|
+
// in the go test folder data/goModGraphResults.text
|
|
13
|
+
cmdStdout = child_process.execSync('go mod graph', { cwd })
|
|
14
|
+
|
|
15
|
+
return cmdStdout.toString()
|
|
16
|
+
} catch (err) {
|
|
17
|
+
if (err.message === 'spawnSync /bin/sh ENOENT') {
|
|
18
|
+
err.message =
|
|
19
|
+
'\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.'
|
|
20
|
+
}
|
|
21
|
+
console.log(
|
|
22
|
+
i18n.__('goReadProjectFile', cwd, `${err.message ? err.message : ''}`)
|
|
23
|
+
)
|
|
24
|
+
// throw new Error(
|
|
25
|
+
// i18n.__('goReadProjectFile', cwd, `${err.message ? err.message : ''}`)
|
|
26
|
+
// )
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
module.exports = {
|
|
31
|
+
getGoDependencies
|
|
32
|
+
}
|
|
@@ -24,7 +24,7 @@ const determineProjectTypeAndCwd = (files, projectPath) => {
|
|
|
24
24
|
return projectData
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
const buildMaven =
|
|
27
|
+
const buildMaven = (config, projectData, timeout) => {
|
|
28
28
|
let cmdStdout
|
|
29
29
|
let mvn_settings = ''
|
|
30
30
|
|
|
@@ -40,23 +40,11 @@ const buildMaven = async (config, projectData, timeout) => {
|
|
|
40
40
|
timeout
|
|
41
41
|
}
|
|
42
42
|
)
|
|
43
|
-
// output.mvnDependancyTreeOutput = cmdStdout.toString()
|
|
44
|
-
// console.log(cmdStdout.toString())
|
|
45
43
|
return cmdStdout.toString()
|
|
46
44
|
} catch (err) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
timeout
|
|
51
|
-
})
|
|
52
|
-
throw new Error(
|
|
53
|
-
i18n.__('mavenDependencyTreeNonZero', projectData.cwd, `${err.message}`)
|
|
54
|
-
)
|
|
55
|
-
} catch (mvnErr) {
|
|
56
|
-
throw new Error(
|
|
57
|
-
i18n.__('mavenNotInstalledError', projectData.cwd, `${mvnErr.message}`)
|
|
58
|
-
)
|
|
59
|
-
}
|
|
45
|
+
throw new Error(
|
|
46
|
+
i18n.__('mavenDependencyTreeNonZero', projectData.cwd, `${err.message}`)
|
|
47
|
+
)
|
|
60
48
|
}
|
|
61
49
|
}
|
|
62
50
|
|
|
@@ -107,7 +95,7 @@ const buildGradle = (config, projectData, timeout) => {
|
|
|
107
95
|
}
|
|
108
96
|
)
|
|
109
97
|
}
|
|
110
|
-
output
|
|
98
|
+
output = cmdStdout.toString()
|
|
111
99
|
return output
|
|
112
100
|
} catch (err) {
|
|
113
101
|
if (
|
|
@@ -129,7 +117,7 @@ const buildGradle = (config, projectData, timeout) => {
|
|
|
129
117
|
}
|
|
130
118
|
}
|
|
131
119
|
|
|
132
|
-
const getJavaBuildDeps =
|
|
120
|
+
const getJavaBuildDeps = (config, files) => {
|
|
133
121
|
const timeout = 960000
|
|
134
122
|
let output = {
|
|
135
123
|
mvnDependancyTreeOutput: undefined,
|
|
@@ -139,18 +127,14 @@ const getJavaBuildDeps = async (config, files) => {
|
|
|
139
127
|
try {
|
|
140
128
|
const projectData = determineProjectTypeAndCwd(files, config.projectPath)
|
|
141
129
|
if (projectData.projectType === MAVEN) {
|
|
142
|
-
output.mvnDependancyTreeOutput =
|
|
143
|
-
config,
|
|
144
|
-
projectData,
|
|
145
|
-
timeout
|
|
146
|
-
)
|
|
130
|
+
output.mvnDependancyTreeOutput = buildMaven(config, projectData, timeout)
|
|
147
131
|
} else if (projectData.projectType === GRADLE) {
|
|
148
132
|
output.mvnDependancyTreeOutput = buildGradle(config, projectData, timeout)
|
|
149
133
|
}
|
|
150
134
|
output.projectType = projectData.projectType
|
|
151
135
|
return output
|
|
152
136
|
} catch (err) {
|
|
153
|
-
|
|
137
|
+
console.log(err.message.toString())
|
|
154
138
|
}
|
|
155
139
|
}
|
|
156
140
|
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
const
|
|
1
|
+
const analysis = require('./analysis')
|
|
2
2
|
const { parseBuildDeps } = require('./javaBuildDepsParser')
|
|
3
3
|
const { createJavaTSMessage } = require('../common/formatMessage')
|
|
4
4
|
|
|
5
|
-
const javaAnalysis =
|
|
5
|
+
const javaAnalysis = (config, languageFiles) => {
|
|
6
6
|
languageFiles.java.forEach(file => {
|
|
7
7
|
file.replace('build.gradle.kts', 'build.gradle')
|
|
8
8
|
})
|
|
9
9
|
|
|
10
|
-
const javaDeps =
|
|
10
|
+
const javaDeps = buildJavaTree(config, languageFiles.java)
|
|
11
11
|
return createJavaTSMessage(javaDeps)
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
const buildJavaTree =
|
|
15
|
-
const javaBuildDeps =
|
|
14
|
+
const buildJavaTree = (config, files) => {
|
|
15
|
+
const javaBuildDeps = analysis.getJavaBuildDeps(config, files)
|
|
16
16
|
return parseBuildDeps(config, javaBuildDeps)
|
|
17
17
|
}
|
|
18
18
|
|