mirror of
https://github.com/SAP/jenkins-library.git
synced 2025-01-18 05:18:24 +02:00
Initial checkin of new whitesource step
This commit is contained in:
parent
9ebce31fe6
commit
14700ba210
@ -0,0 +1,41 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>${reportTitle}</title>
|
||||
<style type="text/css">${style}</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>${reportTitle}</h1>
|
||||
<h2>
|
||||
<span>
|
||||
<i>WhiteSource product name: ${whitesourceProductName}</i><br />
|
||||
<i>Filtered project names: ${whitesourceProjectNames?:''}</i>
|
||||
</span>
|
||||
</h2>
|
||||
<div>
|
||||
<h3> total number of vulnerabilities: ${totalVulnerabilities}<br />
|
||||
total number of high/critical vulnerabilities with CVSS score >= 7.0: ${totalSevereVulnerabilities}
|
||||
</h3>
|
||||
</div>
|
||||
<p>Snapshot taken:${now} GMT</p>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Entry #</th>
|
||||
<th>Date</th>
|
||||
<th>CVE</th>
|
||||
<th>CVSS Score</th>
|
||||
<th>CVSS Version</th>
|
||||
<th>Project</th>
|
||||
<th>Library file name</th>
|
||||
<th>Library group ID</th>
|
||||
<th>Library artifact ID</th>
|
||||
<th>Library version</th>
|
||||
<th>Description</th>
|
||||
<th>Top fix</th>
|
||||
</tr>
|
||||
|
||||
${vulnerabilityTable}
|
||||
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
@ -254,6 +254,67 @@ steps:
|
||||
- 'tests'
|
||||
npmExecute:
|
||||
dockerImage: 'node:8-stretch'
|
||||
whitesourceExecuteScan:
|
||||
buildDescriptorExcludeList: []
|
||||
parallelLimit: 0
|
||||
licensingVulnerabilities: true
|
||||
securityVulnerabilities: false
|
||||
reporting: true
|
||||
vulnerabilityReportFileName: 'piper_whitesource_vulnerability_report'
|
||||
vulnerabilityReportTitle: 'Whitesource Security Vulnerability Report'
|
||||
projectNames: []
|
||||
jreDownloadUrl: 'https://github.com/SAP/SapMachine/releases/download/sapmachine-11.0.2/sapmachine-jre-11.0.2_linux-x64_bin.tar.gz'
|
||||
whitesourceAccessor: 'com.sap.piper.internal.integration.InternalWhitesource'
|
||||
mta:
|
||||
stashContent:
|
||||
- 'buildDescriptor'
|
||||
- 'opensourceConfiguration'
|
||||
maven:
|
||||
buildDescriptorFile: './pom.xml'
|
||||
dockerImage: 'docker.wdf.sap.corp:50000/piper/maven'
|
||||
dockerWorkspace: '/home/piper'
|
||||
agentFileName: 'wss-unified-agent.jar'
|
||||
agentDownloadUrl: 'https://github.com/whitesource/unified-agent-distribution/raw/master/standAlone/${config.agentFileName}'
|
||||
agentParameters: ''
|
||||
configFilePath: './wss-unified-agent.config'
|
||||
stashContent:
|
||||
- 'buildDescriptor'
|
||||
- 'opensourceConfiguration'
|
||||
npm:
|
||||
buildDescriptorFile: './package.json'
|
||||
dockerImage: 'docker.wdf.sap.corp:50000/piper/node'
|
||||
dockerWorkspace: '/home/piper'
|
||||
agentFileName: 'wss-unified-agent.jar'
|
||||
agentDownloadUrl: 'https://github.com/whitesource/unified-agent-distribution/raw/master/standAlone/${config.agentFileName}'
|
||||
agentParameters: ''
|
||||
configFilePath: './wss-unified-agent.config'
|
||||
stashContent:
|
||||
- 'buildDescriptor'
|
||||
- 'opensourceConfiguration'
|
||||
pip:
|
||||
buildDescriptorFile: './setup.py'
|
||||
dockerImage: 'docker.wdf.sap.corp:50000/piper/node'
|
||||
dockerWorkspace: '/home/piper'
|
||||
agentFileName: 'wss-unified-agent.jar'
|
||||
agentDownloadUrl: 'https://github.com/whitesource/unified-agent-distribution/raw/master/standAlone/${config.agentFileName}'
|
||||
agentParameters: ''
|
||||
configFilePath: './wss-unified-agent.config'
|
||||
stashContent:
|
||||
- 'buildDescriptor'
|
||||
- 'opensourceConfiguration'
|
||||
sbt:
|
||||
buildDescriptorFile: './build.sbt'
|
||||
dockerImage: 'docker.wdf.sap.corp:50000/piper/sbt'
|
||||
dockerWorkspace: '/home/piper'
|
||||
agentFileName: 'wss-unified-agent.jar'
|
||||
agentDownloadUrl: 'https://github.com/whitesource/unified-agent-distribution/raw/master/standAlone/${config.agentFileName}'
|
||||
agentParameters: ''
|
||||
configFilePath: './wss-unified-agent.config'
|
||||
stashContent:
|
||||
- 'buildDescriptor'
|
||||
- 'opensourceConfiguration'
|
||||
verbose: false
|
||||
timeout: 0
|
||||
pipelineRestartSteps:
|
||||
sendMail: true
|
||||
timeoutInSeconds: 900
|
||||
|
@ -1,8 +1,14 @@
|
||||
package com.sap.piper
|
||||
|
||||
import com.cloudbees.groovy.cps.NonCPS
|
||||
import groovy.json.JsonSlurperClassic
|
||||
|
||||
@NonCPS
|
||||
String getPrettyJsonString(object) {
|
||||
return groovy.json.JsonOutput.prettyPrint(groovy.json.JsonOutput.toJson(object))
|
||||
}
|
||||
|
||||
@NonCPS
|
||||
def parseJsonSerializable(text) {
|
||||
return new JsonSlurperClassic().parseText(text)
|
||||
}
|
||||
|
255
src/com/sap/piper/WhitesourceConfigurationHelper.groovy
Normal file
255
src/com/sap/piper/WhitesourceConfigurationHelper.groovy
Normal file
@ -0,0 +1,255 @@
|
||||
package com.sap.piper
|
||||
|
||||
import com.cloudbees.groovy.cps.NonCPS
|
||||
|
||||
import java.security.MessageDigest
|
||||
|
||||
class WhitesourceConfigurationHelper implements Serializable {
|
||||
|
||||
private static def SCALA_CONTENT_KEY = "@__content"
|
||||
|
||||
static def extendUAConfigurationFile(script, Utils utils, config, path) {
|
||||
def mapping = []
|
||||
def parsingClosure = { fileReadPath -> return script.readProperties (file: fileReadPath) }
|
||||
def serializationClosure = { configuration -> serializeUAConfig(configuration) }
|
||||
def inputFile = config.configFilePath.replaceFirst('\\./', '')
|
||||
def suffix = MessageDigest.getInstance("MD5").digest(config.configFilePath.bytes).encodeHex().toString()
|
||||
def targetFile = "${inputFile}.${suffix}"
|
||||
if(config.productName.startsWith('DIST - ')) {
|
||||
mapping += [
|
||||
[name: 'checkPolicies', value: false],
|
||||
[name: 'forceCheckAllDependencies', value: false]
|
||||
]
|
||||
} else if(config.productName.startsWith('SHC - ')) {
|
||||
mapping += [
|
||||
[name: 'checkPolicies', value: true],
|
||||
[name: 'forceCheckAllDependencies', value: true]
|
||||
]
|
||||
}
|
||||
if(config.verbose)
|
||||
mapping += [name: 'log.level', value: 'debug']
|
||||
|
||||
mapping += [
|
||||
[name: 'apiKey', value: config.orgToken, warnIfPresent: true],
|
||||
[name: 'productName', value: config.productName],
|
||||
[name: 'productVersion', value: config.productVersion],
|
||||
[name: 'projectName', value: config.projectName],
|
||||
[name: 'projectVersion', value: config.productVersion],
|
||||
[name: 'productToken', value: config.productToken, omitIfPresent: 'projectToken'],
|
||||
[name: 'userKey', value: config.userKey, warnIfPresent: true],
|
||||
[name: 'forceUpdate', value: true],
|
||||
[name: 'offline', value: false],
|
||||
[name: 'ignoreSourceFiles', value: true],
|
||||
[name: 'resolveAllDependencies', value: false]
|
||||
]
|
||||
switch (config.scanType) {
|
||||
case 'maven':
|
||||
mapping += [
|
||||
|
||||
]
|
||||
break
|
||||
case 'npm':
|
||||
mapping += [
|
||||
|
||||
]
|
||||
break
|
||||
case 'pip':
|
||||
mapping += [
|
||||
[name: 'python.resolveDependencies', value: true],
|
||||
[name: 'python.ignoreSourceFiles', value: true],
|
||||
[name: 'python.ignorePipInstallErrors', value: false],
|
||||
[name: 'python.installVirtualenv', value: true],
|
||||
[name: 'python.resolveHierarchyTree', value: true],
|
||||
[name: 'python.requirementsFileIncludes', value: 'requirements.txt'],
|
||||
[name: 'python.resolveSetupPyFiles', value: true],
|
||||
[name: 'python.runPipenvPreStep', value: true],
|
||||
[name: 'python.pipenvDevDependencies', value: true],
|
||||
[name: 'python.IgnorePipenvInstallErrors', value: false],
|
||||
[name: 'includes', value: '**/*.py **/*.txt'],
|
||||
[name: 'excludes', value: '**/*sources.jar **/*javadoc.jar'],
|
||||
[name: 'case.sensitive.glob', value: false],
|
||||
[name: 'followSymbolicLinks', value: true]
|
||||
]
|
||||
break
|
||||
case 'sbt':
|
||||
mapping += [
|
||||
|
||||
]
|
||||
break
|
||||
}
|
||||
|
||||
rewriteConfiguration(script, config, utils, mapping, suffix, path, inputFile, targetFile, parsingClosure, serializationClosure)
|
||||
}
|
||||
|
||||
static def extendConfigurationFile(script, Utils utils, config, path) {
|
||||
def mapping = [:]
|
||||
def parsingClosure
|
||||
def serializationClosure
|
||||
def inputFile = config.configFilePath.replaceFirst('\\./', '')
|
||||
def suffix = MessageDigest.getInstance("MD5").digest(config.configFilePath.bytes).encodeHex().toString()
|
||||
def targetFile = "${inputFile}.${suffix}"
|
||||
switch (config.scanType) {
|
||||
case 'unifiedAgent':
|
||||
case 'fileAgent':
|
||||
mapping = [
|
||||
[name: 'apiKey', value: config.orgToken, warnIfPresent: true],
|
||||
[name: 'productName', value: config.productName],
|
||||
[name: 'productToken', value: config.productToken, omitIfPresent: 'projectToken'],
|
||||
[name: 'userKey', value: config.userKey, warnIfPresent: true]
|
||||
]
|
||||
parsingClosure = { fileReadPath -> return script.readProperties (file: fileReadPath) }
|
||||
serializationClosure = { Properties configuration -> new StringWriter().with{ w -> configuration.store(w, null); w }.toString() }
|
||||
break
|
||||
case 'npm':
|
||||
mapping = [
|
||||
[name: 'apiKey', value: config.orgToken, warnIfPresent: true],
|
||||
[name: 'productName', value: config.productName],
|
||||
[name: 'productToken', value: config.productToken, omitIfPresent: 'projectToken'],
|
||||
[name: 'userKey', value: config.userKey, warnIfPresent: true]
|
||||
]
|
||||
parsingClosure = { fileReadPath -> return script.readJSON (file: fileReadPath) }
|
||||
serializationClosure = { configuration -> return utils.jsonToString(configuration) }
|
||||
break
|
||||
case 'pip':
|
||||
mapping = [
|
||||
[name: "'org_token'", value: "\'${config.orgToken}\'", warnIfPresent: true],
|
||||
[name: "'product_name'", value: "\'${config.productName}\'"],
|
||||
[name: "'product_token'", value: "\'${config.productToken}\'"],
|
||||
[name: "'user_key'", value: "\'${config.userKey}\'", warnIfPresent: true]
|
||||
]
|
||||
parsingClosure = { fileReadPath -> return readPythonConfig (script, fileReadPath) }
|
||||
serializationClosure = { configuration -> serializePythonConfig(configuration) }
|
||||
targetFile = "${inputFile}.${suffix}.py"
|
||||
break
|
||||
case 'sbt':
|
||||
mapping = [
|
||||
[name: "whitesourceOrgToken in ThisBuild", value: "\"${config.orgToken}\"", warnIfPresent: true],
|
||||
[name: "whitesourceProduct in ThisBuild", value: "\"${config.productName}\""],
|
||||
[name: "whitesourceServiceUrl in ThisBuild", value: "uri(\"${config.agentUrl}\")"]
|
||||
// actually not supported [name: "whitesourceUserKey in ThisBuild", value: config.userKey]
|
||||
]
|
||||
parsingClosure = { fileReadPath -> return readScalaConfig (script, mapping, fileReadPath) }
|
||||
serializationClosure = { configuration -> serializeScalaConfig (configuration) }
|
||||
targetFile = inputFile
|
||||
break
|
||||
}
|
||||
|
||||
rewriteConfiguration(script, config, utils, mapping, suffix, path, inputFile, targetFile, parsingClosure, serializationClosure)
|
||||
}
|
||||
|
||||
static private def rewriteConfiguration(script, config, utils, mapping, suffix, path, inputFile, targetFile, parsingClosure, serializationClosure) {
|
||||
def inputFilePath = "${path}${inputFile}"
|
||||
def outputFilePath = "${path}${targetFile}"
|
||||
def moduleSpecificFile = parsingClosure(inputFilePath)
|
||||
if (!moduleSpecificFile)
|
||||
moduleSpecificFile = parsingClosure(config.configFilePath)
|
||||
if (!moduleSpecificFile)
|
||||
moduleSpecificFile = [:]
|
||||
|
||||
mapping.each {
|
||||
entry ->
|
||||
//if (entry.warnIfPresent && moduleSpecificFile[entry.name])
|
||||
//Notify.warning(script, "Obsolete configuration ${entry.name} detected, please omit its use and rely on configuration via Piper.", 'WhitesourceConfigurationHelper')
|
||||
def dependentValue = entry.omitIfPresent ? moduleSpecificFile[entry.omitIfPresent] : null
|
||||
if ((entry.omitIfPresent && !dependentValue || !entry.omitIfPresent) && entry.value && entry.value != 'null' && entry.value != '')
|
||||
moduleSpecificFile[entry.name] = entry.value.toString()
|
||||
}
|
||||
|
||||
def output = serializationClosure(moduleSpecificFile)
|
||||
|
||||
if(config.verbose)
|
||||
script.echo "Writing config file ${outputFilePath} with content:\n${output}"
|
||||
script.writeFile file: outputFilePath, text: output
|
||||
if(config.stashContent && config.stashContent.size() > 0) {
|
||||
def stashName = "modified whitesource config ${suffix}".toString()
|
||||
utils.stashWithMessage (
|
||||
stashName,
|
||||
"Stashing modified Whitesource configuration",
|
||||
outputFilePath.replaceFirst('\\./', '')
|
||||
)
|
||||
config.stashContent += [stashName]
|
||||
}
|
||||
config.configFilePath = outputFilePath
|
||||
}
|
||||
|
||||
static private def readPythonConfig(script, filePath) {
|
||||
def contents = script.readFile file: filePath
|
||||
def lines = contents.split('\n')
|
||||
def resultMap = [:]
|
||||
lines.each {
|
||||
line ->
|
||||
List parts = line?.replaceAll(',$', '')?.split(':')
|
||||
def key = parts[0]?.trim()
|
||||
parts.removeAt(0)
|
||||
resultMap[key] = parts.size() > 0 ? (parts as String[]).join(':').trim() : null
|
||||
}
|
||||
return resultMap
|
||||
}
|
||||
|
||||
static private def serializePythonConfig(configuration) {
|
||||
StringBuilder result = new StringBuilder()
|
||||
configuration.each {
|
||||
entry ->
|
||||
if(entry.key != '}')
|
||||
result.append(entry.value ? ' ' : '').append(entry.key).append(entry.value ? ': ' : '').append(entry.value ?: '').append(entry.value ? ',' : '').append('\r\n')
|
||||
}
|
||||
return result.toString().replaceAll(',$', '\r\n}')
|
||||
}
|
||||
|
||||
static private def readScalaConfig(script, mapping, filePath) {
|
||||
def contents = script.readFile file: filePath
|
||||
def lines = contents.split('\n')
|
||||
def resultMap = [:]
|
||||
resultMap[SCALA_CONTENT_KEY] = []
|
||||
def keys = mapping.collect( { it.name } )
|
||||
lines.each {
|
||||
line ->
|
||||
def parts = line?.split(':=').toList()
|
||||
def key = parts[0]?.trim()
|
||||
if (keys.contains(key)) {
|
||||
resultMap[key] = parts[1]?.trim()
|
||||
} else if (line != null) {
|
||||
resultMap[SCALA_CONTENT_KEY].add(line)
|
||||
}
|
||||
}
|
||||
return resultMap
|
||||
}
|
||||
|
||||
static private def serializeScalaConfig(configuration) {
|
||||
StringBuilder result = new StringBuilder()
|
||||
|
||||
// write the general content
|
||||
configuration[SCALA_CONTENT_KEY].each {
|
||||
line ->
|
||||
result.append(line)
|
||||
result.append('\r\n')
|
||||
}
|
||||
|
||||
// write the mappings
|
||||
def confKeys = configuration.keySet()
|
||||
confKeys.remove(SCALA_CONTENT_KEY)
|
||||
|
||||
confKeys.each {
|
||||
key ->
|
||||
def value = configuration[key]
|
||||
result.append(key)
|
||||
if (value != null) {
|
||||
result.append(' := ').append(value)
|
||||
}
|
||||
result.append('\r\n')
|
||||
}
|
||||
|
||||
return result.toString()
|
||||
}
|
||||
|
||||
@NonCPS
|
||||
static private def serializeUAConfig(configuration) {
|
||||
Properties p = new Properties()
|
||||
configuration.each {
|
||||
entry ->
|
||||
p.setProperty(entry.key, entry.value)
|
||||
}
|
||||
|
||||
new StringWriter().with{ w -> p.store(w, null); w }.toString()
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
package com.sap.piper.integration
|
||||
|
||||
import com.cloudbees.groovy.cps.NonCPS
|
||||
import com.sap.piper.JsonUtils
|
||||
import com.sap.piper.Utils
|
||||
|
||||
class WhitesourceOrgAdminRepository implements Serializable {
|
||||
|
||||
final Script script
|
||||
final internalWhitesource
|
||||
final Map config
|
||||
|
||||
WhitesourceOrgAdminRepository(Script script, Map config) {
|
||||
this.script = script
|
||||
this.config = config
|
||||
if(!this.config.serviceUrl && !this.config.whitesourceAccessor)
|
||||
script.error "Parameter 'serviceUrl' must be provided as part of the configuration."
|
||||
if(this.config.whitesourceAccessor instanceof String) {
|
||||
def clazz = this.class.classLoader.loadClass(this.config.whitesourceAccessor)
|
||||
this.internalWhitesource = clazz?.newInstance(this.script, this.config)
|
||||
}
|
||||
}
|
||||
|
||||
def fetchProductMetaInfo() {
|
||||
def requestBody = [
|
||||
requestType: "getOrganizationProductVitals",
|
||||
orgToken: config.orgToken
|
||||
]
|
||||
def response = internalWhitesource ? internalWhitesource.httpWhitesource(requestBody) : httpWhitesource(requestBody)
|
||||
def parsedResponse = new JsonUtils().parseJsonSerializable(response.content)
|
||||
|
||||
findProductMeta(parsedResponse)
|
||||
}
|
||||
|
||||
def findProductMeta(parsedResponse) {
|
||||
def foundMetaProduct = null
|
||||
for (product in parsedResponse.productVitals) {
|
||||
if (product.name == config.productName) {
|
||||
foundMetaProduct = product
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundMetaProduct)
|
||||
script.error "[WhiteSource] Could not fetch/find requested product '${config.productName}'"
|
||||
|
||||
return foundMetaProduct
|
||||
}
|
||||
|
||||
|
||||
|
||||
@NonCPS
|
||||
protected def httpWhitesource(requestBody) {
|
||||
script.withCredentials ([script.string(
|
||||
credentialsId: config.orgAdminUserTokenCredentialsId,
|
||||
variable: 'adminUserKey'
|
||||
)]) {
|
||||
requestBody["userKey"] = adminUserKey
|
||||
def serializedBody = new JsonUtils().getPrettyJsonString(requestBody)
|
||||
def params = [
|
||||
url : config.serviceUrl,
|
||||
httpMode : 'POST',
|
||||
acceptType : 'APPLICATION_JSON',
|
||||
contentType: 'APPLICATION_JSON',
|
||||
requestBody: serializedBody,
|
||||
quiet : !config.verbose,
|
||||
timeout : config.timeout
|
||||
]
|
||||
|
||||
if (script.env.HTTP_PROXY && !config.serviceUrl.matches('http(s)*://.*\\.sap\\.corp.*'))
|
||||
params["httpProxy"] = script.env.HTTP_PROXY
|
||||
|
||||
if (config.verbose)
|
||||
script.echo "Sending http request with parameters ${params}"
|
||||
|
||||
def response = script.httpRequest(params)
|
||||
|
||||
if (config.verbose)
|
||||
script.echo "Received response ${reponse}"
|
||||
|
||||
return response
|
||||
}
|
||||
}
|
||||
}
|
252
src/com/sap/piper/integration/WhitesourceRepository.groovy
Normal file
252
src/com/sap/piper/integration/WhitesourceRepository.groovy
Normal file
@ -0,0 +1,252 @@
|
||||
package com.sap.piper.integration
|
||||
|
||||
import com.cloudbees.groovy.cps.NonCPS
|
||||
import com.sap.piper.JsonUtils
|
||||
import com.sap.piper.Utils
|
||||
|
||||
class WhitesourceRepository implements Serializable {
|
||||
|
||||
final Script script
|
||||
final Map config
|
||||
|
||||
WhitesourceRepository(Script script, Map config) {
|
||||
this.script = script
|
||||
this.config = config
|
||||
|
||||
if(!config.serviceUrl)
|
||||
script.error "Parameter 'serviceUrl' must be provided as part of the configuration."
|
||||
}
|
||||
|
||||
List fetchVulnerabilities(whitesourceProjectsMetaInformation) {
|
||||
def fetchedVulnerabilities = []
|
||||
if (config.projectNames) {
|
||||
for (int i = 0; i < whitesourceProjectsMetaInformation.size(); i++) {
|
||||
def metaInfo = whitesourceProjectsMetaInformation[i]
|
||||
|
||||
def requestBody = [
|
||||
requestType : "getProjectAlertsByType",
|
||||
alertType : "SECURITY_VULNERABILITY",
|
||||
projectToken: metaInfo.token
|
||||
]
|
||||
|
||||
def response = fetchWhitesourceResource(requestBody)
|
||||
fetchedVulnerabilities.addAll(response.alerts)
|
||||
}
|
||||
} else {
|
||||
def requestBody = [
|
||||
requestType : "getProductAlertsByType",
|
||||
alertType : "SECURITY_VULNERABILITY",
|
||||
productToken: config.productToken,
|
||||
]
|
||||
|
||||
def response = fetchWhitesourceResource(requestBody)
|
||||
fetchedVulnerabilities.addAll(response.alerts)
|
||||
}
|
||||
|
||||
sortVulnerabilitiesByScore(fetchedVulnerabilities)
|
||||
|
||||
return fetchedVulnerabilities
|
||||
}
|
||||
|
||||
List fetchLibraries(whitesourceProjectsMetaInformation) {
|
||||
def fetchedLibraries = []
|
||||
if (config.projectNames) {
|
||||
for (int i = 0; i < whitesourceProjectsMetaInformation.size(); i++) {
|
||||
def metaInfo = whitesourceProjectsMetaInformation[i]
|
||||
def requestBody = [
|
||||
requestType : "getProjectLicenses",
|
||||
projectToken: metaInfo.token
|
||||
]
|
||||
|
||||
def response = fetchWhitesourceResource(requestBody)
|
||||
fetchedLibraries.addAll(response.libraries)
|
||||
}
|
||||
} else {
|
||||
def requestBody = [
|
||||
requestType : "getProductLicenses",
|
||||
productToken: config.productToken
|
||||
]
|
||||
|
||||
def response = fetchWhitesourceResource(requestBody)
|
||||
fetchedLibraries.addAll(response.libraries)
|
||||
}
|
||||
|
||||
sortLibrariesAlphabeticallyGAV(fetchedLibraries)
|
||||
|
||||
return listUniqueEntries(fetchedLibraries)
|
||||
}
|
||||
|
||||
@NonCPS
|
||||
def listUniqueEntries(Collection list) {
|
||||
return list.unique()
|
||||
}
|
||||
|
||||
|
||||
protected def fetchWhitesourceResource(Map requestBody) {
|
||||
final def response = httpWhitesource(requestBody)
|
||||
def parsedResponse = new JsonUtils().parseJsonSerializable(response.content)
|
||||
|
||||
if(parsedResponse?.errorCode){
|
||||
script.error "[WhiteSource] Request failed with error message '${parsedResponse.errorMessage}' (${parsedResponse.errorCode})."
|
||||
}
|
||||
|
||||
return parsedResponse
|
||||
}
|
||||
|
||||
@NonCPS
|
||||
void sortLibrariesAlphabeticallyGAV(List libraries) {
|
||||
script.echo "found a total of ${libraries.size()} dependencies (direct and indirect)"
|
||||
libraries.sort { o1, o2 ->
|
||||
String groupID1 = o1.groupId
|
||||
String groupID2 = o2.groupId
|
||||
def comparisionResult = groupID1 <=> groupID2;
|
||||
|
||||
if (comparisionResult != 0) {
|
||||
comparisionResult
|
||||
} else {
|
||||
String artifactID1 = o1.artifactId
|
||||
String artifactID2 = o2.artifactId
|
||||
|
||||
artifactID1 <=> artifactID2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NonCPS
|
||||
void sortVulnerabilitiesByScore(List vulnerabilities) {
|
||||
script.echo "${vulnerabilities.size() > 0 ? 'WARNING: ' : ''}found a total of ${vulnerabilities.size()} vulnerabilities"
|
||||
vulnerabilities.sort { o1, o2 ->
|
||||
def cvss3score1 = o1.vulnerability.cvss3_score != 0 ? o1.vulnerability.cvss3_score : o1.vulnerability.score
|
||||
def cvss3score2 = o2.vulnerability.cvss3_score != 0 ? o2.vulnerability.cvss3_score : o2.vulnerability.score
|
||||
|
||||
def comparisionResult = cvss3score1 <=> cvss3score2
|
||||
|
||||
if (comparisionResult != 0) {
|
||||
-comparisionResult
|
||||
} else {
|
||||
def score1 = o1.vulnerability.score
|
||||
def score2 = o2.vulnerability.score
|
||||
|
||||
-(score1 <=> score2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List fetchProjectsMetaInfo() {
|
||||
def projectsMetaInfo = []
|
||||
if(config.projectNames){
|
||||
def requestBody = [
|
||||
requestType: "getProductProjectVitals",
|
||||
productToken: config.productToken
|
||||
]
|
||||
def response = fetchWhitesourceResource(requestBody)
|
||||
|
||||
if(response?.projectVitals) {
|
||||
projectsMetaInfo.addAll(findProjectsMeta(response.projectVitals))
|
||||
} else {
|
||||
script.error "[WhiteSource] Could not fetch any projects for product '${config.productName}' from backend, response was ${response}"
|
||||
}
|
||||
}
|
||||
return projectsMetaInfo
|
||||
}
|
||||
|
||||
List findProjectsMeta(projectVitals) {
|
||||
def matchedProjects = []
|
||||
for (int i = 0; i < config.projectNames?.size(); i++) {
|
||||
def requestedProjectName = config.projectNames[i].trim()
|
||||
def matchedProjectInfo = null
|
||||
|
||||
for (int j = 0; j < projectVitals.size(); j++) {
|
||||
def projectResponse = projectVitals[j]
|
||||
if (projectResponse.name == requestedProjectName) {
|
||||
matchedProjectInfo = projectResponse
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (matchedProjectInfo != null) {
|
||||
matchedProjects.add(matchedProjectInfo)
|
||||
} else {
|
||||
script.error "[WhiteSource] Could not fetch/find requested project '${requestedProjectName}' for product '${config.productName}'"
|
||||
}
|
||||
}
|
||||
|
||||
return matchedProjects
|
||||
}
|
||||
|
||||
void fetchReportForProduct() {
|
||||
def requestContent = [
|
||||
requestType: "getProductRiskReport",
|
||||
productToken: config.productToken
|
||||
]
|
||||
|
||||
fetchFileFromWhiteSource("whitesource-riskReport.pdf", requestContent)
|
||||
|
||||
}
|
||||
|
||||
def fetchProductLicenseAlerts() {
|
||||
def requestContent = [
|
||||
requestType: "getProductAlertsByType",
|
||||
alertType: "REJECTED_BY_POLICY_RESOURCE",
|
||||
productToken: config.productToken
|
||||
]
|
||||
def parsedResponse = fetchWhitesourceResource(requestContent)
|
||||
|
||||
return parsedResponse
|
||||
}
|
||||
|
||||
def fetchProjectLicenseAlerts(String projectToken) {
|
||||
def requestContent = [
|
||||
requestType: "getProjectAlertsByType",
|
||||
alertType: "REJECTED_BY_POLICY_RESOURCE",
|
||||
projectToken: projectToken
|
||||
]
|
||||
def parsedResponse = fetchWhitesourceResource(requestContent)
|
||||
|
||||
return parsedResponse
|
||||
}
|
||||
|
||||
@NonCPS
|
||||
protected def httpWhitesource(requestBody) {
|
||||
handleAdditionalRequestParameters(requestBody)
|
||||
def serializedBody = new JsonUtils().getPrettyJsonString(requestBody)
|
||||
def params = [
|
||||
url : config.serviceUrl,
|
||||
httpMode : 'POST',
|
||||
acceptType : 'APPLICATION_JSON',
|
||||
contentType: 'APPLICATION_JSON',
|
||||
requestBody: serializedBody,
|
||||
quiet : !config.verbose,
|
||||
timeout : config.timeout
|
||||
]
|
||||
|
||||
if (script.env.HTTP_PROXY && !config.serviceUrl.matches('http(s)*://.*\\.sap\\.corp.*'))
|
||||
params["httpProxy"] = script.env.HTTP_PROXY
|
||||
|
||||
if(config.verbose)
|
||||
script.echo "Sending http request with parameters ${params}"
|
||||
|
||||
def response = script.httpRequest(params)
|
||||
|
||||
if(config.verbose)
|
||||
script.echo "Received response ${reponse}"
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
@NonCPS
|
||||
private void fetchFileFromWhiteSource(String fileName, Map params) {
|
||||
handleAdditionalRequestParameters(params)
|
||||
def serializedContent = new JsonUtils().getPrettyJsonString(params)
|
||||
|
||||
if(config.verbose)
|
||||
script.echo "Sending curl request with parameters ${params}"
|
||||
|
||||
script.sh "${config.verbose ? '' : '#!/bin/sh -e\n'}curl -o ${fileName} -X POST ${config.serviceUrl} -H 'Content-Type: application/json' -d \'${serializedContent}\'"
|
||||
}
|
||||
|
||||
private void handleAdditionalRequestParameters(params) {
|
||||
if(config.userKey)
|
||||
params["userKey"] = config.userKey
|
||||
}
|
||||
}
|
808
test/groovy/WhitesourceExecuteScanTest.groovy
Normal file
808
test/groovy/WhitesourceExecuteScanTest.groovy
Normal file
@ -0,0 +1,808 @@
|
||||
#!groovy
|
||||
import com.sap.piper.JsonUtils
|
||||
import com.sap.piper.integration.WhitesourceOrgAdminRepository
|
||||
import com.sap.piper.integration.WhitesourceRepository
|
||||
import hudson.AbortException
|
||||
import org.hamcrest.Matchers
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.ExpectedException
|
||||
import org.junit.rules.RuleChain
|
||||
import util.*
|
||||
|
||||
import static org.hamcrest.Matchers.*
|
||||
import static org.junit.Assert.assertThat
|
||||
|
||||
class WhitesourceExecuteScanTest extends BasePiperTest {
|
||||
|
||||
private ExpectedException thrown = ExpectedException.none()
|
||||
private JenkinsDockerExecuteRule dockerExecuteRule = new JenkinsDockerExecuteRule(this)
|
||||
private JenkinsShellCallRule shellRule = new JenkinsShellCallRule(this)
|
||||
private JenkinsLoggingRule loggingRule = new JenkinsLoggingRule(this)
|
||||
private JenkinsWriteFileRule writeFileRule = new JenkinsWriteFileRule(this)
|
||||
private JenkinsStepRule stepRule = new JenkinsStepRule(this)
|
||||
|
||||
@Rule
|
||||
public RuleChain ruleChain = Rules
|
||||
.getCommonRules(this)
|
||||
.around(new JenkinsReadYamlRule(this))
|
||||
.around(thrown)
|
||||
.around(dockerExecuteRule)
|
||||
.around(shellRule)
|
||||
.around(loggingRule)
|
||||
.around(writeFileRule)
|
||||
.around(stepRule)
|
||||
|
||||
def whitesourceOrgAdminRepositoryStub
|
||||
def whitesourceStub
|
||||
|
||||
@Before
|
||||
void init() {
|
||||
def credentialsStore = ['ID-123456789': 'token-0815', 'ID-abcdefg': ['testUser', 'testPassword']]
|
||||
def withCredentialsBindings
|
||||
helper.registerAllowedMethod('string', [Map], {
|
||||
m ->
|
||||
withCredentialsBindings = ["${m.credentialsId}": "${m.variable}"]
|
||||
return m
|
||||
})
|
||||
helper.registerAllowedMethod('usernamePassword', [Map], {
|
||||
m ->
|
||||
withCredentialsBindings = ["${m.credentialsId}": ["${m.usernameVariable}", "${m.passwordVariable}"]]
|
||||
return m
|
||||
})
|
||||
helper.registerAllowedMethod('withCredentials', [List.class, Closure.class], {
|
||||
l, body ->
|
||||
def index = 0
|
||||
withCredentialsBindings.each {
|
||||
entry ->
|
||||
if(entry.value instanceof List) {
|
||||
entry.value.each {
|
||||
subEntry ->
|
||||
def value = credentialsStore[entry.key]
|
||||
getBinding().setProperty(subEntry, value[index])
|
||||
index++
|
||||
|
||||
}
|
||||
} else {
|
||||
getBinding().setProperty(entry.value, credentialsStore[entry.key])
|
||||
}
|
||||
}
|
||||
try {
|
||||
body()
|
||||
} finally {
|
||||
withCredentialsBindings.each {
|
||||
entry ->
|
||||
if(entry.value instanceof List) {
|
||||
entry.value.each {
|
||||
subEntry ->
|
||||
getBinding().setProperty(subEntry, null)
|
||||
|
||||
}
|
||||
} else {
|
||||
getBinding().setProperty(entry.value, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
helper.registerAllowedMethod("archiveArtifacts", [Map.class], { m ->
|
||||
if (m.artifacts == null) {
|
||||
throw new Exception('artifacts cannot be null')
|
||||
}
|
||||
return null
|
||||
})
|
||||
helper.registerAllowedMethod("findFiles", [Map.class], { map ->
|
||||
return [].toArray()
|
||||
})
|
||||
|
||||
whitesourceOrgAdminRepositoryStub = new WhitesourceOrgAdminRepository(nullScript, [serviceUrl: "http://some.host.whitesource.com/api/"])
|
||||
LibraryLoadingTestExecutionListener.prepareObjectInterceptors(whitesourceOrgAdminRepositoryStub)
|
||||
|
||||
whitesourceStub = new WhitesourceRepository(nullScript, [serviceUrl: "http://some.host.whitesource.com/api/"])
|
||||
LibraryLoadingTestExecutionListener.prepareObjectInterceptors(whitesourceStub)
|
||||
|
||||
helper.registerAllowedMethod("fetchProductMetaInfo", [], {
|
||||
return new JsonUtils().parseJsonSerializable("{ \"productVitals\": [{ \"id\": 59639, \"name\": \"SHC - Piper\", \"token\": \"e30132d8e8f04a4c8be6332c75a0ff0580ab326fa7534540ad326e97a74d945b\", \"creationDate\": \"2017-09-20 09:22:46 +0000\", \"lastUpdatedDate\": \"2018-09-19 09:44:40 +0000\" }]}")
|
||||
})
|
||||
helper.registerAllowedMethod("fetchProjectsMetaInfo", [], {
|
||||
return new JsonUtils().parseJsonSerializable("{ \"projectVitals\": [{ \"id\": 261964, \"name\": \"piper-demo - 0.0.1\", \"token\": \"a2a62e5d7beb4170ad4dccfa3316b5a4cd3fadefc56c49f88fbf9400a09f7d94\", \"creationDate\": \"2017-09-21 00:28:06 +0000\", \"lastUpdatedDate\": \"2017-10-12 01:03:05 +0000\" }]}").projectVitals
|
||||
})
|
||||
helper.registerAllowedMethod("fetchReportForProduct", [], { })
|
||||
helper.registerAllowedMethod( "fetchProjectLicenseAlerts", [Object.class], {
|
||||
return new JsonUtils().parseJsonSerializable("{ \"alerts\": [] }").alerts
|
||||
})
|
||||
helper.registerAllowedMethod( "fetchProductLicenseAlerts", [], {
|
||||
return new JsonUtils().parseJsonSerializable("{ \"alerts\": [] }").alerts
|
||||
})
|
||||
helper.registerAllowedMethod( "publishHTML", [Map], {})
|
||||
|
||||
helper.registerAllowedMethod( "getNpmGAV", [String], {return [group: 'com.sap.node', artifact: 'test-node', version: '1.2.3']})
|
||||
helper.registerAllowedMethod( "getSbtGAV", [String], {return [group: 'com.sap.sbt', artifact: 'test-scala', version: '1.2.3']})
|
||||
helper.registerAllowedMethod( "getPipGAV", [String], {return [artifact: 'test-python', version: '1.2.3']})
|
||||
helper.registerAllowedMethod( "readMavenGAV", [String], {return [group: 'com.sap.maven', artifact: 'test-java', version: '1.2.3']})
|
||||
|
||||
nullScript.commonPipelineEnvironment.configuration = nullScript.commonPipelineEnvironment.configuration ?: [:]
|
||||
nullScript.commonPipelineEnvironment.configuration['steps'] = nullScript.commonPipelineEnvironment.configuration['steps'] ?: [:]
|
||||
nullScript.commonPipelineEnvironment.configuration['steps']['whitesourceExecuteScan'] = nullScript.commonPipelineEnvironment.configuration['steps']['whitesourceExecuteScan'] ?: [:]
|
||||
nullScript.commonPipelineEnvironment.configuration['general'] = nullScript.commonPipelineEnvironment.configuration['general'] ?: [:]
|
||||
nullScript.commonPipelineEnvironment.setConfigProperty('userTokenCredentialsId', 'ID-123456789')
|
||||
nullScript.commonPipelineEnvironment.configuration['steps']['whitesourceExecuteScan']['userTokenCredentialsId'] = 'ID-123456789'
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMaven() {
|
||||
helper.registerAllowedMethod("readProperties", [Map], {
|
||||
def result = new Properties()
|
||||
result.putAll([
|
||||
"apiKey": "b39d1328-52e2-42e3-98f0-932709daf3f0",
|
||||
"productName": "SHC - Piper",
|
||||
"checkPolicies": "true",
|
||||
"projectName": "python-test",
|
||||
"projectVersion": "1.0.0"
|
||||
])
|
||||
return result
|
||||
})
|
||||
|
||||
def publishHtmlMap = [:]
|
||||
helper.registerAllowedMethod("publishHTML", [Map.class], { m ->
|
||||
publishHtmlMap = m
|
||||
return null
|
||||
})
|
||||
|
||||
stepRule.step.whitesourceExecuteScan([
|
||||
script : nullScript,
|
||||
whitesourceRepositoryStub : whitesourceStub,
|
||||
whitesourceOrgAdminRepositoryStub : whitesourceOrgAdminRepositoryStub,
|
||||
scanType : 'maven',
|
||||
juStabUtils : utils,
|
||||
orgToken : 'testOrgToken',
|
||||
productName : 'testProduct'
|
||||
])
|
||||
|
||||
assertThat(loggingRule.log, containsString('Unstash content: buildDescriptor'))
|
||||
assertThat(loggingRule.log, containsString('Unstash content: opensourceConfiguration'))
|
||||
|
||||
assertThat(dockerExecuteRule.dockerParams, hasEntry('dockerImage', 'docker.wdf.sap.corp:50000/piper/maven'))
|
||||
assertThat(dockerExecuteRule.dockerParams, hasEntry('dockerWorkspace', '/home/piper'))
|
||||
assertThat(dockerExecuteRule.dockerParams, hasEntry('stashContent', ['buildDescriptor', 'opensourceConfiguration', 'modified whitesource config 420a1bc5c82f57e80307205d8625304f']))
|
||||
|
||||
assertThat(shellRule.shell, Matchers.hasItems(
|
||||
is('curl --location --output wss-unified-agent.jar https://github.com/whitesource/unified-agent-distribution/raw/master/standAlone/wss-unified-agent.jar'),
|
||||
is('./bin/java -jar wss-unified-agent.jar -c \'./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f\' -apiKey \'testOrgToken\' -userKey \'token-0815\' -product \'testProduct\'')
|
||||
))
|
||||
|
||||
assertThat(writeFileRule.files['./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f'], containsString('apiKey=testOrgToken'))
|
||||
assertThat(writeFileRule.files['./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f'], containsString('productName=testProduct'))
|
||||
assertThat(writeFileRule.files['./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f'], containsString('userKey=token-0815'))
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testNpm() {
|
||||
helper.registerAllowedMethod("readProperties", [Map], {
|
||||
def result = new Properties()
|
||||
result.putAll([
|
||||
"apiKey": "b39d1328-52e2-42e3-98f0-932709daf3f0",
|
||||
"productName": "SHC - Piper",
|
||||
"devDep": "false",
|
||||
"checkPolicies": "true",
|
||||
"projectName": "pipeline-test-node",
|
||||
"projectVersion": "1.0.0"
|
||||
])
|
||||
return result
|
||||
})
|
||||
stepRule.step.whitesourceExecuteScan([
|
||||
script : nullScript,
|
||||
whitesourceRepositoryStub : whitesourceStub,
|
||||
whitesourceOrgAdminRepositoryStub : whitesourceOrgAdminRepositoryStub,
|
||||
scanType : 'npm',
|
||||
juStabUtils : utils,
|
||||
orgToken : 'testOrgToken',
|
||||
productName : 'testProductName',
|
||||
productToken : 'testProductToken',
|
||||
reporting : false
|
||||
])
|
||||
|
||||
assertThat(loggingRule.log, containsString('Unstash content: buildDescriptor'))
|
||||
assertThat(loggingRule.log, containsString('Unstash content: opensourceConfiguration'))
|
||||
|
||||
assertThat(dockerExecuteRule.dockerParams, hasEntry('dockerImage', 'docker.wdf.sap.corp:50000/piper/node'))
|
||||
assertThat(dockerExecuteRule.dockerParams, hasEntry('dockerWorkspace', '/home/piper'))
|
||||
assertThat(dockerExecuteRule.dockerParams, hasEntry('stashContent', ['buildDescriptor', 'opensourceConfiguration', 'modified whitesource config 420a1bc5c82f57e80307205d8625304f']))
|
||||
assertThat(shellRule.shell, Matchers.hasItems(
|
||||
is('curl --location --output wss-unified-agent.jar https://github.com/whitesource/unified-agent-distribution/raw/master/standAlone/wss-unified-agent.jar'),
|
||||
is('curl --location --output jvm.tar.gz https://github.com/SAP/SapMachine/releases/download/sapmachine-11.0.2/sapmachine-jre-11.0.2_linux-x64_bin.tar.gz && tar --strip-components=1 -xzf jvm.tar.gz'),
|
||||
is('./bin/java -jar wss-unified-agent.jar -c \'./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f\' -apiKey \'testOrgToken\' -userKey \'token-0815\' -product \'testProductName\'')
|
||||
))
|
||||
|
||||
assertThat(writeFileRule.files['./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f'], containsString('apiKey=testOrgToken'))
|
||||
assertThat(writeFileRule.files['./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f'], containsString('productName=testProductName'))
|
||||
assertThat(writeFileRule.files['./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f'], containsString('productToken=testProductToken'))
|
||||
assertThat(writeFileRule.files['./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f'], containsString('productVersion=1.2.3'))
|
||||
assertThat(writeFileRule.files['./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f'], containsString('projectName=com.sap.node.test-node'))
|
||||
assertThat(writeFileRule.files['./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f'], containsString('userKey=token-0815'))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNpmWithCustomConfigAndFilePath() {
|
||||
helper.registerAllowedMethod("readProperties", [Map], {
|
||||
def result = new Properties()
|
||||
result.putAll([
|
||||
"apiKey": "b39d1328-52e2-42e3-98f0-932709daf3f0",
|
||||
"productName": "SHC - Piper",
|
||||
"devDep": "false",
|
||||
"checkPolicies": "true",
|
||||
"projectName": "pipeline-test-node",
|
||||
"projectVersion": "1.0.0"
|
||||
])
|
||||
return result
|
||||
})
|
||||
stepRule.step.whitesourceExecuteScan([
|
||||
script : nullScript,
|
||||
whitesourceRepositoryStub : whitesourceStub,
|
||||
whitesourceOrgAdminRepositoryStub : whitesourceOrgAdminRepositoryStub,
|
||||
scanType : 'npm',
|
||||
productName : 'SHC - Piper',
|
||||
configFilePath : './../../testConfigPath',
|
||||
file : 'package.json',
|
||||
juStabUtils : utils
|
||||
])
|
||||
|
||||
assertThat(shellRule.shell, Matchers.hasItems(
|
||||
is('curl --location --output wss-unified-agent.jar https://github.com/whitesource/unified-agent-distribution/raw/master/standAlone/wss-unified-agent.jar'),
|
||||
is('curl --location --output jvm.tar.gz https://github.com/SAP/SapMachine/releases/download/sapmachine-11.0.2/sapmachine-jre-11.0.2_linux-x64_bin.tar.gz && tar --strip-components=1 -xzf jvm.tar.gz'),
|
||||
is('./bin/java -jar wss-unified-agent.jar -c \'./../../testConfigPath.092aaffe7a79d11da13593b63b929754\' -userKey \'token-0815\' -product \'SHC - Piper\'')
|
||||
))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPip() {
|
||||
helper.registerAllowedMethod("readProperties", [Map], {
|
||||
def result = new Properties()
|
||||
result.putAll([
|
||||
"apiKey": "b39d1328-52e2-42e3-98f0-932709daf3f0",
|
||||
"productName": "SHC - Piper",
|
||||
"checkPolicies": "true",
|
||||
"projectName": "python-test",
|
||||
"projectVersion": "1.0.0"
|
||||
])
|
||||
return result
|
||||
})
|
||||
|
||||
stepRule.step.whitesourceExecuteScan([
|
||||
script : nullScript,
|
||||
whitesourceRepositoryStub : whitesourceStub,
|
||||
whitesourceOrgAdminRepositoryStub : whitesourceOrgAdminRepositoryStub,
|
||||
scanType : 'pip',
|
||||
juStabUtils : utils,
|
||||
orgToken : 'testOrgToken',
|
||||
productName : 'testProductName',
|
||||
reporting : false
|
||||
])
|
||||
|
||||
assertThat(loggingRule.log, containsString('Unstash content: buildDescriptor'))
|
||||
|
||||
assertThat(dockerExecuteRule.dockerParams, hasEntry('dockerImage', 'docker.wdf.sap.corp:50000/piper/node'))
|
||||
assertThat(dockerExecuteRule.dockerParams, hasEntry('dockerWorkspace', '/home/piper'))
|
||||
assertThat(dockerExecuteRule.dockerParams, hasEntry('stashContent', ['buildDescriptor', 'opensourceConfiguration', 'modified whitesource config 420a1bc5c82f57e80307205d8625304f']))
|
||||
|
||||
assertThat(shellRule.shell, Matchers.hasItems(
|
||||
is('curl --location --output wss-unified-agent.jar https://github.com/whitesource/unified-agent-distribution/raw/master/standAlone/wss-unified-agent.jar'),
|
||||
is('curl --location --output jvm.tar.gz https://github.com/SAP/SapMachine/releases/download/sapmachine-11.0.2/sapmachine-jre-11.0.2_linux-x64_bin.tar.gz && tar --strip-components=1 -xzf jvm.tar.gz'),
|
||||
is('./bin/java -jar wss-unified-agent.jar -c \'./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f\' -apiKey \'testOrgToken\' -userKey \'token-0815\' -product \'testProductName\'')
|
||||
))
|
||||
|
||||
assertThat(writeFileRule.files['./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f'], containsString('apiKey=testOrgToken'))
|
||||
assertThat(writeFileRule.files['./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f'], containsString('productName=testProductName'))
|
||||
assertThat(writeFileRule.files['./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f'], containsString('userKey=token-0815'))
|
||||
assertThat(writeFileRule.files['./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f'], containsString('productVersion=1.2.3'))
|
||||
assertThat(writeFileRule.files['./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f'], containsString('projectName=test-python'))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSbt() {
|
||||
helper.registerAllowedMethod("readProperties", [Map], {
|
||||
def result = new Properties()
|
||||
result.putAll([
|
||||
"apiKey": "b39d1328-52e2-42e3-98f0-932709daf3f0",
|
||||
"productName": "SHC - Piper",
|
||||
"checkPolicies": "true",
|
||||
"projectName": "python-test",
|
||||
"projectVersion": "1.0.0"
|
||||
])
|
||||
return result
|
||||
})
|
||||
|
||||
stepRule.step.whitesourceExecuteScan([
|
||||
script : nullScript,
|
||||
whitesourceRepositoryStub : whitesourceStub,
|
||||
whitesourceOrgAdminRepositoryStub : whitesourceOrgAdminRepositoryStub,
|
||||
scanType : 'sbt',
|
||||
juStabUtils : utils,
|
||||
productName : 'testProductName',
|
||||
orgToken : 'testOrgToken',
|
||||
reporting : false
|
||||
])
|
||||
|
||||
assertThat(loggingRule.log, containsString('Unstash content: buildDescriptor'))
|
||||
assertThat(loggingRule.log, containsString('Unstash content: opensourceConfiguration'))
|
||||
|
||||
assertThat(dockerExecuteRule.dockerParams, hasEntry('dockerImage', 'docker.wdf.sap.corp:50000/piper/sbt'))
|
||||
assertThat(dockerExecuteRule.dockerParams, hasEntry('dockerWorkspace', '/home/piper'))
|
||||
assertThat(dockerExecuteRule.dockerParams, hasEntry('stashContent', ['buildDescriptor', 'opensourceConfiguration', 'modified whitesource config 420a1bc5c82f57e80307205d8625304f']))
|
||||
|
||||
assertThat(shellRule.shell, Matchers.hasItems(
|
||||
is('curl --location --output wss-unified-agent.jar https://github.com/whitesource/unified-agent-distribution/raw/master/standAlone/wss-unified-agent.jar'),
|
||||
is('./bin/java -jar wss-unified-agent.jar -c \'./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f\' -apiKey \'testOrgToken\' -userKey \'token-0815\' -product \'testProductName\'')
|
||||
))
|
||||
|
||||
assertThat(writeFileRule.files['./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f'], containsString('apiKey=testOrgToken'))
|
||||
assertThat(writeFileRule.files['./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f'], containsString('productName=testProductName'))
|
||||
assertThat(writeFileRule.files['./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f'], containsString('userKey=token-0815'))
|
||||
assertThat(writeFileRule.files['./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f'], containsString('productVersion=1.2.3'))
|
||||
assertThat(writeFileRule.files['./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f'], containsString('projectName=com.sap.sbt.test-scala'))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAgentNoDownloads() {
|
||||
helper.registerAllowedMethod("readProperties", [Map], {
|
||||
def result = new Properties()
|
||||
result.putAll([
|
||||
"apiKey": "b39d1328-52e2-42e3-98f0-932709daf3f0",
|
||||
"productName": "SHC - Piper",
|
||||
"checkPolicies": "true",
|
||||
"projectName": "python-test",
|
||||
"projectVersion": "1.0.0"
|
||||
])
|
||||
return result
|
||||
})
|
||||
stepRule.step.whitesourceExecuteScan([
|
||||
script : nullScript,
|
||||
whitesourceRepositoryStub : whitesourceStub,
|
||||
whitesourceOrgAdminRepositoryStub : whitesourceOrgAdminRepositoryStub,
|
||||
scanType : 'maven',
|
||||
agentDownloadUrl : '',
|
||||
jreDownloadUrl : '',
|
||||
agentParameters : 'testParams',
|
||||
juStabUtils : utils,
|
||||
orgToken : 'testOrgToken',
|
||||
productName : 'testProductName'
|
||||
])
|
||||
|
||||
assertThat(shellRule.shell[0], is('java -jar wss-unified-agent.jar -c \'./wss-unified-agent.config.420a1bc5c82f57e80307205d8625304f\' -apiKey \'testOrgToken\' -userKey \'token-0815\' -product \'testProductName\' testParams'))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMta() {
|
||||
helper.registerAllowedMethod("readProperties", [Map], {
|
||||
def result = new Properties()
|
||||
result.putAll([
|
||||
"apiKey": "b39d1328-52e2-42e3-98f0-932709daf3f0",
|
||||
"productName": "SHC - Piper",
|
||||
"checkPolicies": "true",
|
||||
"projectName": "python-test",
|
||||
"projectVersion": "1.0.0"
|
||||
])
|
||||
return result
|
||||
})
|
||||
helper.registerAllowedMethod("findFiles", [Map.class], { map ->
|
||||
if (map.glob == "**${File.separator}pom.xml") {
|
||||
return [new File('maven1/pom.xml'), new File('maven2/pom.xml')].toArray()
|
||||
}
|
||||
if (map.glob == "**${File.separator}package.json") {
|
||||
return [new File('npm1/package.json'), new File('npm2/package.json')].toArray()
|
||||
}
|
||||
return [].toArray()
|
||||
})
|
||||
|
||||
def whitesourceCalls = []
|
||||
helper.registerAllowedMethod("whitesourceExecuteScan", [Map.class], { map ->
|
||||
whitesourceCalls.add(map)
|
||||
stepRule.step.call(map)
|
||||
})
|
||||
|
||||
def parallelMap = [:]
|
||||
helper.registerAllowedMethod("parallel", [Map.class], { map ->
|
||||
parallelMap = map
|
||||
parallelMap['Whitesource - maven1']()
|
||||
parallelMap['Whitesource - npm1']()
|
||||
})
|
||||
|
||||
//need to use call due to mock above
|
||||
stepRule.step.call([
|
||||
script : nullScript,
|
||||
whitesourceRepositoryStub : whitesourceStub,
|
||||
whitesourceOrgAdminRepositoryStub : whitesourceOrgAdminRepositoryStub,
|
||||
scanType : 'mta',
|
||||
productName : 'SHC - Piper',
|
||||
buildDescriptorExcludeList : ["maven2${File.separator}pom.xml".toString(), "npm2${File.separator}package.json".toString()],
|
||||
reporting : true,
|
||||
juStabUtils : utils
|
||||
])
|
||||
|
||||
assertThat(loggingRule.log, containsString('Unstash content: buildDescriptor'))
|
||||
assertThat(loggingRule.log, containsString('Unstash content: opensourceConfiguration'))
|
||||
|
||||
assertThat(parallelMap, hasKey('Whitesource - maven1'))
|
||||
assertThat(parallelMap, hasKey('Whitesource - npm1'))
|
||||
assertThat(parallelMap.keySet(), hasSize(3))
|
||||
|
||||
assertThat(whitesourceCalls, hasItem(allOf(
|
||||
hasEntry('scanType', 'maven'),
|
||||
hasEntry('buildDescriptorFile', "maven1${File.separator}pom.xml".toString())
|
||||
)))
|
||||
assertThat(whitesourceCalls, hasItem(allOf(
|
||||
hasEntry('scanType', 'npm'),
|
||||
hasEntry('projectNames', ["com.sap.maven.test-java - 1.2.3", "com.sap.node.test-node - 1.2.3"]),
|
||||
hasEntry('buildDescriptorFile', "npm1${File.separator}package.json".toString())
|
||||
)))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMtaBlocks() {
|
||||
helper.registerAllowedMethod("findFiles", [Map.class], { map ->
|
||||
if (map.glob == "**${File.separator}pom.xml") {
|
||||
return [new File('maven1/pom.xml'), new File('maven2/pom.xml')].toArray()
|
||||
}
|
||||
if (map.glob == "**${File.separator}package.json") {
|
||||
return [new File('npm1/package.json'), new File('npm2/package.json'), new File('npm3/package.json'), new File('npm4/package.json')].toArray()
|
||||
}
|
||||
return [].toArray()
|
||||
})
|
||||
|
||||
def whitesourceCalls = []
|
||||
helper.registerAllowedMethod("whitesourceExecuteScan", [Map.class], { map ->
|
||||
whitesourceCalls.add(map)
|
||||
})
|
||||
|
||||
def invocation = 0
|
||||
def parallelMap = [:]
|
||||
helper.registerAllowedMethod("parallel", [Map.class], { map ->
|
||||
parallelMap[invocation] = map
|
||||
for(i = 0; i < parallelMap[invocation].keySet().size(); i++) {
|
||||
def key = parallelMap[invocation].keySet()[i]
|
||||
if(key != "failFast")
|
||||
parallelMap[invocation][key]()
|
||||
}
|
||||
invocation++
|
||||
})
|
||||
|
||||
//need to use call due to mock above
|
||||
stepRule.step.call([
|
||||
script : nullScript,
|
||||
whitesourceRepositoryStub : whitesourceStub,
|
||||
whitesourceOrgAdminRepositoryStub : whitesourceOrgAdminRepositoryStub,
|
||||
scanType : 'mta',
|
||||
productName : 'SHC - Piper',
|
||||
buildDescriptorExcludeList : ["maven2${File.separator}pom.xml".toString()],
|
||||
juStabUtils : utils,
|
||||
parallelLimit : 3
|
||||
])
|
||||
|
||||
assertThat(loggingRule.log, containsString('Unstash content: buildDescriptor'))
|
||||
assertThat(loggingRule.log, containsString('Unstash content: opensourceConfiguration'))
|
||||
|
||||
assertThat(invocation, is(2))
|
||||
assertThat(parallelMap[0], hasKey('Whitesource - maven1'))
|
||||
assertThat(parallelMap[0], hasKey('Whitesource - npm1'))
|
||||
assertThat(parallelMap[0], hasKey('Whitesource - npm2'))
|
||||
assertThat(parallelMap[0].keySet(), hasSize(4))
|
||||
assertThat(parallelMap[1], hasKey('Whitesource - npm3'))
|
||||
assertThat(parallelMap[1], hasKey('Whitesource - npm4'))
|
||||
assertThat(parallelMap[1].keySet(), hasSize(3))
|
||||
|
||||
assertThat(whitesourceCalls, hasItem(allOf(
|
||||
hasEntry('scanType', 'maven'),
|
||||
hasEntry('buildDescriptorFile', "maven1${File.separator}pom.xml".toString())
|
||||
)))
|
||||
assertThat(whitesourceCalls, hasItem(allOf(
|
||||
hasEntry('scanType', 'npm'),
|
||||
hasEntry('buildDescriptorFile', "npm1${File.separator}package.json".toString())
|
||||
)))
|
||||
assertThat(whitesourceCalls, hasItem(allOf(
|
||||
hasEntry('scanType', 'npm'),
|
||||
hasEntry('buildDescriptorFile', "npm2${File.separator}package.json".toString())
|
||||
)))
|
||||
assertThat(whitesourceCalls, hasItem(allOf(
|
||||
hasEntry('scanType', 'npm'),
|
||||
hasEntry('buildDescriptorFile', "npm3${File.separator}package.json".toString())
|
||||
)))
|
||||
assertThat(whitesourceCalls, hasItem(allOf(
|
||||
hasEntry('scanType', 'npm'),
|
||||
hasEntry('buildDescriptorFile', "npm4${File.separator}package.json".toString())
|
||||
)))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMtaSingleExclude() {
|
||||
|
||||
helper.registerAllowedMethod("findFiles", [Map.class], { map ->
|
||||
if (map.glob == "**${File.separator}pom.xml") {
|
||||
return [new File('maven1/pom.xml'), new File('maven2/pom.xml')].toArray()
|
||||
}
|
||||
if (map.glob == "**${File.separator}package.json") {
|
||||
return [new File('npm1/package.json'), new File('npm2/package.json')].toArray()
|
||||
}
|
||||
return [].toArray()
|
||||
})
|
||||
|
||||
def parallelMap = [:]
|
||||
helper.registerAllowedMethod("parallel", [Map.class], { map ->
|
||||
parallelMap = map
|
||||
})
|
||||
|
||||
stepRule.step.whitesourceExecuteScan([
|
||||
script : nullScript,
|
||||
whitesourceRepositoryStub : whitesourceStub,
|
||||
whitesourceOrgAdminRepositoryStub : whitesourceOrgAdminRepositoryStub,
|
||||
scanType : 'mta',
|
||||
productName : 'SHC - Piper',
|
||||
buildDescriptorExcludeList : "maven2${File.separator}pom.xml",
|
||||
juStabUtils : utils
|
||||
])
|
||||
|
||||
assertThat(parallelMap.keySet(), hasSize(4))
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNPMStatusCheckScanException() {
|
||||
thrown.expect(AbortException.class)
|
||||
stepRule.step.checkStatus(-1 & 0xFF, [licensingVulnerabilities: true])
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNPMStatusCheckPolicyViolation() {
|
||||
thrown.expect(AbortException.class)
|
||||
stepRule.step.checkStatus(-2 & 0xFF, [licensingVulnerabilities: true])
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNPMStatusCheckNoPolicyViolation() {
|
||||
stepRule.step.checkStatus(-2 & 0xFF, [licensingVulnerabilities: false])
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNPMStatusCheckClientException() {
|
||||
thrown.expect(AbortException.class)
|
||||
stepRule.step.checkStatus(-3 & 0xFF, [licensingVulnerabilities: true])
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNPMStatusCheckConnectionException() {
|
||||
thrown.expect(AbortException.class)
|
||||
stepRule.step.checkStatus(-4 & 0xFF, [licensingVulnerabilities: true])
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNPMStatusCheckServerException() {
|
||||
thrown.expect(AbortException.class)
|
||||
stepRule.step.checkStatus(-3 & 0xFF, [licensingVulnerabilities: true])
|
||||
}
|
||||
|
||||
@Test
|
||||
void testViolationPolicy() {
|
||||
stepRule.step.checkViolationStatus(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
void testViolationPolicyException() {
|
||||
thrown.expect(AbortException.class)
|
||||
thrown.expectMessage("1")
|
||||
stepRule.step.checkViolationStatus(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFetchViolationCountProject() {
|
||||
|
||||
def config = [projectNames: ["piper-java-cc - 0.0.1", "pipeline-test - 0.0.1"], productToken: "product-token"]
|
||||
|
||||
def projectTokens = [[token:"abc-project-token"],[token:"def-project-token"]]
|
||||
helper.registerAllowedMethod('fetchProjectsMetaInfo', [], { return projectTokens })
|
||||
helper.registerAllowedMethod('fetchProjectLicenseAlerts', [String], { projectToken ->
|
||||
if(projectToken == projectTokens[0].token)
|
||||
return [alerts: []]
|
||||
if(projectToken == projectTokens[1].token)
|
||||
return [alerts: []]
|
||||
})
|
||||
|
||||
def violationCount = stepRule.step.fetchViolationCount(config, whitesourceStub)
|
||||
|
||||
Assert.assertTrue(violationCount == 0)
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testFetchViolationCountProjectNotZero() {
|
||||
|
||||
def config = [projectNames: ["piper-java-cc - 0.0.1", "pipeline-test - 0.0.1"]]
|
||||
|
||||
def projectTokens = [[token:"abc-project-token"],[token:"def-project-token"]]
|
||||
helper.registerAllowedMethod('fetchProjectsMetaInfo', [], { return projectTokens })
|
||||
helper.registerAllowedMethod('fetchProjectLicenseAlerts', [String], { projectToken ->
|
||||
if(projectToken == projectTokens[0].token)
|
||||
return [alerts: [{}, {}]]
|
||||
if(projectToken == projectTokens[1].token)
|
||||
return [alerts: [{}, {}, {}]]
|
||||
})
|
||||
|
||||
def violationCount = stepRule.step.fetchViolationCount(config, whitesourceStub)
|
||||
|
||||
Assert.assertTrue(violationCount == 5)
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFetchViolationCountProduct() {
|
||||
|
||||
def config = [:]
|
||||
|
||||
helper.registerAllowedMethod('fetchProductLicenseAlerts', [], { return [alerts: []] })
|
||||
|
||||
def violationCount = stepRule.step.fetchViolationCount(config, whitesourceStub)
|
||||
|
||||
Assert.assertTrue(violationCount == 0)
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFetchViolationCountProductNotZero() {
|
||||
|
||||
def config = [:]
|
||||
|
||||
helper.registerAllowedMethod('fetchProductLicenseAlerts', [], { return [alerts: [{}, {}]]})
|
||||
|
||||
def violationCount = stepRule.step.fetchViolationCount(config, whitesourceStub)
|
||||
|
||||
Assert.assertTrue(violationCount == 2)
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCheckException() {
|
||||
helper.registerAllowedMethod("readProperties", [Map], {
|
||||
def result = new Properties()
|
||||
result.putAll([
|
||||
"apiKey": "b39d1328-52e2-42e3-98f0-932709daf3f0",
|
||||
"productName": "SHC - Piper",
|
||||
"checkPolicies": "true",
|
||||
"projectName": "python-test",
|
||||
"projectVersion": "1.0.0"
|
||||
])
|
||||
return result
|
||||
})
|
||||
helper.registerAllowedMethod("fetchVulnerabilities", [Object.class], {
|
||||
return new JsonUtils().parseJsonSerializable("{ \"alerts\": [ { \"vulnerability\": { \"name\": \"CVE-2017-15095\", \"type\": \"CVE\", \"severity\": \"high\", \"score\": 7.5, \"cvss3_severity\": \"high\", \"cvss3_score\": 9.8, \"scoreMetadataVector\": \"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H\", \"publishDate\": \"2018-02-06\", \"url\": \"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-15095\", \"description\": \"A deserialization flaw was discovered in the jackson-databind in versions before 2.8.10 and 2.9.1, which could allow an unauthenticated user to perform code execution by sending the maliciously crafted input to the readValue method of the ObjectMapper. This issue extends the previous flaw CVE-2017-7525 by blacklisting more classes that could be used maliciously.\", \"topFix\": { \"vulnerability\": \"CVE-2017-15095\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/FasterXML/jackson-databind/commit/60d459ce\"," +
|
||||
"\"fixResolution\": \"src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java,release-notes/VERSION,src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java\", \"date\": \"2017-04-13\", \"message\": \"Fix #1599 for 2.8.9\\n\\nMerge branch '2.7' into 2.8\", \"extraData\": \"key=60d459c&committerName=cowtowncoder&committerUrl=https://github.com/cowtowncoder&committerAvatar=https://avatars0.githubusercontent.com/u/55065?v=4\" }, \"allFixes\": [ { \"vulnerability\": \"CVE-2017-15095\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/FasterXML/jackson-databind/commit/60d459ce\", \"fixResolution\": \"src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java,release-notes/VERSION,src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java\", \"date\": \"2017-04-13\", \"message\": \"Fix #1599 for 2.8.9\\n\\nMerge branch '2.7' into 2.8\"," +
|
||||
"\"extraData\": \"key=60d459c&committerName=cowtowncoder&committerUrl=https://github.com/cowtowncoder&committerAvatar=https://avatars0.githubusercontent.com/u/55065?v=4\" }, { \"vulnerability\": \"CVE-2017-15095\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/FasterXML/jackson-databind/commit/e865a7a4464da63ded9f4b1a2328ad85c9ded78b#diff-98084d808198119d550a9211e128a16f\", \"fixResolution\": \"src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java,release-notes/VERSION,src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java\", \"date\": \"2017-12-12\", \"message\": \"Fix #1737 (#1857)\", \"extraData\": \"key=e865a7a&committerName=cowtowncoder&committerUrl=https://github.com/cowtowncoder&committerAvatar=https://avatars0.githubusercontent.com/u/55065?v=4\" }, { \"vulnerability\": \"CVE-2017-15095\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/FasterXML/jackson-databind/commit/e8f043d1\"," +
|
||||
"\"fixResolution\": \"release-notes/VERSION,src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java\", \"date\": \"2017-06-30\", \"message\": \"Fix #1680\", \"extraData\": \"key=e8f043d&committerName=cowtowncoder&committerUrl=https://github.com/cowtowncoder&committerAvatar=https://avatars0.githubusercontent.com/u/55065?v=4\" } ], \"fixResolutionText\": \"Replace or update the following files: IllegalTypesCheckTest.java, VERSION, BeanDeserializerFactory.java\", \"references\": [] }, \"type\": \"SECURITY_VULNERABILITY\", \"level\": \"MAJOR\", \"library\": { \"keyUuid\": \"13f7802e-8aa1-4303-a5db-1d0c85e871a9\", \"keyId\": 23410061, \"filename\": \"jackson-databind-2.8.8.jar\", \"name\": \"jackson-databind\", \"groupId\": \"com.fasterxml.jackson.core\", \"artifactId\": \"jackson-databind\", \"version\": \"2.8.8\", \"sha1\": \"bf88c7b27e95cbadce4e7c316a56c3efffda8026\", \"type\": \"Java\", \"references\": { \"url\": \"http://github.com/FasterXML/jackson\", \"issueUrl\": \"https://github.com/FasterXML/jackson-databind/issues\"," +
|
||||
"\"pomUrl\": \"http://repo.jfrog.org/artifactory/list/repo1/com/fasterxml/jackson/core/jackson-databind/2.8.8/jackson-databind-2.8.8.pom\", \"scmUrl\": \"http://github.com/FasterXML/jackson-databind\" }, \"licenses\": [ { \"name\": \"Apache 2.0\", \"url\": \"http://apache.org/licenses/LICENSE-2.0\", \"profileInfo\": { \"copyrightRiskScore\": \"THREE\", \"patentRiskScore\": \"ONE\", \"copyleft\": \"NO\", \"linking\": \"DYNAMIC\", \"royaltyFree\": \"CONDITIONAL\" } } ] }, \"project\": \"pipeline-test - 0.0.1\", \"projectId\": 302194, \"projectToken\": \"1b8fdc36cb6949f482d0fd936a39dab69d6b34f43fff4dda8a9241f2c6e536c7\", \"directDependency\": false, \"description\": \"High:5,\", \"date\": \"2017-11-15\" }, { \"vulnerability\": { \"name\": \"CVE-2017-17485\", \"type\": \"CVE\", \"severity\": \"high\", \"score\": 7.5, \"cvss3_severity\": \"high\", \"cvss3_score\": 9.8, \"scoreMetadataVector\": \"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H\", \"publishDate\": \"2018-01-10\", \"url\": \"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-17485\"," +
|
||||
"\"description\": \"FasterXML jackson-databind through 2.8.10 and 2.9.x through 2.9.3 allows unauthenticated remote code execution because of an incomplete fix for the CVE-2017-7525 deserialization flaw. This is exploitable by sending maliciously crafted JSON input to the readValue method of the ObjectMapper, bypassing a blacklist that is ineffective if the Spring libraries are available in the classpath.\", \"topFix\": { \"vulnerability\": \"CVE-2017-17485\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/FasterXML/jackson-databind/commit/bb45fb16709018842f858f1a6e1118676aaa34bd#diff-727a6e8db3603b95f185697108af6c48\", \"fixResolution\": \"src/test/java/org/springframework/jacksontest/AbstractApplicationContext.java,src/test/java/org/springframework/jacksontest/AbstractPointcutAdvisor.java,src/test/java/org/springframework/jacksontest/BogusApplicationContext.java,src/main/java/com/fasterxml/jackson/databind/jsontype/impl/SubTypeValidator.java,src/test/java/org/springframework/jacksontest/BogusPointcutAdvisor.java,src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java\"," +
|
||||
"\"date\": \"2017-12-19\", \"message\": \"Fix issues with earlier fix for #1855\", \"extraData\": \"key=bb45fb1&committerName=cowtowncoder&committerUrl=https://github.com/cowtowncoder&committerAvatar=https://avatars0.githubusercontent.com/u/55065?v=4\" }, \"allFixes\": [ { \"vulnerability\": \"CVE-2017-17485\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/FasterXML/jackson-databind/commit/bb45fb16709018842f858f1a6e1118676aaa34bd#diff-727a6e8db3603b95f185697108af6c48\", \"fixResolution\": \"src/test/java/org/springframework/jacksontest/AbstractApplicationContext.java,src/test/java/org/springframework/jacksontest/AbstractPointcutAdvisor.java,src/test/java/org/springframework/jacksontest/BogusApplicationContext.java,src/main/java/com/fasterxml/jackson/databind/jsontype/impl/SubTypeValidator.java,src/test/java/org/springframework/jacksontest/BogusPointcutAdvisor.java,src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java\", \"date\": \"2017-12-19\", \"message\": \"Fix issues with earlier fix for #1855\"," +
|
||||
"\"extraData\": \"key=bb45fb1&committerName=cowtowncoder&committerUrl=https://github.com/cowtowncoder&committerAvatar=https://avatars0.githubusercontent.com/u/55065?v=4\" }, { \"vulnerability\": \"CVE-2017-17485\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/FasterXML/jackson-databind/commit/bb45fb16709018842f858f1a6e1118676aaa34bd\", \"fixResolution\": \"src/test/java/org/springframework/jacksontest/AbstractApplicationContext.java,src/test/java/org/springframework/jacksontest/AbstractPointcutAdvisor.java,src/test/java/org/springframework/jacksontest/BogusApplicationContext.java,src/main/java/com/fasterxml/jackson/databind/jsontype/impl/SubTypeValidator.java,src/test/java/org/springframework/jacksontest/BogusPointcutAdvisor.java,src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java\", \"date\": \"2017-12-19\", \"message\": \"Fix issues with earlier fix for #1855\", \"extraData\": \"key=bb45fb1&committerName=cowtowncoder&committerUrl=https://github.com/cowtowncoder&committerAvatar=https://avatars0.githubusercontent.com/u/55065?v=4\" } ]," +
|
||||
"\"fixResolutionText\": \"Replace or update the following files: AbstractApplicationContext.java, AbstractPointcutAdvisor.java, BogusApplicationContext.java, SubTypeValidator.java, BogusPointcutAdvisor.java, IllegalTypesCheckTest.java\", \"references\": [] }, \"type\": \"SECURITY_VULNERABILITY\", \"level\": \"MAJOR\", \"library\": { \"keyUuid\": \"13f7802e-8aa1-4303-a5db-1d0c85e871a9\", \"keyId\": 23410061, \"filename\": \"jackson-databind-2.8.8.jar\", \"name\": \"jackson-databind\", \"groupId\": \"com.fasterxml.jackson.core\", \"artifactId\": \"jackson-databind\", \"version\": \"2.8.8\", \"sha1\": \"bf88c7b27e95cbadce4e7c316a56c3efffda8026\", \"type\": \"Java\", \"references\": { \"url\": \"http://github.com/FasterXML/jackson\", \"issueUrl\": \"https://github.com/FasterXML/jackson-databind/issues\", \"pomUrl\": \"http://repo.jfrog.org/artifactory/list/repo1/com/fasterxml/jackson/core/jackson-databind/2.8.8/jackson-databind-2.8.8.pom\", \"scmUrl\": \"http://github.com/FasterXML/jackson-databind\" }, \"licenses\": [ { \"name\": \"Apache 2.0\", \"url\": \"http://apache.org/licenses/LICENSE-2.0\"," +
|
||||
"\"profileInfo\": { \"copyrightRiskScore\": \"THREE\", \"patentRiskScore\": \"ONE\", \"copyleft\": \"NO\", \"linking\": \"DYNAMIC\", \"royaltyFree\": \"CONDITIONAL\" } } ] }, \"project\": \"pipeline-test - 0.0.1\", \"projectId\": 302194, \"projectToken\": \"1b8fdc36cb6949f482d0fd936a39dab69d6b34f43fff4dda8a9241f2c6e536c7\", \"directDependency\": false, \"description\": \"High:5,\", \"date\": \"2017-11-15\" }, { \"vulnerability\": { \"name\": \"CVE-2017-7525\", \"type\": \"CVE\", \"severity\": \"high\", \"score\": 7.5, \"cvss3_severity\": \"high\", \"cvss3_score\": 9.8, \"scoreMetadataVector\": \"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H\", \"publishDate\": \"2018-02-06\", \"url\": \"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-7525\", \"description\": \"A deserialization flaw was discovered in the jackson-databind, versions before 2.6.7.1, 2.7.9.1 and 2.8.9, which could allow an unauthenticated user to perform code execution by sending the maliciously crafted input to the readValue method of the ObjectMapper.\", \"topFix\": { \"vulnerability\": \"CVE-2017-7525\"," +
|
||||
"\"type\": \"UPGRADE_VERSION\", \"origin\": \"BUGZILLA\", \"url\": \"https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2017-7525\", \"fixResolution\": \"jackson-databind 2.8.9,jackson-databind 2.9.0\", \"message\": \"CVE-2017-7525 jackson-databind: Deserialization vulnerability via readValue method of ObjectMapper\", \"extraData\": \"key=1462702&assignee=Red Hat Product Security\" }, \"allFixes\": [ { \"vulnerability\": \"CVE-2017-7525\", \"type\": \"UPGRADE_VERSION\", \"origin\": \"BUGZILLA\", \"url\": \"https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2017-7525\", \"fixResolution\": \"jackson-databind 2.8.9,jackson-databind 2.9.0\", \"message\": \"CVE-2017-7525 jackson-databind: Deserialization vulnerability via readValue method of ObjectMapper\", \"extraData\": \"key=1462702&assignee=Red Hat Product Security\" }, { \"vulnerability\": \"CVE-2017-7525\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/FasterXML/jackson-databind/commit/60d459cedcf079c6106ae7da2ac562bc32dcabe1#diff-98084d808198119d550a9211e128a16f\"," +
|
||||
"\"fixResolution\": \"src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java,release-notes/VERSION,src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java\", \"date\": \"2017-04-13\", \"message\": \"Fix #1599 for 2.8.9\\n\\nMerge branch '2.7' into 2.8\", \"extraData\": \"key=60d459c&committerName=cowtowncoder&committerUrl=https://github.com/cowtowncoder&committerAvatar=https://avatars0.githubusercontent.com/u/55065?v=4\" }, { \"vulnerability\": \"CVE-2017-7525\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/FasterXML/jackson-databind/commit/60d459cedcf079c6106ae7da2ac562bc32dcabe1\", \"fixResolution\": \"src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java,release-notes/VERSION,src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java\", \"date\": \"2017-04-13\", \"message\": \"Fix #1599 for 2.8.9\\n\\nMerge branch '2.7' into 2.8\"," +
|
||||
"\"extraData\": \"key=60d459c&committerName=cowtowncoder&committerUrl=https://github.com/cowtowncoder&committerAvatar=https://avatars0.githubusercontent.com/u/55065?v=4\" }, { \"vulnerability\": \"CVE-2017-7525\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/FasterXML/jackson-databind/commit/6ce32ffd18facac6abdbbf559c817b47fcb622c1\", \"fixResolution\": \"src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java,release-notes/VERSION,src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java\", \"date\": \"2017-04-13\", \"message\": \"Fix #1599 for 2.7(.10)\", \"extraData\": \"key=6ce32ff&committerName=cowtowncoder&committerUrl=https://github.com/cowtowncoder&committerAvatar=https://avatars0.githubusercontent.com/u/55065?v=4\" } ], \"fixResolutionText\": \"Upgrade to version jackson-databind 2.8.9, jackson-databind 2.9.0 or greater\", \"references\": [] }, \"type\": \"SECURITY_VULNERABILITY\"," +
|
||||
"\"level\": \"MAJOR\", \"library\": { \"keyUuid\": \"13f7802e-8aa1-4303-a5db-1d0c85e871a9\", \"keyId\": 23410061, \"filename\": \"jackson-databind-2.8.8.jar\", \"name\": \"jackson-databind\", \"groupId\": \"com.fasterxml.jackson.core\", \"artifactId\": \"jackson-databind\", \"version\": \"2.8.8\", \"sha1\": \"bf88c7b27e95cbadce4e7c316a56c3efffda8026\", \"type\": \"Java\", \"references\": { \"url\": \"http://github.com/FasterXML/jackson\", \"issueUrl\": \"https://github.com/FasterXML/jackson-databind/issues\", \"pomUrl\": \"http://repo.jfrog.org/artifactory/list/repo1/com/fasterxml/jackson/core/jackson-databind/2.8.8/jackson-databind-2.8.8.pom\", \"scmUrl\": \"http://github.com/FasterXML/jackson-databind\" }, \"licenses\": [ { \"name\": \"Apache 2.0\", \"url\": \"http://apache.org/licenses/LICENSE-2.0\", \"profileInfo\": { \"copyrightRiskScore\": \"THREE\", \"patentRiskScore\": \"ONE\", \"copyleft\": \"NO\", \"linking\": \"DYNAMIC\", \"royaltyFree\": \"CONDITIONAL\" } } ] }," +
|
||||
"\"project\": \"pipeline-test - 0.0.1\", \"projectId\": 302194, \"projectToken\": \"1b8fdc36cb6949f482d0fd936a39dab69d6b34f43fff4dda8a9241f2c6e536c7\", \"directDependency\": false, \"description\": \"High:5,\", \"date\": \"2017-11-15\" }, { \"vulnerability\": { \"name\": \"CVE-2018-5968\", \"type\": \"CVE\", \"severity\": \"medium\", \"score\": 5.1, \"cvss3_severity\": \"high\", \"cvss3_score\": 8.1, \"scoreMetadataVector\": \"CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H\", \"publishDate\": \"2018-01-22\", \"url\": \"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-5968\", \"description\": \"FasterXML jackson-databind through 2.8.11 and 2.9.x through 2.9.3 allows unauthenticated remote code execution because of an incomplete fix for the CVE-2017-7525 and CVE-2017-17485 deserialization flaws. This is exploitable via two different gadgets that bypass a blacklist.\", \"topFix\": { \"vulnerability\": \"CVE-2018-5968\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\"," +
|
||||
"\"url\": \"https://github.com/FasterXML/jackson-databind/commit/038b471e2efde2e8f96b4e0be958d3e5a1ff1d05\", \"fixResolution\": \"src/main/java/com/fasterxml/jackson/databind/jsontype/impl/SubTypeValidator.java,release-notes/VERSION\", \"date\": \"2018-01-22\", \"message\": \"Fix #1899\", \"extraData\": \"key=038b471&committerName=cowtowncoder&committerUrl=https://github.com/cowtowncoder&committerAvatar=https://avatars0.githubusercontent.com/u/55065?v=4\" }, \"allFixes\": [], \"fixResolutionText\": \"Replace or update the following files: SubTypeValidator.java, VERSION\", \"references\": [] }, \"type\": \"SECURITY_VULNERABILITY\", \"level\": \"MAJOR\", \"library\": { \"keyUuid\": \"13f7802e-8aa1-4303-a5db-1d0c85e871a9\", \"keyId\": 23410061, \"filename\": \"jackson-databind-2.8.8.jar\", \"name\": \"jackson-databind\", \"groupId\": \"com.fasterxml.jackson.core\", \"artifactId\": \"jackson-databind\", \"version\": \"2.8.8\", \"sha1\": \"bf88c7b27e95cbadce4e7c316a56c3efffda8026\"," +
|
||||
"\"type\": \"Java\", \"references\": { \"url\": \"http://github.com/FasterXML/jackson\", \"issueUrl\": \"https://github.com/FasterXML/jackson-databind/issues\", \"pomUrl\": \"http://repo.jfrog.org/artifactory/list/repo1/com/fasterxml/jackson/core/jackson-databind/2.8.8/jackson-databind-2.8.8.pom\", \"scmUrl\": \"http://github.com/FasterXML/jackson-databind\" }, \"licenses\": [ { \"name\": \"Apache 2.0\", \"url\": \"http://apache.org/licenses/LICENSE-2.0\", \"profileInfo\": { \"copyrightRiskScore\": \"THREE\", \"patentRiskScore\": \"ONE\", \"copyleft\": \"NO\", \"linking\": \"DYNAMIC\", \"royaltyFree\": \"CONDITIONAL\" } } ] }, \"project\": \"pipeline-test - 0.0.1\", \"projectId\": 302194, \"projectToken\": \"1b8fdc36cb6949f482d0fd936a39dab69d6b34f43fff4dda8a9241f2c6e536c7\", \"directDependency\": false, \"description\": \"High:5,\", \"date\": \"2017-11-15\" }, { \"vulnerability\": { \"name\": \"CVE-2018-7489\", \"type\": \"CVE\", \"severity\": \"high\", \"score\": 7.5," +
|
||||
"\"cvss3_severity\": \"high\", \"cvss3_score\": 9.8, \"scoreMetadataVector\": \"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H\", \"publishDate\": \"2018-02-26\", \"url\": \"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-7489\", \"description\": \"FasterXML jackson-databind before 2.8.11.1 and 2.9.x before 2.9.5 allows unauthenticated remote code execution because of an incomplete fix for the CVE-2017-7525 deserialization flaw. This is exploitable by sending maliciously crafted JSON input to the readValue method of the ObjectMapper, bypassing a blacklist that is ineffective if the c3p0 libraries are available in the classpath.\", \"topFix\": { \"vulnerability\": \"CVE-2018-7489\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/FasterXML/jackson-databind/commit/6799f8f10cc78e9af6d443ed6982d00a13f2e7d2\", \"fixResolution\": \"src/main/java/com/fasterxml/jackson/databind/jsontype/impl/SubTypeValidator.java,src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java,src/test/java/com/mchange/v2/c3p0/jacksontest/ComboPooledDataSource.java,release-notes/VERSION\"," +
|
||||
"\"date\": \"2018-02-11\", \"message\": \"Fix #1931\", \"extraData\": \"key=6799f8f&committerName=cowtowncoder&committerUrl=https://github.com/cowtowncoder&committerAvatar=https://avatars0.githubusercontent.com/u/55065?v=4\" }, \"allFixes\": [], \"fixResolutionText\": \"Replace or update the following files: SubTypeValidator.java, IllegalTypesCheckTest.java, ComboPooledDataSource.java, VERSION\", \"references\": [] }, \"type\": \"SECURITY_VULNERABILITY\", \"level\": \"MAJOR\", \"library\": { \"keyUuid\": \"13f7802e-8aa1-4303-a5db-1d0c85e871a9\", \"keyId\": 23410061, \"filename\": \"jackson-databind-2.8.8.jar\", \"name\": \"jackson-databind\", \"groupId\": \"com.fasterxml.jackson.core\", \"artifactId\": \"jackson-databind\", \"version\": \"2.8.8\", \"sha1\": \"bf88c7b27e95cbadce4e7c316a56c3efffda8026\", \"type\": \"Java\", \"references\": { \"url\": \"http://github.com/FasterXML/jackson\", \"issueUrl\": \"https://github.com/FasterXML/jackson-databind/issues\"," +
|
||||
"\"pomUrl\": \"http://repo.jfrog.org/artifactory/list/repo1/com/fasterxml/jackson/core/jackson-databind/2.8.8/jackson-databind-2.8.8.pom\", \"scmUrl\": \"http://github.com/FasterXML/jackson-databind\" }, \"licenses\": [ { \"name\": \"Apache 2.0\", \"url\": \"http://apache.org/licenses/LICENSE-2.0\", \"profileInfo\": { \"copyrightRiskScore\": \"THREE\", \"patentRiskScore\": \"ONE\", \"copyleft\": \"NO\", \"linking\": \"DYNAMIC\", \"royaltyFree\": \"CONDITIONAL\" } } ] }, \"project\": \"pipeline-test - 0.0.1\", \"projectId\": 302194, \"projectToken\": \"1b8fdc36cb6949f482d0fd936a39dab69d6b34f43fff4dda8a9241f2c6e536c7\", \"directDependency\": false, \"description\": \"High:5,\", \"date\": \"2017-11-15\" }, { \"vulnerability\": { \"name\": \"CVE-2016-3720\", \"type\": \"CVE\", \"severity\": \"high\", \"score\": 7.5, \"cvss3_severity\": \"high\", \"cvss3_score\": 9.8, \"scoreMetadataVector\": \"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H\", \"publishDate\": \"2016-06-10\", \"url\": \"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-3720\"," +
|
||||
"\"description\": \"XML external entity (XXE) vulnerability in XmlMapper in the Data format extension for Jackson (aka jackson-dataformat-xml) allows attackers to have unspecified impact via unknown vectors.\", \"allFixes\": [], \"references\": [] }, \"type\": \"SECURITY_VULNERABILITY\", \"level\": \"MAJOR\", \"library\": { \"keyUuid\": \"9c7e7805-0ba0-480a-8647-ed0a457b4a88\", \"keyId\": 441802, \"filename\": \"jackson-dataformat-xml-2.4.2.jar\", \"name\": \"Jackson-dataformat-XML\", \"groupId\": \"com.fasterxml.jackson.dataformat\", \"artifactId\": \"jackson-dataformat-xml\", \"version\": \"2.4.2\", \"sha1\": \"02f2d96f68b2d3475452d95dde7a3fbee225f6ae\", \"type\": \"Java\", \"references\": { \"url\": \"http://wiki.fasterxml.com/JacksonExtensionXmlDataBinding\", \"issueUrl\": \"https://github.com/FasterXML/jackson-dataformat-xml/issues\", \"pomUrl\": \"http://maven.ibiblio.org/maven2/com/fasterxml/jackson/dataformat/jackson-dataformat-xml/2.4.2/jackson-dataformat-xml-2.4.2.pom\", \"scmUrl\": \"http://github.com/FasterXML/jackson-dataformat-xml\" }," +
|
||||
"\"licenses\": [ { \"name\": \"Apache 2.0\", \"url\": \"http://apache.org/licenses/LICENSE-2.0\", \"profileInfo\": { \"copyrightRiskScore\": \"THREE\", \"patentRiskScore\": \"ONE\", \"copyleft\": \"NO\", \"linking\": \"DYNAMIC\", \"royaltyFree\": \"CONDITIONAL\" } } ] }, \"project\": \"pipeline-test - 0.0.1\", \"projectId\": 302194, \"projectToken\": \"1b8fdc36cb6949f482d0fd936a39dab69d6b34f43fff4dda8a9241f2c6e536c7\", \"directDependency\": false, \"description\": \"High:1,\", \"date\": \"2017-10-26\" }, { \"vulnerability\": { \"name\": \"CVE-2017-5929\", \"type\": \"CVE\", \"severity\": \"high\", \"score\": 7.5, \"cvss3_severity\": \"high\", \"cvss3_score\": 9.8, \"scoreMetadataVector\": \"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H\", \"publishDate\": \"2017-03-13\", \"url\": \"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5929\", \"description\": \"QOS.ch Logback before 1.2.0 has a serialization vulnerability affecting the SocketServer and ServerSocketReceiver components.\", \"topFix\": { \"vulnerability\": \"CVE-2017-5929\"," +
|
||||
"\"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/qos-ch/logback/commit/f46044b805bca91efe5fd6afe52257cd02f775f8\", \"fixResolution\": \"logback-classic/src/main/java/ch/qos/logback/classic/net/server/LogbackClassicSerializationHelper.java,logback-core/src/test/java/ch/qos/logback/core/net/Innocent.java,logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java,logback-core/src/main/java/ch/qos/logback/core/net/HardenedObjectInputStream.java,logback-classic/src/test/java/ch/qos/logback/classic/LoggerSerializationTest.java,logback-core/src/test/java/ch/qos/logback/core/net/HardenedObjectInputStreamTest.java\", \"date\": \"2017-02-07\", \"message\": \"harden serialization\", \"extraData\": \"key=f46044b&committerName=ceki&committerUrl=https://github.com/ceki&committerAvatar=https://avatars1.githubusercontent.com/u/115476?v=4\" }, \"allFixes\": [ { \"vulnerability\": \"CVE-2017-5929\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\"," +
|
||||
"\"url\": \"https://github.com/qos-ch/logback/commit/f46044b805bca91efe5fd6afe52257cd02f775f8\", \"fixResolution\": \"logback-classic/src/main/java/ch/qos/logback/classic/net/server/LogbackClassicSerializationHelper.java,logback-core/src/test/java/ch/qos/logback/core/net/Innocent.java,logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java,logback-core/src/main/java/ch/qos/logback/core/net/HardenedObjectInputStream.java,logback-classic/src/test/java/ch/qos/logback/classic/LoggerSerializationTest.java,logback-core/src/test/java/ch/qos/logback/core/net/HardenedObjectInputStreamTest.java\", \"date\": \"2017-02-07\", \"message\": \"harden serialization\", \"extraData\": \"key=f46044b&committerName=ceki&committerUrl=https://github.com/ceki&committerAvatar=https://avatars1.githubusercontent.com/u/115476?v=4\" }, { \"vulnerability\": \"CVE-2017-5929\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/victims/victims-cve-db/commit/94745e07d4b10a58d98ffc3916d9711fa407b018\"," +
|
||||
"\"fixResolution\": \"database/java/2017/5929.yaml\", \"date\": \"2017-03-15\", \"message\": \"Added CVE-2017-5929 per issue #76\", \"extraData\": \"key=94745e0&committerName=cplvic&committerUrl=https://github.com/cplvic&committerAvatar=https://avatars0.githubusercontent.com/u/11528385?v=4\" } ], \"fixResolutionText\": \"Replace or update the following files: LogbackClassicSerializationHelper.java, Innocent.java, SimpleSocketServer.java, HardenedObjectInputStream.java, LoggerSerializationTest.java, HardenedObjectInputStreamTest.java\", \"references\": [] }, \"type\": \"SECURITY_VULNERABILITY\", \"level\": \"MAJOR\", \"library\": { \"keyUuid\": \"1259a151-8d7c-4921-b293-3b4b8708ac5e\", \"keyId\": 754707, \"filename\": \"logback-classic-1.1.3.jar\", \"name\": \"Logback Classic Module\", \"groupId\": \"ch.qos.logback\", \"artifactId\": \"logback-classic\", \"version\": \"1.1.3\", \"sha1\": \"d90276fff414f06cb375f2057f6778cd63c6082f\", \"type\": \"Java\", \"references\": { \"url\": \"http://logback.qos.ch/logback-classic\"," +
|
||||
"\"pomUrl\": \"http://maven.ibiblio.org/maven2/ch/qos/logback/logback-classic/1.1.3/logback-classic-1.1.3.pom\", \"scmUrl\": \"https://github.com/ceki/logback/logback-classic\" }, \"licenses\": [ { \"name\": \"LGPL 2.1\", \"url\": \"http://opensource.org/licenses/lgpl-2.1\", \"profileInfo\": { \"copyrightRiskScore\": \"FIVE\", \"patentRiskScore\": \"ONE\", \"copyleft\": \"PARTIAL\", \"linking\": \"DYNAMIC\", \"royaltyFree\": \"CONDITIONAL\" } }, { \"name\": \"Eclipse 1.0\", \"url\": \"http://opensource.org/licenses/eclipse-1.0.php\", \"profileInfo\": { \"copyrightRiskScore\": \"SIX\", \"patentRiskScore\": \"FOUR\", \"copyleft\": \"PARTIAL\", \"linking\": \"VIRAL\", \"royaltyFree\": \"CONDITIONAL\" } } ] }, \"project\": \"pipeline-test - 0.0.1\", \"projectId\": 302194, \"projectToken\": \"1b8fdc36cb6949f482d0fd936a39dab69d6b34f43fff4dda8a9241f2c6e536c7\", \"directDependency\": true, \"description\": \"High:1,\", \"date\": \"2017-10-26\" }, { \"vulnerability\": { \"name\": \"CVE-2017-5929\", \"type\": \"CVE\", \"severity\": \"high\"," +
|
||||
"\"score\": 7.5, \"cvss3_severity\": \"high\", \"cvss3_score\": 9.8, \"scoreMetadataVector\": \"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H\", \"publishDate\": \"2017-03-13\", \"url\": \"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5929\", \"description\": \"QOS.ch Logback before 1.2.0 has a serialization vulnerability affecting the SocketServer and ServerSocketReceiver components.\", \"topFix\": { \"vulnerability\": \"CVE-2017-5929\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/qos-ch/logback/commit/f46044b805bca91efe5fd6afe52257cd02f775f8\", \"fixResolution\": \"logback-classic/src/main/java/ch/qos/logback/classic/net/server/LogbackClassicSerializationHelper.java,logback-core/src/test/java/ch/qos/logback/core/net/Innocent.java,logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java,logback-core/src/main/java/ch/qos/logback/core/net/HardenedObjectInputStream.java,logback-classic/src/test/java/ch/qos/logback/classic/LoggerSerializationTest.java,logback-core/src/test/java/ch/qos/logback/core/net/HardenedObjectInputStreamTest.java\", \"date\": \"2017-02-07\"," +
|
||||
"\"message\": \"harden serialization\", \"extraData\": \"key=f46044b&committerName=ceki&committerUrl=https://github.com/ceki&committerAvatar=https://avatars1.githubusercontent.com/u/115476?v=4\" }, \"allFixes\": [ { \"vulnerability\": \"CVE-2017-5929\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/qos-ch/logback/commit/f46044b805bca91efe5fd6afe52257cd02f775f8\", \"fixResolution\": \"logback-classic/src/main/java/ch/qos/logback/classic/net/server/LogbackClassicSerializationHelper.java,logback-core/src/test/java/ch/qos/logback/core/net/Innocent.java,logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java,logback-core/src/main/java/ch/qos/logback/core/net/HardenedObjectInputStream.java,logback-classic/src/test/java/ch/qos/logback/classic/LoggerSerializationTest.java,logback-core/src/test/java/ch/qos/logback/core/net/HardenedObjectInputStreamTest.java\", \"date\": \"2017-02-07\", \"message\": \"harden serialization\", \"extraData\": \"key=f46044b&committerName=ceki&committerUrl=https://github.com/ceki&committerAvatar=https://avatars1.githubusercontent.com/u/115476?v=4\" }," +
|
||||
"{ \"vulnerability\": \"CVE-2017-5929\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/victims/victims-cve-db/commit/94745e07d4b10a58d98ffc3916d9711fa407b018\", \"fixResolution\": \"database/java/2017/5929.yaml\", \"date\": \"2017-03-15\", \"message\": \"Added CVE-2017-5929 per issue #76\", \"extraData\": \"key=94745e0&committerName=cplvic&committerUrl=https://github.com/cplvic&committerAvatar=https://avatars0.githubusercontent.com/u/11528385?v=4\" } ], \"fixResolutionText\": \"Replace or update the following files: LogbackClassicSerializationHelper.java, Innocent.java, SimpleSocketServer.java, HardenedObjectInputStream.java, LoggerSerializationTest.java, HardenedObjectInputStreamTest.java\", \"references\": [] }, \"type\": \"SECURITY_VULNERABILITY\", \"level\": \"MAJOR\", \"library\": { \"keyUuid\": \"d2b236f1-ac7d-4413-92fa-848cc7c3d3e5\", \"keyId\": 754708, \"filename\": \"logback-core-1.1.3.jar\", \"name\": \"Logback Core Module\", \"groupId\": \"ch.qos.logback\", \"artifactId\": \"logback-core\", \"version\": \"1.1.3\", \"sha1\": \"e3c02049f2dbbc764681b40094ecf0dcbc99b157\", \"type\": \"Java\"," +
|
||||
"\"references\": { \"url\": \"http://logback.qos.ch/logback-core\", \"pomUrl\": \"http://maven.ibiblio.org/maven2/ch/qos/logback/logback-core/1.1.3/logback-core-1.1.3.pom\", \"scmUrl\": \"https://github.com/ceki/logback/logback-core\" }, \"licenses\": [ { \"name\": \"Eclipse 1.0\", \"url\": \"http://opensource.org/licenses/eclipse-1.0.php\", \"profileInfo\": { \"copyrightRiskScore\": \"SIX\", \"patentRiskScore\": \"FOUR\", \"copyleft\": \"PARTIAL\", \"linking\": \"VIRAL\", \"royaltyFree\": \"CONDITIONAL\" } }, { \"name\": \"LGPL 2.1\", \"url\": \"http://opensource.org/licenses/lgpl-2.1\", \"profileInfo\": { \"copyrightRiskScore\": \"FIVE\", \"patentRiskScore\": \"ONE\", \"copyleft\": \"PARTIAL\", \"linking\": \"DYNAMIC\", \"royaltyFree\": \"CONDITIONAL\" } } ] }, \"project\": \"pipeline-test - 0.0.1\", \"projectId\": 302194, \"projectToken\": \"1b8fdc36cb6949f482d0fd936a39dab69d6b34f43fff4dda8a9241f2c6e536c7\", \"directDependency\": false, \"description\": \"High:1,\", \"date\": \"2017-10-26\" }, { \"vulnerability\": { \"name\": \"CVE-2012-4529\", \"type\": \"CVE\", \"severity\": \"medium\", \"score\": 4.3, \"cvss3_score\": 0," +
|
||||
"\"publishDate\": \"2013-10-28\", \"url\": \"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-4529\", \"description\": \"The org.apache.catalina.connector.Response.encodeURL method in Red Hat JBoss Web 7.1.x and earlier, when the tracking mode is set to COOKIE, sends the jsessionid in the URL of the first response of a session, which allows remote attackers to obtain the session id (1) via a man-in-the-middle attack or (2) by reading a log.\", \"allFixes\": [], \"references\": [] }, \"type\": \"SECURITY_VULNERABILITY\", \"level\": \"MAJOR\", \"library\": { \"keyUuid\": \"aa3a10d7-4e2c-46fe-bbf9-3c2d06e43b02\", \"keyId\": 24276785, \"filename\": \"tomcat-embed-core-7.0.78.jar\", \"name\": \"tomcat-embed-core\", \"groupId\": \"org.apache.tomcat.embed\", \"artifactId\": \"tomcat-embed-core\", \"version\": \"7.0.78\", \"sha1\": \"ddb63d615ec3944b4394aed6dc825cd0cbb16b21\", \"type\": \"Java\", \"references\": { \"url\": \"http://tomcat.apache.org/\", \"pomUrl\": \"http://repo.jfrog.org/artifactory/list/repo1/org/apache/tomcat/embed/tomcat-embed-core/7.0.78/tomcat-embed-core-7.0.78.pom\" }, \"licenses\": [ { \"name\": \"Apache 2.0\"," +
|
||||
"\"url\": \"http://apache.org/licenses/LICENSE-2.0\", \"profileInfo\": { \"copyrightRiskScore\": \"THREE\", \"patentRiskScore\": \"ONE\", \"copyleft\": \"NO\", \"linking\": \"DYNAMIC\", \"royaltyFree\": \"CONDITIONAL\" } } ] }, \"project\": \"pipeline-test - 0.0.1\", \"projectId\": 302194, \"projectToken\": \"1b8fdc36cb6949f482d0fd936a39dab69d6b34f43fff4dda8a9241f2c6e536c7\", \"directDependency\": true, \"description\": \"High:3,Medium:2,\", \"date\": \"2017-10-26\" }, { \"vulnerability\": { \"name\": \"CVE-2017-12615\", \"type\": \"CVE\", \"severity\": \"medium\", \"score\": 6.8, \"cvss3_severity\": \"high\", \"cvss3_score\": 8.1, \"scoreMetadataVector\": \"CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H\", \"publishDate\": \"2017-09-19\", \"url\": \"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-12615\", \"description\": \"When running Apache Tomcat 7.0.0 to 7.0.79 on Windows with HTTP PUTs enabled (e.g. via setting the readonly initialisation parameter of the Default to false) it was possible to upload a JSP file to the server via a specially crafted request. This JSP could then be requested and any code it contained would be executed by the server.\"," +
|
||||
"\"topFix\": { \"vulnerability\": \"CVE-2017-12615\", \"type\": \"UPGRADE_VERSION\", \"origin\": \"SECURITY_TRACKER\", \"url\": \"http://www.securitytracker.com/id/1039392\", \"fixResolution\": \"The vendor has issued a fix (7.0.81).\\n\\nThe vendor advisory is available at:\\n\\nhttps://tomcat.apache.org/security-7.html#Fixed_in_Apache_Tomcat_7.0.81\", \"date\": \"2017-12-31\", \"message\": \"Apache Tomcat on Windows HTTP PUT Request Processing Flaw Lets Remote Users Execute Arbitrary Code on the Target System\", \"extraData\": \"key=1039392\" }, \"allFixes\": [ { \"vulnerability\": \"CVE-2017-12615\", \"type\": \"UPGRADE_VERSION\", \"origin\": \"SECURITY_TRACKER\", \"url\": \"http://www.securitytracker.com/id/1039392\", \"fixResolution\": \"The vendor has issued a fix (7.0.81).\\n\\nThe vendor advisory is available at:\\n\\nhttps://tomcat.apache.org/security-7.html#Fixed_in_Apache_Tomcat_7.0.81\", \"date\": \"2017-12-31\", \"message\": \"Apache Tomcat on Windows HTTP PUT Request Processing Flaw Lets Remote Users Execute Arbitrary Code on the Target System\", \"extraData\": \"key=1039392\" }, { \"vulnerability\": \"CVE-2017-12615\", \"type\": \"CHANGE_FILES\"," +
|
||||
"\"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/apache/tomcat70/commit/07dc0ea2745f0afab6415f22b16a29f1c6de5727\", \"fixResolution\": \"java/org/apache/naming/resources/VirtualDirContext.java,webapps/docs/changelog.xml,java/org/apache/naming/resources/FileDirContext.java\", \"date\": \"2017-08-10\", \"message\": \"Correct regression in r1804604 that broke WebDAV.\\n\\ngit-svn-id: https://svn.apache.org/repos/asf/tomcat/tc7.0.x/trunk@1804729 13f79535-47bb-0310-9956-ffa450edef68\", \"extraData\": \"key=07dc0ea&committerName=markt-asf&committerUrl=https://github.com/markt-asf&committerAvatar=https://avatars3.githubusercontent.com/u/4690029?v=4\" } ], \"fixResolutionText\": \"The vendor has issued a fix (7.0.81).\\n\\nThe vendor advisory is available at:\\n\\nhttps://tomcat.apache.org/security-7.html#Fixed_in_Apache_Tomcat_7.0.81\", \"references\": [] }, \"type\": \"SECURITY_VULNERABILITY\", \"level\": \"MAJOR\", \"library\": { \"keyUuid\": \"aa3a10d7-4e2c-46fe-bbf9-3c2d06e43b02\", \"keyId\": 24276785, \"filename\": \"tomcat-embed-core-7.0.78.jar\", \"name\": \"tomcat-embed-core\", \"groupId\": \"org.apache.tomcat.embed\", \"artifactId\": \"tomcat-embed-core\"," +
|
||||
"\"version\": \"7.0.78\", \"sha1\": \"ddb63d615ec3944b4394aed6dc825cd0cbb16b21\", \"type\": \"Java\", \"references\": { \"url\": \"http://tomcat.apache.org/\", \"pomUrl\": \"http://repo.jfrog.org/artifactory/list/repo1/org/apache/tomcat/embed/tomcat-embed-core/7.0.78/tomcat-embed-core-7.0.78.pom\" }, \"licenses\": [ { \"name\": \"Apache 2.0\", \"url\": \"http://apache.org/licenses/LICENSE-2.0\", \"profileInfo\": { \"copyrightRiskScore\": \"THREE\", \"patentRiskScore\": \"ONE\", \"copyleft\": \"NO\", \"linking\": \"DYNAMIC\", \"royaltyFree\": \"CONDITIONAL\" } } ] }, \"project\": \"pipeline-test - 0.0.1\", \"projectId\": 302194, \"projectToken\": \"1b8fdc36cb6949f482d0fd936a39dab69d6b34f43fff4dda8a9241f2c6e536c7\", \"directDependency\": true, \"description\": \"High:3,Medium:2,\", \"date\": \"2017-10-26\" }, { \"vulnerability\": { \"name\": \"CVE-2017-12616\", \"type\": \"CVE\", \"severity\": \"medium\", \"score\": 5, \"cvss3_severity\": \"high\", \"cvss3_score\": 7.5, \"scoreMetadataVector\": \"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N\", \"publishDate\": \"2017-09-19\", \"url\": \"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-12616\"," +
|
||||
"\"description\": \"When using a VirtualDirContext with Apache Tomcat 7.0.0 to 7.0.80 it was possible to bypass security constraints and/or view the source code of JSPs for resources served by the VirtualDirContext using a specially crafted request.\", \"topFix\": { \"vulnerability\": \"CVE-2017-12616\", \"type\": \"UPGRADE_VERSION\", \"origin\": \"SECURITY_TRACKER\", \"url\": \"http://www.securitytracker.com/id/1039393\", \"fixResolution\": \"The vendor has issued a fix (7.0.81).\\n\\nThe vendor advisory is available at:\\n\\nhttps://tomcat.apache.org/security-7.html#Fixed_in_Apache_Tomcat_7.0.81\", \"date\": \"2017-12-31\", \"message\": \"Apache Tomcat VirtualDirContext Flaw Lets Remote Users View JSP Source Code for the Affected Resource\", \"extraData\": \"key=1039393\" }, \"allFixes\": [ { \"vulnerability\": \"CVE-2017-12616\", \"type\": \"UPGRADE_VERSION\", \"origin\": \"SECURITY_TRACKER\", \"url\": \"http://www.securitytracker.com/id/1039393\", \"fixResolution\": \"The vendor has issued a fix (7.0.81).\\n\\nThe vendor advisory is available at:\\n\\nhttps://tomcat.apache.org/security-7.html#Fixed_in_Apache_Tomcat_7.0.81\", \"date\": \"2017-12-31\"," +
|
||||
"\"message\": \"Apache Tomcat VirtualDirContext Flaw Lets Remote Users View JSP Source Code for the Affected Resource\", \"extraData\": \"key=1039393\" }, { \"vulnerability\": \"CVE-2017-12616\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/apache/tomcat70/commit/07dc0ea2745f0afab6415f22b16a29f1c6de5727\", \"fixResolution\": \"java/org/apache/naming/resources/VirtualDirContext.java,webapps/docs/changelog.xml,java/org/apache/naming/resources/FileDirContext.java\", \"date\": \"2017-08-10\", \"message\": \"Correct regression in r1804604 that broke WebDAV.\\n\\ngit-svn-id: https://svn.apache.org/repos/asf/tomcat/tc7.0.x/trunk@1804729 13f79535-47bb-0310-9956-ffa450edef68\", \"extraData\": \"key=07dc0ea&committerName=markt-asf&committerUrl=https://github.com/markt-asf&committerAvatar=https://avatars3.githubusercontent.com/u/4690029?v=4\" } ], \"fixResolutionText\": \"The vendor has issued a fix (7.0.81).\\n\\nThe vendor advisory is available at:\\n\\nhttps://tomcat.apache.org/security-7.html#Fixed_in_Apache_Tomcat_7.0.81\", \"references\": [] }, \"type\": \"SECURITY_VULNERABILITY\", \"level\": \"MAJOR\"," +
|
||||
"\"library\": { \"keyUuid\": \"aa3a10d7-4e2c-46fe-bbf9-3c2d06e43b02\", \"keyId\": 24276785, \"filename\": \"tomcat-embed-core-7.0.78.jar\", \"name\": \"tomcat-embed-core\", \"groupId\": \"org.apache.tomcat.embed\", \"artifactId\": \"tomcat-embed-core\", \"version\": \"7.0.78\", \"sha1\": \"ddb63d615ec3944b4394aed6dc825cd0cbb16b21\", \"type\": \"Java\", \"references\": { \"url\": \"http://tomcat.apache.org/\", \"pomUrl\": \"http://repo.jfrog.org/artifactory/list/repo1/org/apache/tomcat/embed/tomcat-embed-core/7.0.78/tomcat-embed-core-7.0.78.pom\" }, \"licenses\": [ { \"name\": \"Apache 2.0\", \"url\": \"http://apache.org/licenses/LICENSE-2.0\", \"profileInfo\": { \"copyrightRiskScore\": \"THREE\", \"patentRiskScore\": \"ONE\", \"copyleft\": \"NO\", \"linking\": \"DYNAMIC\", \"royaltyFree\": \"CONDITIONAL\" } } ] }, \"project\": \"pipeline-test - 0.0.1\", \"projectId\": 302194, \"projectToken\": \"1b8fdc36cb6949f482d0fd936a39dab69d6b34f43fff4dda8a9241f2c6e536c7\", \"directDependency\": true, \"description\": \"High:3,Medium:2,\", \"date\": \"2017-10-26\" }, { \"vulnerability\": { \"name\": \"CVE-2017-7674\", \"type\": \"CVE\", \"severity\": \"medium\", \"score\": 4.3," +
|
||||
"\"cvss3_severity\": \"medium\", \"cvss3_score\": 4.3, \"scoreMetadataVector\": \"CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N\", \"publishDate\": \"2017-08-11\", \"url\": \"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-7674\", \"description\": \"The CORS Filter in Apache Tomcat 9.0.0.M1 to 9.0.0.M21, 8.5.0 to 8.5.15, 8.0.0.RC1 to 8.0.44 and 7.0.41 to 7.0.78 did not add an HTTP Vary header indicating that the response varies depending on Origin. This permitted client and server side cache poisoning in some circumstances.\", \"topFix\": { \"vulnerability\": \"CVE-2017-7674\", \"type\": \"UPGRADE_VERSION\", \"origin\": \"BUGZILLA\", \"url\": \"https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2017-7674\", \"fixResolution\": \"tomcat 7.0.79,tomcat 8.0.45,tomcat 8.5.16\", \"message\": \"CVE-2017-7674 tomcat: Vary header not added by CORS filter leading to cache poisoning\", \"extraData\": \"key=1480618&assignee=Red Hat Product Security\" }, \"allFixes\": [ { \"vulnerability\": \"CVE-2017-7674\", \"type\": \"UPGRADE_VERSION\", \"origin\": \"BUGZILLA\", \"url\": \"https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2017-7674\"," +
|
||||
"\"fixResolution\": \"tomcat 7.0.79,tomcat 8.0.45,tomcat 8.5.16\", \"message\": \"CVE-2017-7674 tomcat: Vary header not added by CORS filter leading to cache poisoning\", \"extraData\": \"key=1480618&assignee=Red Hat Product Security\" }, { \"vulnerability\": \"CVE-2017-7674\", \"type\": \"UPGRADE_VERSION\", \"origin\": \"BUGZILLA\", \"url\": \"https://bugzilla.redhat.com/show_bug.cgi?id=1480618\", \"fixResolution\": \"tomcat 7.0.79,tomcat 8.0.45,tomcat 8.5.16\", \"message\": \"CVE-2017-7674 tomcat: Vary header not added by CORS filter leading to cache poisoning\", \"extraData\": \"key=1480618&assignee=Red Hat Product Security\" }, { \"vulnerability\": \"CVE-2017-7674\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/apache/tomcat/commit/b94478d45b7e1fc06134a785571f78772fa30fed\", \"fixResolution\": \"java/org/apache/catalina/filters/CorsFilter.java,webapps/docs/changelog.xml\", \"date\": \"2017-05-22\", \"message\": \"BZ61101: CORS filter should set Vary header in response. Submitted by Rick Riemer.\\n\\ngit-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1795813 13f79535-47bb-0310-9956-ffa450edef68\"," +
|
||||
"\"extraData\": \"key=b94478d&committerName=rmaucher&committerUrl=https://github.com/rmaucher&committerAvatar=https://avatars2.githubusercontent.com/u/324250?v=4\" }, { \"vulnerability\": \"CVE-2017-7674\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/apache/tomcat85/commit/9044c1672bbe4b2cf4c55028cc8b977cc62650e7\", \"fixResolution\": \"java/org/apache/catalina/filters/CorsFilter.java,webapps/docs/changelog.xml\", \"date\": \"2017-05-22\", \"message\": \"BZ61101: CORS filter should set Vary header in response. Submitted by Rick Riemer.\\n\\ngit-svn-id: https://svn.apache.org/repos/asf/tomcat/tc8.5.x/trunk@1795814 13f79535-47bb-0310-9956-ffa450edef68\", \"extraData\": \"key=9044c16&committerName=rmaucher&committerUrl=https://github.com/rmaucher&committerAvatar=https://avatars2.githubusercontent.com/u/324250?v=4\" }, { \"vulnerability\": \"CVE-2017-7674\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/apache/tomcat70/commit/52382ebfbce20a98b01cd9d37184a12703987a5a\", \"fixResolution\": \"java/org/apache/catalina/filters/CorsFilter.java,webapps/docs/changelog.xml\"," +
|
||||
"\"date\": \"2017-05-22\", \"message\": \"BZ61101: CORS filter should set Vary header in response. Submitted by Rick Riemer.\\n\\ngit-svn-id: https://svn.apache.org/repos/asf/tomcat/tc7.0.x/trunk@1795816 13f79535-47bb-0310-9956-ffa450edef68\", \"extraData\": \"key=52382eb&committerName=rmaucher&committerUrl=https://github.com/rmaucher&committerAvatar=https://avatars2.githubusercontent.com/u/324250?v=4\" }, { \"vulnerability\": \"CVE-2017-7674\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/apache/tomcat80/commit/f52c242d92d4563dd1226dcc993ec37370ba9ce3\", \"fixResolution\": \"java/org/apache/catalina/filters/CorsFilter.java,webapps/docs/changelog.xml\", \"date\": \"2017-05-22\", \"message\": \"BZ61101: CORS filter should set Vary header in response. Submitted by Rick Riemer.\\n\\ngit-svn-id: https://svn.apache.org/repos/asf/tomcat/tc8.0.x/trunk@1795815 13f79535-47bb-0310-9956-ffa450edef68\", \"extraData\": \"key=f52c242&committerName=rmaucher&committerUrl=https://github.com/rmaucher&committerAvatar=https://avatars2.githubusercontent.com/u/324250?v=4\" } ], \"fixResolutionText\": \"Upgrade to version tomcat 7.0.79, tomcat 8.0.45, tomcat 8.5.16 or greater\"," +
|
||||
"\"references\": [] }, \"type\": \"SECURITY_VULNERABILITY\", \"level\": \"MAJOR\", \"library\": { \"keyUuid\": \"aa3a10d7-4e2c-46fe-bbf9-3c2d06e43b02\", \"keyId\": 24276785, \"filename\": \"tomcat-embed-core-7.0.78.jar\", \"name\": \"tomcat-embed-core\", \"groupId\": \"org.apache.tomcat.embed\", \"artifactId\": \"tomcat-embed-core\", \"version\": \"7.0.78\", \"sha1\": \"ddb63d615ec3944b4394aed6dc825cd0cbb16b21\", \"type\": \"Java\", \"references\": { \"url\": \"http://tomcat.apache.org/\", \"pomUrl\": \"http://repo.jfrog.org/artifactory/list/repo1/org/apache/tomcat/embed/tomcat-embed-core/7.0.78/tomcat-embed-core-7.0.78.pom\" }, \"licenses\": [ { \"name\": \"Apache 2.0\", \"url\": \"http://apache.org/licenses/LICENSE-2.0\", \"profileInfo\": { \"copyrightRiskScore\": \"THREE\", \"patentRiskScore\": \"ONE\", \"copyleft\": \"NO\", \"linking\": \"DYNAMIC\", \"royaltyFree\": \"CONDITIONAL\" } } ] }, \"project\": \"pipeline-test - 0.0.1\", \"projectId\": 302194, \"projectToken\": \"1b8fdc36cb6949f482d0fd936a39dab69d6b34f43fff4dda8a9241f2c6e536c7\", \"directDependency\": true, \"description\": \"High:3,Medium:2,\", \"date\": \"2017-10-26\" }, { \"vulnerability\": { \"name\": \"CVE-2018-8014\"," +
|
||||
"\"type\": \"CVE\", \"severity\": \"high\", \"score\": 7.5, \"cvss3_severity\": \"high\", \"cvss3_score\": 9.8, \"scoreMetadataVector\": \"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H\", \"publishDate\": \"2018-05-16\", \"url\": \"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-8014\", \"description\": \"The defaults settings for the CORS filter provided in Apache Tomcat 9.0.0.M1 to 9.0.8, 8.5.0 to 8.5.31, 8.0.0.RC1 to 8.0.52, 7.0.41 to 7.0.88 are insecure and enable 'supportsCredentials' for all origins. It is expected that users of the CORS filter will have configured it appropriately for their environment rather than using it in the default configuration. Therefore, it is expected that most users will not be impacted by this issue.\", \"topFix\": { \"vulnerability\": \"CVE-2018-8014\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/apache/tomcat70/commit/5877390a9605f56d9bd6859a54ccbfb16374a78b\", \"fixResolution\": \"java/org/apache/catalina/filters/LocalStrings.properties,test/org/apache/catalina/filters/TestCorsFilter.java,java/org/apache/catalina/filters/CorsFilter.java,webapps/docs/changelog.xml,test/org/apache/catalina/filters/TesterFilterConfigs.java\"," +
|
||||
"\"date\": \"2018-05-16\", \"message\": \"Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=62343\\nMake CORS filter defaults more secure.\\nThis is the fix for CVE-2018-8014.\\n\\ngit-svn-id: https://svn.apache.org/repos/asf/tomcat/tc7.0.x/trunk@1831730 13f79535-47bb-0310-9956-ffa450edef68\", \"extraData\": \"key=5877390&committerName=markt-asf&committerUrl=https://github.com/markt-asf&committerAvatar=https://avatars3.githubusercontent.com/u/4690029?v=4\" }, \"allFixes\": [ { \"vulnerability\": \"CVE-2018-8014\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/apache/tomcat70/commit/5877390a9605f56d9bd6859a54ccbfb16374a78b\", \"fixResolution\": \"java/org/apache/catalina/filters/LocalStrings.properties,test/org/apache/catalina/filters/TestCorsFilter.java,java/org/apache/catalina/filters/CorsFilter.java,webapps/docs/changelog.xml,test/org/apache/catalina/filters/TesterFilterConfigs.java\", \"date\": \"2018-05-16\", \"message\": \"Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=62343\\nMake CORS filter defaults more secure.\\nThis is the fix for CVE-2018-8014.\\n\\ngit-svn-id: https://svn.apache.org/repos/asf/tomcat/tc7.0.x/trunk@1831730 13f79535-47bb-0310-9956-ffa450edef68\"," +
|
||||
"\"extraData\": \"key=5877390&committerName=markt-asf&committerUrl=https://github.com/markt-asf&committerAvatar=https://avatars3.githubusercontent.com/u/4690029?v=4\" }, { \"vulnerability\": \"CVE-2018-8014\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/apache/tomcat80/commit/2c9d8433bd3247a2856d4b2555447108758e813e#diff-32f241c95d21b1b224601e52f83af334\", \"fixResolution\": \"java/org/apache/catalina/filters/LocalStrings.properties,test/org/apache/catalina/filters/TestCorsFilter.java,java/org/apache/catalina/filters/CorsFilter.java,webapps/docs/changelog.xml,test/org/apache/catalina/filters/TesterFilterConfigs.java\", \"date\": \"2018-05-16\", \"message\": \"Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=62343\\nMake CORS filter defaults more secure.\\nThis is the fix for CVE-2018-8014.\\n\\ngit-svn-id: https://svn.apache.org/repos/asf/tomcat/tc8.0.x/trunk@1831729 13f79535-47bb-0310-9956-ffa450edef68\", \"extraData\": \"key=2c9d843&committerName=markt-asf&committerUrl=https://github.com/markt-asf&committerAvatar=https://avatars3.githubusercontent.com/u/4690029?v=4\" }, { \"vulnerability\": \"CVE-2018-8014\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\"," +
|
||||
"\"url\": \"https://github.com/apache/tomcat/commit/d83a76732e6804739b81d8b2056365307637b42d\", \"fixResolution\": \"java/org/apache/catalina/filters/LocalStrings.properties,test/org/apache/catalina/filters/TestCorsFilter.java,java/org/apache/catalina/filters/CorsFilter.java,webapps/docs/changelog.xml,test/org/apache/catalina/filters/TesterFilterConfigs.java\", \"date\": \"2018-05-16\", \"message\": \"Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=62343\\nMake CORS filter defaults more secure.\\nThis is the fix for CVE-2018-8014.\\n\\ngit-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1831726 13f79535-47bb-0310-9956-ffa450edef68\", \"extraData\": \"key=d83a767&committerName=markt-asf&committerUrl=https://github.com/markt-asf&committerAvatar=https://avatars3.githubusercontent.com/u/4690029?v=4\" }, { \"vulnerability\": \"CVE-2018-8014\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/apache/tomcat85/commit/60f596a21fd6041335a3a1a4015d4512439cecb5\", \"fixResolution\": \"java/org/apache/catalina/filters/LocalStrings.properties,test/org/apache/catalina/filters/TestCorsFilter.java,java/org/apache/catalina/filters/CorsFilter.java,webapps/docs/changelog.xml,test/org/apache/catalina/filters/TesterFilterConfigs.java\"," +
|
||||
"\"date\": \"2018-05-16\", \"message\": \"Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=62343\\nMake CORS filter defaults more secure.\\nThis is the fix for CVE-2018-8014.\\n\\ngit-svn-id: https://svn.apache.org/repos/asf/tomcat/tc8.5.x/trunk@1831728 13f79535-47bb-0310-9956-ffa450edef68\", \"extraData\": \"key=60f596a&committerName=markt-asf&committerUrl=https://github.com/markt-asf&committerAvatar=https://avatars3.githubusercontent.com/u/4690029?v=4\" } ], \"fixResolutionText\": \"Replace or update the following files: LocalStrings.properties, TestCorsFilter.java, CorsFilter.java, changelog.xml, TesterFilterConfigs.java\", \"references\": [] }, \"type\": \"SECURITY_VULNERABILITY\", \"level\": \"MAJOR\", \"library\": { \"keyUuid\": \"aa3a10d7-4e2c-46fe-bbf9-3c2d06e43b02\", \"keyId\": 24276785, \"filename\": \"tomcat-embed-core-7.0.78.jar\", \"name\": \"tomcat-embed-core\", \"groupId\": \"org.apache.tomcat.embed\", \"artifactId\": \"tomcat-embed-core\", \"version\": \"7.0.78\", \"sha1\": \"ddb63d615ec3944b4394aed6dc825cd0cbb16b21\", \"type\": \"Java\", \"references\": { \"url\": \"http://tomcat.apache.org/\", \"pomUrl\": \"http://repo.jfrog.org/artifactory/list/repo1/org/apache/tomcat/embed/tomcat-embed-core/7.0.78/tomcat-embed-core-7.0.78.pom\" }," +
|
||||
"\"licenses\": [ { \"name\": \"Apache 2.0\", \"url\": \"http://apache.org/licenses/LICENSE-2.0\", \"profileInfo\": { \"copyrightRiskScore\": \"THREE\", \"patentRiskScore\": \"ONE\", \"copyleft\": \"NO\", \"linking\": \"DYNAMIC\", \"royaltyFree\": \"CONDITIONAL\" } } ] }, \"project\": \"pipeline-test - 0.0.1\", \"projectId\": 302194, \"projectToken\": \"1b8fdc36cb6949f482d0fd936a39dab69d6b34f43fff4dda8a9241f2c6e536c7\", \"directDependency\": true, \"description\": \"High:3,Medium:2,\", \"date\": \"2017-10-26\" } ] }").alerts
|
||||
})
|
||||
|
||||
thrown.expect(AbortException.class)
|
||||
|
||||
stepRule.step.whitesourceExecuteScan([
|
||||
script : nullScript,
|
||||
scanType : 'npm',
|
||||
juStabUtils : utils,
|
||||
securityVulnerabilities : true,
|
||||
whitesourceRepositoryStub : whitesourceStub,
|
||||
whitesourceOrgAdminRepositoryStub : whitesourceOrgAdminRepositoryStub,
|
||||
orgToken : 'testOrgToken',
|
||||
productName : 'SHC - Piper',
|
||||
projectNames : [ 'piper-demo - 0.0.1' ]
|
||||
])
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCheckFindingBelowSeven() {
|
||||
helper.registerAllowedMethod("readProperties", [Map], {
|
||||
def result = new Properties()
|
||||
result.putAll([
|
||||
"apiKey": "b39d1328-52e2-42e3-98f0-932709daf3f0",
|
||||
"productName": "SHC - Piper",
|
||||
"checkPolicies": "true",
|
||||
"projectName": "pipeline-test-node",
|
||||
"projectVersion": "1.0.0"
|
||||
])
|
||||
return result
|
||||
})
|
||||
helper.registerAllowedMethod("fetchVulnerabilities", [Object.class], {
|
||||
return new JsonUtils().parseJsonSerializable("{ \"alerts\": [ { \"vulnerability\": { \"name\": \"CVE-2017-15095\", \"type\": \"CVE\", \"severity\": \"high\", \"score\": 2.1, \"cvss3_severity\": \"high\", \"cvss3_score\": 5.3, \"scoreMetadataVector\": \"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H\", \"publishDate\": \"2018-02-06\", \"url\": \"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-15095\", \"description\": \"A deserialization flaw was discovered in the jackson-databind in versions before 2.8.10 and 2.9.1, which could allow an unauthenticated user to perform code execution by sending the maliciously crafted input to the readValue method of the ObjectMapper. This issue extends the previous flaw CVE-2017-7525 by blacklisting more classes that could be used maliciously.\", \"topFix\": { \"vulnerability\": \"CVE-2017-15095\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/FasterXML/jackson-databind/commit/60d459ce\"," +
|
||||
"\"fixResolution\": \"src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java,release-notes/VERSION,src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java\", \"date\": \"2017-04-13\", \"message\": \"Fix #1599 for 2.8.9\\n\\nMerge branch '2.7' into 2.8\", \"extraData\": \"key=60d459c&committerName=cowtowncoder&committerUrl=https://github.com/cowtowncoder&committerAvatar=https://avatars0.githubusercontent.com/u/55065?v=4\" }, \"allFixes\": [ { \"vulnerability\": \"CVE-2017-15095\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/FasterXML/jackson-databind/commit/60d459ce\", \"fixResolution\": \"src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java,release-notes/VERSION,src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java\", \"date\": \"2017-04-13\", \"message\": \"Fix #1599 for 2.8.9\\n\\nMerge branch '2.7' into 2.8\"," +
|
||||
"\"extraData\": \"key=60d459c&committerName=cowtowncoder&committerUrl=https://github.com/cowtowncoder&committerAvatar=https://avatars0.githubusercontent.com/u/55065?v=4\" }, { \"vulnerability\": \"CVE-2017-15095\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\", \"url\": \"https://github.com/FasterXML/jackson-databind/commit/e865a7a4464da63ded9f4b1a2328ad85c9ded78b#diff-98084d808198119d550a9211e128a16f\", \"fixResolution\": \"src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java,release-notes/VERSION,src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java\", \"date\": \"2017-12-12\", \"message\": \"Fix #1737 (#1857)\", \"extraData\": \"key=e865a7a&committerName=cowtowncoder&committerUrl=https://github.com/cowtowncoder&committerAvatar=https://avatars0.githubusercontent.com/u/55065?v=4\" }, { \"vulnerability\": \"CVE-2017-15095\", \"type\": \"CHANGE_FILES\", \"origin\": \"GITHUB_COMMIT\"," +
|
||||
"\"url\": \"https://github.com/FasterXML/jackson-databind/commit/e8f043d1\", \"fixResolution\": \"release-notes/VERSION,src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java\", \"date\": \"2017-06-30\", \"message\": \"Fix #1680\", \"extraData\": \"key=e8f043d&committerName=cowtowncoder&committerUrl=https://github.com/cowtowncoder&committerAvatar=https://avatars0.githubusercontent.com/u/55065?v=4\" } ], \"fixResolutionText\": \"Replace or update the following files: IllegalTypesCheckTest.java, VERSION, BeanDeserializerFactory.java\", \"references\": [] }, \"type\": \"SECURITY_VULNERABILITY\", \"level\": \"MAJOR\", \"library\": { \"keyUuid\": \"13f7802e-8aa1-4303-a5db-1d0c85e871a9\", \"keyId\": 23410061, \"filename\": \"jackson-databind-2.8.8.jar\", \"name\": \"jackson-databind\", \"groupId\": \"com.fasterxml.jackson.core\", \"artifactId\": \"jackson-databind\", \"version\": \"2.8.8\", \"sha1\": \"bf88c7b27e95cbadce4e7c316a56c3efffda8026\"," +
|
||||
"\"type\": \"Java\", \"references\": { \"url\": \"http://github.com/FasterXML/jackson\", \"issueUrl\": \"https://github.com/FasterXML/jackson-databind/issues\", \"pomUrl\": \"http://repo.jfrog.org/artifactory/list/repo1/com/fasterxml/jackson/core/jackson-databind/2.8.8/jackson-databind-2.8.8.pom\", \"scmUrl\": \"http://github.com/FasterXML/jackson-databind\" }, \"licenses\": [ { \"name\": \"Apache 2.0\", \"url\": \"http://apache.org/licenses/LICENSE-2.0\", \"profileInfo\": { \"copyrightRiskScore\": \"THREE\", \"patentRiskScore\": \"ONE\", \"copyleft\": \"NO\", \"linking\": \"DYNAMIC\", \"royaltyFree\": \"CONDITIONAL\" } } ] }, \"project\": \"pipeline-test - 0.0.1\", \"projectId\": 302194, \"projectToken\": \"1b8fdc36cb6949f482d0fd936a39dab69d6b34f43fff4dda8a9241f2c6e536c7\", \"directDependency\": false, \"description\": \"High:5,\", \"date\": \"2017-11-15\" } ] }").alerts
|
||||
})
|
||||
|
||||
stepRule.step.whitesourceExecuteScan([
|
||||
script : nullScript,
|
||||
whitesourceRepositoryStub : whitesourceStub,
|
||||
whitesourceOrgAdminRepositoryStub : whitesourceOrgAdminRepositoryStub,
|
||||
scanType : 'npm',
|
||||
juStabUtils : utils,
|
||||
securityVulnerabilities : true,
|
||||
orgToken : 'testOrgToken',
|
||||
productName : 'SHC - Piper',
|
||||
projectNames : [ 'piper-demo - 0.0.1' ]
|
||||
])
|
||||
|
||||
assertThat(loggingRule.log, containsString('WARNING: 1 Open Source Software Security vulnerabilities with CVSS score below 7.0 detected.'))
|
||||
assertThat(writeFileRule.files['piper_whitesource_vulnerability_report.json'], not(isEmptyOrNullString()))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCheckNoFindings() {
|
||||
helper.registerAllowedMethod("readProperties", [Map], {
|
||||
def result = new Properties()
|
||||
result.putAll([
|
||||
"apiKey": "b39d1328-52e2-42e3-98f0-932709daf3f0",
|
||||
"productName": "SHC - Piper",
|
||||
"checkPolicies": "true",
|
||||
"projectName": "pipeline-test-node",
|
||||
"projectVersion": "1.0.0"
|
||||
])
|
||||
return result
|
||||
})
|
||||
helper.registerAllowedMethod("fetchVulnerabilities", [Object.class], {
|
||||
return new JsonUtils().parseJsonSerializable("{ \"alerts\": [] }").alerts
|
||||
})
|
||||
|
||||
stepRule.step.whitesourceExecuteScan([
|
||||
script : nullScript,
|
||||
whitesourceRepositoryStub : whitesourceStub,
|
||||
whitesourceOrgAdminRepositoryStub : whitesourceOrgAdminRepositoryStub,
|
||||
scanType : 'npm',
|
||||
juStabUtils : utils,
|
||||
securityVulnerabilities : true,
|
||||
orgToken : 'testOrgToken',
|
||||
productName : 'SHC - Piper',
|
||||
projectNames : [ 'piper-demo - 0.0.1' ]
|
||||
])
|
||||
|
||||
assertThat(loggingRule.log, containsString('No Open Source Software Security vulnerabilities detected.'))
|
||||
assertThat(writeFileRule.files['piper_whitesource_vulnerability_report.json'], not(isEmptyOrNullString()))
|
||||
}
|
||||
}
|
347
vars/whitesourceExecuteScan.groovy
Normal file
347
vars/whitesourceExecuteScan.groovy
Normal file
@ -0,0 +1,347 @@
|
||||
import com.sap.piper.JsonUtils
|
||||
import com.sap.piper.Utils
|
||||
import com.sap.piper.integration.WhitesourceOrgAdminRepository
|
||||
import com.sap.piper.integration.WhitesourceRepository
|
||||
import com.sap.piper.ConfigurationHelper
|
||||
import com.sap.piper.WhitesourceConfigurationHelper
|
||||
import com.sap.piper.mta.MtaMultiplexer
|
||||
import groovy.text.GStringTemplateEngine
|
||||
import groovy.transform.Field
|
||||
import groovy.text.SimpleTemplateEngine
|
||||
|
||||
import static com.sap.piper.Prerequisites.checkScript
|
||||
|
||||
@Field String STEP_NAME = 'whitesourceExecuteScan'
|
||||
@Field Set GENERAL_CONFIG_KEYS = [
|
||||
'agentDownloadUrl',
|
||||
'agentFileName',
|
||||
'agentParameters',
|
||||
'artifactUrl',
|
||||
'buildDescriptorExcludeList',
|
||||
'buildDescriptorFile',
|
||||
'configFilePath',
|
||||
'dockerImage',
|
||||
'dockerWorkspace',
|
||||
'internalServiceUrl',
|
||||
'jreDownloadUrl',
|
||||
'licensingVulnerabilities',
|
||||
'orgToken',
|
||||
'parallelLimit',
|
||||
'reporting',
|
||||
'scanType',
|
||||
'securityVulnerabilities',
|
||||
'stashContent',
|
||||
'timeout',
|
||||
'productName',
|
||||
'productVersion',
|
||||
'productToken',
|
||||
'projectNames',
|
||||
'serviceUrl',
|
||||
'userTokenCredentialsId',
|
||||
'vulnerabilityReportFileName',
|
||||
'vulnerabilityReportTitle',
|
||||
'whitesourceAccessor',
|
||||
'verbose'
|
||||
]
|
||||
@Field Set STEP_CONFIG_KEYS = GENERAL_CONFIG_KEYS
|
||||
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS
|
||||
|
||||
void call(Map parameters = [:]) {
|
||||
handlePipelineStepErrors(stepName: STEP_NAME, stepParameters: parameters) {
|
||||
def script = checkScript(this, parameters) ?: this
|
||||
def utils = parameters.juStabUtils ?: new Utils()
|
||||
def statusCode = 1
|
||||
|
||||
// load default & individual configuration
|
||||
Map config = ConfigurationHelper.newInstance(this)
|
||||
.loadStepDefaults()
|
||||
.mixinGeneralConfig(script.commonPipelineEnvironment, GENERAL_CONFIG_KEYS)
|
||||
.mixinStepConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS)
|
||||
.mixinStageConfig(script.commonPipelineEnvironment, parameters.stageName ?: env.STAGE_NAME, STEP_CONFIG_KEYS)
|
||||
.mixin(parameters, PARAMETER_KEYS)
|
||||
.dependingOn('scanType').mixin('buildDescriptorFile')
|
||||
.dependingOn('scanType').mixin('configFilePath')
|
||||
.dependingOn('scanType').mixin('dockerImage')
|
||||
.dependingOn('scanType').mixin('dockerWorkspace')
|
||||
.dependingOn('scanType').mixin('stashContent')
|
||||
.dependingOn('scanType').mixin('agentDownloadUrl')
|
||||
.dependingOn('scanType').mixin('agentFileName')
|
||||
.dependingOn('scanType').mixin('agentParameters')
|
||||
.withMandatoryProperty('userTokenCredentialsId')
|
||||
.withMandatoryProperty('productName')
|
||||
.use()
|
||||
|
||||
config.stashContent = utils.unstashAll(config.stashContent)
|
||||
config.projectNames = (config.projectNames instanceof List) ? config.projectNames : config.projectNames?.tokenize(',')
|
||||
parameters.projectNames = config.projectNames
|
||||
|
||||
script.commonPipelineEnvironment.setInfluxStepData('whitesource', false)
|
||||
|
||||
utils.pushToSWA([
|
||||
step: STEP_NAME,
|
||||
stepParamKey1: 'scanType',
|
||||
stepParam1: config.scanType
|
||||
], config)
|
||||
|
||||
echo "Parameters: scanType: ${config.scanType}"
|
||||
|
||||
def whitesourceRepository = parameters.whitesourceRepositoryStub ?: new WhitesourceRepository(this, config)
|
||||
def whitesourceOrgAdminRepository = parameters.whitesourceOrgAdminRepositoryStub ?: new WhitesourceOrgAdminRepository(this, config)
|
||||
|
||||
statusCode = triggerWhitesourceScanWithUserKey(script, config, utils, parameters, whitesourceRepository, whitesourceOrgAdminRepository)
|
||||
|
||||
checkStatus(statusCode, config)
|
||||
|
||||
script.commonPipelineEnvironment.setInfluxStepData('whitesource', true)
|
||||
}
|
||||
}
|
||||
|
||||
private def triggerWhitesourceScanWithUserKey(script, config, utils, parameters, repository, orgAdminRepository) {
|
||||
withCredentials ([string(
|
||||
credentialsId: config.userTokenCredentialsId,
|
||||
variable: 'userKey'
|
||||
)]) {
|
||||
config.userKey = userKey
|
||||
def statusCode = 1
|
||||
echo "Triggering Whitesource scan on product '${config.productName}' with token '${config.productToken}' using credentials with ID '${config.userTokenCredentialsId}'"
|
||||
switch (config.scanType) {
|
||||
case 'mta':
|
||||
def scanJobs = [:]
|
||||
def mtaParameters = [:] + parameters + [reporting: false]
|
||||
// harmonize buildDescriptorExcludeList
|
||||
config.buildDescriptorExcludeList = config.buildDescriptorExcludeList instanceof List ? config.buildDescriptorExcludeList : config.buildDescriptorExcludeList?.replaceAll(', ', ',').replaceAll(' ,', ',').tokenize(',')
|
||||
// create job for each pom.xml with scanType: 'maven'
|
||||
scanJobs.putAll(MtaMultiplexer.createJobs(
|
||||
this, mtaParameters, config.buildDescriptorExcludeList, 'Whitesource', 'pom.xml', 'maven'
|
||||
) { options -> return whitesourceExecuteScan(options) })
|
||||
// create job for each pom.xml with scanType: 'maven'
|
||||
scanJobs.putAll(MtaMultiplexer.createJobs(
|
||||
this, mtaParameters, config.buildDescriptorExcludeList, 'Whitesource', 'package.json', 'npm'
|
||||
) { options -> whitesourceExecuteScan(options) })
|
||||
// create job for each setup.py with scanType: 'pip'
|
||||
scanJobs.putAll(MtaMultiplexer.createJobs(
|
||||
this, mtaParameters, config.buildDescriptorExcludeList, 'Whitesource', 'setup.py', 'pip'
|
||||
) { options -> whitesourceExecuteScan(options) })
|
||||
// execute scan jobs
|
||||
if (config.parallelLimit > 0 && config.parallelLimit < scanJobs.keySet().size()) {
|
||||
// block wise
|
||||
def scanJobsAll = scanJobs
|
||||
scanJobs = [failFast: false]
|
||||
for (int i = 1; i <= scanJobsAll.keySet().size(); i++) {
|
||||
def index = i - 1
|
||||
def key = scanJobsAll.keySet()[index]
|
||||
scanJobs[key] = scanJobsAll[key]
|
||||
if (i % config.parallelLimit == 0 || i == scanJobsAll.keySet().size()) {
|
||||
parallel scanJobs
|
||||
scanJobs = [failFast: false]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// in parallel
|
||||
scanJobs += [failFast: false]
|
||||
parallel scanJobs
|
||||
}
|
||||
statusCode = 0
|
||||
break
|
||||
default:
|
||||
def path = config.buildDescriptorFile.substring(0, config.buildDescriptorFile.lastIndexOf('/') + 1)
|
||||
def gav
|
||||
switch (config.scanType) {
|
||||
case 'npm':
|
||||
gav = utils.getNpmGAV(config.buildDescriptorFile)
|
||||
config.projectName = gav.group + "." + gav.artifact
|
||||
config.productVersion = gav.version
|
||||
break
|
||||
case 'sbt':
|
||||
gav = utils.getSbtGAV(config.buildDescriptorFile)
|
||||
config.projectName = gav.group + "." + gav.artifact
|
||||
config.productVersion = gav.version
|
||||
break
|
||||
case 'pip':
|
||||
gav = utils.getPipGAV(config.buildDescriptorFile)
|
||||
config.projectName = gav.artifact
|
||||
config.productVersion = gav.version
|
||||
break
|
||||
default:
|
||||
gav = utils.readMavenGAV(config.buildDescriptorFile)
|
||||
config.projectName = gav.group + "." + gav.artifact
|
||||
config.productVersion = gav.version
|
||||
break
|
||||
}
|
||||
config.projectNames.add("${config.projectName} - ${config.productVersion}".toString())
|
||||
WhitesourceConfigurationHelper.extendUAConfigurationFile(script, utils, config, path)
|
||||
dockerExecute(script: script, dockerImage: config.dockerImage, dockerWorkspace: config.dockerWorkspace, stashContent: config.stashContent) {
|
||||
if (config.agentDownloadUrl) {
|
||||
def agentDownloadUrl = new GStringTemplateEngine().createTemplate(config.agentDownloadUrl).make([config: config]).toString()
|
||||
//if agentDownloadUrl empty, rely on dockerImage to contain unifiedAgent correctly set up and available
|
||||
sh "curl ${script.env.HTTP_PROXY ? '--proxy ' + script.env.HTTP_PROXY + ' ' : ''}--location --output ${config.agentFileName} ${agentDownloadUrl}".toString()
|
||||
}
|
||||
|
||||
def javaCmd = 'java'
|
||||
if (config.jreDownloadUrl) {
|
||||
//if jreDownloadUrl empty, rely on dockerImage to contain java correctly set up and available on the path
|
||||
sh "curl ${script.env.HTTP_PROXY ? '--proxy ' + script.env.HTTP_PROXY + ' ' : ''}--location --output jvm.tar.gz ${config.jreDownloadUrl} && tar --strip-components=1 -xzf jvm.tar.gz".toString()
|
||||
javaCmd = './bin/java'
|
||||
}
|
||||
|
||||
def options = ["-jar ${config.agentFileName} -c \'${config.configFilePath}\'"]
|
||||
if (config.orgToken) options.push("-apiKey '${config.orgToken}'")
|
||||
if (config.userKey) options.push("-userKey '${config.userKey}'")
|
||||
if (config.productName) options.push("-product '${config.productName}'")
|
||||
|
||||
statusCode = sh(script: "${javaCmd} ${options.join(' ')} ${config.agentParameters}", returnStatus: true)
|
||||
|
||||
// archive whitesource result files
|
||||
archiveArtifacts artifacts: "whitesource/*.*", allowEmptyArchive: true
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
if (config.reporting) {
|
||||
analyseWhitesourceResults(utils, config, repository, orgAdminRepository)
|
||||
}
|
||||
|
||||
return statusCode
|
||||
}
|
||||
}
|
||||
|
||||
void analyseWhitesourceResults(Utils utils, Map config, WhitesourceRepository repository, WhitesourceOrgAdminRepository orgAdminRepository) {
|
||||
if (!config.productToken) {
|
||||
def metaInfo = orgAdminRepository.fetchProductMetaInfo()
|
||||
echo "Meta Information: $metaInfo"
|
||||
config.productToken = metaInfo.token
|
||||
}
|
||||
|
||||
repository.fetchReportForProduct()
|
||||
def pdfName = "whitesource-riskReport.pdf"
|
||||
archiveArtifacts artifacts: pdfName
|
||||
echo "A summary of the Whitesource findings was stored as artifact under the name $pdfName"
|
||||
|
||||
int violationCount = fetchViolationCount(config, repository)
|
||||
checkViolationStatus(violationCount)
|
||||
|
||||
if (config.securityVulnerabilities)
|
||||
config.severeVulnerabilities = checkSecurityViolations(config, repository)
|
||||
}
|
||||
|
||||
int fetchViolationCount(Map config, WhitesourceRepository repository) {
|
||||
int violationCount = 0
|
||||
if (config.projectNames) {
|
||||
def projectsMeta = repository.fetchProjectsMetaInfo()
|
||||
for (int i = 0; i < projectsMeta.size(); i++) {
|
||||
def project = projectsMeta[i]
|
||||
def responseAlertsProject = repository.fetchProjectLicenseAlerts(project.token)
|
||||
violationCount += responseAlertsProject.alerts.size()
|
||||
}
|
||||
} else {
|
||||
def responseAlerts = repository.fetchProductLicenseAlerts()
|
||||
violationCount += responseAlerts.alerts.size()
|
||||
}
|
||||
return violationCount
|
||||
}
|
||||
|
||||
void checkViolationStatus(int violationCount) {
|
||||
if (violationCount == 0) {
|
||||
echo "****\r\n[${STEP_NAME}] No policy violations found. You can deploy to production, and set the \"Intellectual Property (IP) Scan Plan\" in Sirius to completed. \r\n****"
|
||||
} else {
|
||||
error "[${STEP_NAME}] Whitesource found $violationCount policy violations for your product"
|
||||
}
|
||||
}
|
||||
|
||||
int checkSecurityViolations(Map config, WhitesourceRepository repository) {
|
||||
def whitesourceProjectsMetaInformation = repository.fetchProjectsMetaInfo()
|
||||
def whitesourceVulnerabilities = repository.fetchVulnerabilities(whitesourceProjectsMetaInformation)
|
||||
def severeVulnerabilities = 0
|
||||
whitesourceVulnerabilities.each {
|
||||
item ->
|
||||
if (item.vulnerability.score >= 7 || item.vulnerability.cvss3_score >= 7)
|
||||
severeVulnerabilities++
|
||||
}
|
||||
|
||||
writeFile(file: "${config.vulnerabilityReportFileName}.json", text: new JsonUtils().getPrettyJsonString(whitesourceVulnerabilities))
|
||||
writeFile(file: "${config.vulnerabilityReportFileName}.html", text: getReportHtml(config, whitesourceVulnerabilities, severeVulnerabilities))
|
||||
archiveArtifacts(artifacts: "${config.vulnerabilityReportFileName}.*")
|
||||
|
||||
if (whitesourceVulnerabilities.size() - severeVulnerabilities > 0)
|
||||
echo "[${STEP_NAME}] WARNING: ${whitesourceVulnerabilities.size() - severeVulnerabilities} Open Source Software Security vulnerabilities with CVSS score below 7.0 detected."
|
||||
if (whitesourceVulnerabilities.size() == 0)
|
||||
echo "[${STEP_NAME}] No Open Source Software Security vulnerabilities detected."
|
||||
|
||||
return severeVulnerabilities
|
||||
}
|
||||
|
||||
// ExitCodes: https://whitesource.atlassian.net/wiki/spaces/WD/pages/34209870/NPM+Plugin#NPMPlugin-ExitCode
|
||||
void checkStatus(int statusCode, config) {
|
||||
def errorMessage = ""
|
||||
if(config.securityVulnerabilities && config.severeVulnerabilities > 0)
|
||||
errorMessage += "${config.severeVulnerabilities} Open Source Software Security vulnerabilities with CVSS score greater or equal 7.0 detected. - "
|
||||
if (config.licensingVulnerabilities)
|
||||
switch (statusCode) {
|
||||
case 0:
|
||||
break
|
||||
case 255:
|
||||
errorMessage += "The scan resulted in an error"
|
||||
break
|
||||
case 254:
|
||||
errorMessage += "Whitesource found one or multiple policy violations"
|
||||
break
|
||||
case 253:
|
||||
errorMessage += "The local scan client failed to execute the scan"
|
||||
break
|
||||
case 252:
|
||||
errorMessage += "There was a failure in the connection to the WhiteSource servers"
|
||||
break
|
||||
case 251:
|
||||
errorMessage += "The server failed to analyze the scan"
|
||||
break
|
||||
default:
|
||||
errorMessage += "Whitesource scan failed with unknown error code '${statusCode}'"
|
||||
}
|
||||
|
||||
if (errorMessage)
|
||||
error "[${STEP_NAME}] " + errorMessage
|
||||
}
|
||||
|
||||
def getReportHtml(config, vulnerabilityList, numSevereVulns) {
|
||||
def now = new Date().format('MMM dd, yyyy - HH:mm:ss')
|
||||
def vulnerabilityTable = ''
|
||||
if (vulnerabilityList.size() == 0) {
|
||||
vulnerabilityTable += '''
|
||||
<tr>
|
||||
<td colspan=12> No publicly known vulnerabilities detected </td>
|
||||
</tr>'''
|
||||
} else {
|
||||
for (int i = 0; i < vulnerabilityList.size(); i++) {
|
||||
def item = vulnerabilityList[i]
|
||||
def score = item.vulnerability.cvss3_score > 0 ? item.vulnerability.cvss3_score : item.vulnerability.score
|
||||
def topFix = item.vulnerability.topFix ? "${item.vulnerability.topFix?.message}<br>${item.vulnerability.topFix?.fixResolution}<br><a href=\"${item.vulnerability.topFix?.url}\">${item.vulnerability.topFix?.url}</a>}" : ''
|
||||
vulnerabilityTable += """
|
||||
<tr>
|
||||
<td>${i + 1}</td>
|
||||
<td>${item.date}</td>
|
||||
<td><a href=\"${item.vulnerability.url}\">${item.vulnerability.name}</a></td>
|
||||
<td class=\"${score < 7.0 ? 'warn' : 'notok'}\">${score}</td>
|
||||
<td>${item.vulnerability.cvss3_score > 0 ? 'v3' : 'v2'}</td>
|
||||
<td>${item.project}</td>
|
||||
<td>${item.library.filename}</td>
|
||||
<td>${item.library.groupId}</td>
|
||||
<td>${item.library.artifactId}</td>
|
||||
<td>${item.library.version}</td>
|
||||
<td>${item.vulnerability.description}</td>
|
||||
<td>${topFix}</td>
|
||||
</tr>"""
|
||||
}
|
||||
}
|
||||
|
||||
return SimpleTemplateEngine.newInstance().createTemplate(libraryResource('com.sap.piper/templates/whitesourceVulnerabilities.html')).make(
|
||||
[
|
||||
now : now,
|
||||
reportTitle : config.vulnerabilityReportTitle,
|
||||
style : config.style,
|
||||
totalSevereVulnerabilities : numSevereVulns,
|
||||
totalVulnerabilities : vulnerabilityList.size(),
|
||||
vulnerabilityTable : vulnerabilityTable,
|
||||
whitesourceProductName : config.whitesourceProductName,
|
||||
whitesourceProjectNames : config.whitesourceProjectNames
|
||||
]).toString()
|
||||
}
|
Loading…
Reference in New Issue
Block a user