1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-03-03 15:02:35 +02:00

Refactored to generally migrate config to deep structure

This commit is contained in:
Sven Merk 2019-03-14 15:14:09 +01:00
parent f2c7265986
commit c96f73866a
11 changed files with 252 additions and 211 deletions

View File

@ -23,5 +23,5 @@ None
## Examples
```groovy
whitesourceExecuteScan script: this, scanType: 'pip', productName: 'My Whitesource Product', userTokenCredentialsId: 'companyAdminToken', orgAdminUserTokenCredentialsId: 'orgAdmiToken', orgToken: 'myWhitesourceOrganizationToken'
whitesourceExecuteScan script: this, scanType: 'pip', whitesource: [ productName: 'My Whitesource Product', userTokenCredentialsId: 'companyAdminToken', orgAdminUserTokenCredentialsId: 'orgAdmiToken', orgToken: 'myWhitesourceOrganizationToken' ]
```

View File

@ -59,22 +59,21 @@ class ConfigurationHelper implements Serializable {
return this
}
private Map handleCompatibility(Map compatibleParameters, String paramStructure = '', Map configMap ) {
private Map handleCompatibility(Map compatibleParameters, String paramStructure = '', Map configMap, Map newConfigMap = [:] ) {
Map newConfig = [:]
compatibleParameters.each {entry ->
if (entry.getValue() instanceof Map) {
def internalParamStructure = (paramStructure ? paramStructure + '.' : '') + entry.getKey()
newConfig[entry.getKey()] = handleCompatibility(entry.getValue(), internalParamStructure, configMap)
newConfig[entry.getKey()] = handleCompatibility(entry.getValue(), internalParamStructure, configMap, newConfig)
} else {
def configSubMap = configMap
for(String key in paramStructure.tokenize('.')){
configSubMap = configSubMap?.get(key)
}
if (configSubMap == null || (configSubMap != null && configSubMap[entry.getKey()] == null)) {
def stages = entry.getValue()?.tokenize('.')
def value = resolveToFlat(stages, configMap)
def value = configMap[entry.getValue()]
if(null == value)
value = resolveToFlat(stages, newConfig)
value = newConfigMap[entry.getValue()]
if (value != null) {
newConfig[entry.getKey()] = value
def paramName = (paramStructure ? paramStructure + '.' : '') + entry.getKey()
@ -86,19 +85,6 @@ class ConfigurationHelper implements Serializable {
return newConfig
}
private String resolveToFlat(stages, configMap) {
def first = 0
def result
def configSubMap = configMap[stages?.get(first)]
if(configSubMap instanceof Map) {
stages?.remove(first)
result = resolveToFlat(stages, configSubMap)
} else {
result = configSubMap
}
return result
}
Map dependingOn(dependentKey){
return [
mixin: {key ->

View File

@ -11,35 +11,34 @@ class WhitesourceConfigurationHelper implements Serializable {
def inputFile = config.configFilePath.replaceFirst('\\./', '')
def suffix = utils.generateSha1(config.configFilePath)
def targetFile = "${inputFile}.${suffix}"
if(config.productName.startsWith('DIST - ')) {
if(config.whitesource.productName.startsWith('DIST - ')) {
mapping += [
[name: 'checkPolicies', value: false],
[name: 'forceCheckAllDependencies', value: false]
[name: 'checkPolicies', value: false, force: true],
[name: 'forceCheckAllDependencies', value: false, force: true]
]
} else if(config.productName.startsWith('SHC - ')) {
} else if(config.whitesource.productName.startsWith('SHC - ')) {
mapping += [
[name: 'checkPolicies', value: true],
[name: 'forceCheckAllDependencies', value: true]
[name: 'checkPolicies', value: true, force: true],
[name: 'forceCheckAllDependencies', value: true, force: true]
]
}
if(config.verbose)
mapping += [name: 'log.level', value: 'debug']
if(config.whitesource.verbose)
mapping += [name: 'log.level', value: 'debug', force: true]
mapping += [
[name: 'apiKey', value: config.orgToken],
[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],
[name: 'forceUpdate', value: true],
[name: 'offline', value: false],
[name: 'ignoreSourceFiles', value: true],
[name: 'resolveAllDependencies', value: false]
[name: 'apiKey', value: config.whitesource.orgToken, force: true],
[name: 'productName', value: config.whitesource.productName, force: true],
[name: 'productVersion', value: config.whitesource.productVersion, force: true],
[name: 'projectName', value: config.whitesource.projectName, force: true],
[name: 'projectVersion', value: config.whitesource.productVersion, force: true],
[name: 'productToken', value: config.whitesource.productToken, omitIfPresent: 'projectToken', force: true],
[name: 'userKey', value: config.whitesource.userKey, force: true],
[name: 'forceUpdate', value: true, force: true],
[name: 'offline', value: false, force: true],
[name: 'ignoreSourceFiles', value: true, force: true],
[name: 'resolveAllDependencies', value: false, force: true]
]
switch (config.scanType) {
case 'npm':
mapping += [
@ -47,8 +46,8 @@ class WhitesourceConfigurationHelper implements Serializable {
break
case 'pip':
mapping += [
[name: 'python.resolveDependencies', value: true],
[name: 'python.ignoreSourceFiles', value: true],
[name: 'python.resolveDependencies', value: true, force: true],
[name: 'python.ignoreSourceFiles', value: true, force: true],
[name: 'python.ignorePipInstallErrors', value: false],
[name: 'python.installVirtualenv', value: true],
[name: 'python.resolveHierarchyTree', value: true],
@ -70,7 +69,14 @@ class WhitesourceConfigurationHelper implements Serializable {
break
case 'golang':
mapping += [
[name: 'go.resolveDependencies', value: true, force: true],
[name: 'go.ignoreSourceFiles', value: true, force: true],
[name: 'go.collectDependenciesAtRuntime', value: true],
[name: 'go.dependencyManager', value: ''],
[name: 'includes', value: '**/*.lock'],
[name: 'excludes', value: '**/*sources.jar **/*javadoc.jar'],
[name: 'case.sensitive.glob', value: false],
[name: 'followSymbolicLinks', value: true]
]
break
case 'dlang':
@ -100,13 +106,13 @@ class WhitesourceConfigurationHelper implements Serializable {
mapping.each {
entry ->
def dependentValue = entry.omitIfPresent ? moduleSpecificFile[entry.omitIfPresent] : null
if ((entry.omitIfPresent && !dependentValue || !entry.omitIfPresent) && entry.value && entry.value != 'null' && entry.value != '')
if ((entry.omitIfPresent && !dependentValue || !entry.omitIfPresent) && (entry.force || moduleSpecificFile[entry.name] == null) && entry.value != 'null')
moduleSpecificFile[entry.name] = entry.value.toString()
}
def output = serializationClosure(moduleSpecificFile)
if(config.verbose)
if(config.whitesource.verbose)
script.echo "Writing config file ${outputFilePath} with content:\n${output}"
script.writeFile file: outputFilePath, text: output
if(config.stashContent && config.stashContent.size() > 0) {
@ -124,10 +130,7 @@ class WhitesourceConfigurationHelper implements Serializable {
@NonCPS
static private def serializeUAConfig(configuration) {
Properties p = new Properties()
configuration.each {
entry ->
p.setProperty(entry.key, entry.value)
}
p.putAll(configuration)
new StringWriter().with{ w -> p.store(w, null); w }.toString()
}

View File

@ -12,8 +12,8 @@ class WhitesourceOrgAdminRepository implements Serializable {
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.whitesource.serviceUrl && !this.config.whitesourceAccessor)
script.error "Parameter 'whitesource.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)
@ -23,7 +23,7 @@ class WhitesourceOrgAdminRepository implements Serializable {
def fetchProductMetaInfo() {
def requestBody = [
requestType: "getOrganizationProductVitals",
orgToken: config.orgToken
orgToken: config.whitesource.orgToken
]
def parsedResponse = issueHttpRequest(requestBody)
@ -33,7 +33,7 @@ class WhitesourceOrgAdminRepository implements Serializable {
def findProductMeta(parsedResponse) {
def foundMetaProduct = null
for (product in parsedResponse.productVitals) {
if (product.name == config.productName) {
if (product.name == config.whitesource.productName) {
foundMetaProduct = product
break
}
@ -45,15 +45,15 @@ class WhitesourceOrgAdminRepository implements Serializable {
def createProduct() {
def requestBody = [
requestType: "createProduct",
orgToken: config.orgToken,
productName: config.productName
orgToken: config.whitesource.orgToken,
productName: config.whitesource.productName
]
def parsedResponse = issueHttpRequest(requestBody)
def metaInfo = parsedResponse
def groups = []
def users = []
config.emailAddressesOfInitialProductAdmins.each {
config.whitesource.emailAddressesOfInitialProductAdmins.each {
email -> users.add(["email": email])
}
@ -80,27 +80,27 @@ class WhitesourceOrgAdminRepository implements Serializable {
@NonCPS
protected def httpWhitesource(requestBody) {
requestBody["userKey"] = config.orgAdminUserKey
requestBody["userKey"] = config.whitesource.orgAdminUserKey
def serializedBody = new JsonUtils().jsonToString(requestBody)
def params = [
url : config.serviceUrl,
url : config.whitesource.serviceUrl,
httpMode : 'POST',
acceptType : 'APPLICATION_JSON',
contentType: 'APPLICATION_JSON',
requestBody: serializedBody,
quiet : !config.verbose,
timeout : config.timeout
quiet : !config.whitesource.verbose,
timeout : config.whitesource.timeout
]
if (script.env.HTTP_PROXY)
params["httpProxy"] = script.env.HTTP_PROXY
if (config.verbose)
if (config.whitesource.verbose)
script.echo "Sending http request with parameters ${params}"
def response = script.httpRequest(params)
if (config.verbose)
if (config.whitesource.verbose)
script.echo "Received response ${response}"
return response

View File

@ -12,13 +12,13 @@ class WhitesourceRepository implements Serializable {
this.script = script
this.config = config
if(!config.serviceUrl)
script.error "Parameter 'serviceUrl' must be provided as part of the configuration."
if(!config.whitesource.serviceUrl)
script.error "Parameter 'whitesource.serviceUrl' must be provided as part of the configuration."
}
List fetchVulnerabilities(whitesourceProjectsMetaInformation) {
def fetchedVulnerabilities = []
if (config.projectNames) {
if (config.whitesource.projectNames) {
for (int i = 0; i < whitesourceProjectsMetaInformation.size(); i++) {
def metaInfo = whitesourceProjectsMetaInformation[i]
@ -35,7 +35,7 @@ class WhitesourceRepository implements Serializable {
def requestBody = [
requestType : "getProductAlertsByType",
alertType : "SECURITY_VULNERABILITY",
productToken: config.productToken,
productToken: config.whitesource.productToken,
]
def response = fetchWhitesourceResource(requestBody)
@ -99,17 +99,17 @@ class WhitesourceRepository implements Serializable {
List fetchProjectsMetaInfo() {
def projectsMetaInfo = []
if(config.projectNames){
if(config.whitesource.projectNames){
def requestBody = [
requestType: "getProductProjectVitals",
productToken: config.productToken
productToken: config.whitesource.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}"
script.error "[WhiteSource] Could not fetch any projects for product '${config.whitesource.productName}' from backend, response was ${response}"
}
}
return projectsMetaInfo
@ -117,8 +117,8 @@ class WhitesourceRepository implements Serializable {
List findProjectsMeta(projectVitals) {
def matchedProjects = []
for (int i = 0; i < config.projectNames?.size(); i++) {
def requestedProjectName = config.projectNames[i].trim()
for (int i = 0; i < config.whitesource.projectNames?.size(); i++) {
def requestedProjectName = config.whitesource.projectNames[i].trim()
def matchedProjectInfo = null
for (int j = 0; j < projectVitals.size(); j++) {
@ -132,7 +132,7 @@ class WhitesourceRepository implements Serializable {
if (matchedProjectInfo != null) {
matchedProjects.add(matchedProjectInfo)
} else {
script.error "[WhiteSource] Could not fetch/find requested project '${requestedProjectName}' for product '${config.productName}'"
script.error "[WhiteSource] Could not fetch/find requested project '${requestedProjectName}' for product '${config.whitesource.productName}'"
}
}
@ -142,7 +142,7 @@ class WhitesourceRepository implements Serializable {
void fetchReportForProduct(reportName) {
def requestContent = [
requestType: "getProductRiskReport",
productToken: config.productToken
productToken: config.whitesource.productToken
]
fetchFileFromWhiteSource(reportName, requestContent)
@ -152,7 +152,7 @@ class WhitesourceRepository implements Serializable {
def requestContent = [
requestType: "getProductAlertsByType",
alertType: "REJECTED_BY_POLICY_RESOURCE",
productToken: config.productToken
productToken: config.whitesource.productToken
]
def parsedResponse = fetchWhitesourceResource(requestContent)
@ -175,24 +175,24 @@ class WhitesourceRepository implements Serializable {
handleAdditionalRequestParameters(requestBody)
def serializedBody = new JsonUtils().getPrettyJsonString(requestBody)
def params = [
url : config.serviceUrl,
url : config.whitesource.serviceUrl,
httpMode : 'POST',
acceptType : 'APPLICATION_JSON',
contentType: 'APPLICATION_JSON',
requestBody: serializedBody,
quiet : !config.verbose,
timeout : config.timeout
quiet : !config.whitesource.verbose,
timeout : config.whitesource.timeout
]
if (script.env.HTTP_PROXY)
params["httpProxy"] = script.env.HTTP_PROXY
if(config.verbose)
if(config.whitesource.verbose)
script.echo "Sending http request with parameters ${params}"
def response = script.httpRequest(params)
if(config.verbose)
if(config.whitesource.verbose)
script.echo "Received response ${response}"
return response
@ -203,15 +203,15 @@ class WhitesourceRepository implements Serializable {
handleAdditionalRequestParameters(params)
def serializedContent = new JsonUtils().jsonToString(params)
if(config.verbose)
if(config.whitesource.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}\'"
script.sh "${config.whitesource.verbose ? '' : '#!/bin/sh -e\n'}curl -o ${fileName} -X POST ${config.whitesource.serviceUrl} -H 'Content-Type: application/json' -d \'${serializedContent}\'"
}
@NonCPS
protected void handleAdditionalRequestParameters(params) {
if(config.userKey)
params["userKey"] = config.userKey
if(config.whitesource.userKey)
params["userKey"] = config.whitesource.userKey
}
}

View File

@ -26,10 +26,12 @@ class WhitesourceExecuteScanTest extends BasePiperTest {
private JenkinsWriteFileRule writeFileRule = new JenkinsWriteFileRule(this)
private JenkinsStepRule stepRule = new JenkinsStepRule(this)
private JenkinsErrorRule errorRule = new JenkinsErrorRule(this)
private JenkinsEnvironmentRule environmentRule = new JenkinsEnvironmentRule(this)
@Rule
public RuleChain ruleChain = Rules
.getCommonRules(this)
.around(environmentRule)
.around(new JenkinsReadYamlRule(this))
.around(thrown)
.around(dockerExecuteRule)
@ -103,10 +105,10 @@ class WhitesourceExecuteScanTest extends BasePiperTest {
return [].toArray()
})
whitesourceOrgAdminRepositoryStub = new WhitesourceOrgAdminRepository(nullScript, [serviceUrl: "http://some.host.whitesource.com/api/"])
whitesourceOrgAdminRepositoryStub = new WhitesourceOrgAdminRepository(nullScript, [whitesource: [serviceUrl: "http://some.host.whitesource.com/api/"]])
LibraryLoadingTestExecutionListener.prepareObjectInterceptors(whitesourceOrgAdminRepositoryStub)
whitesourceStub = new WhitesourceRepository(nullScript, [serviceUrl: "http://some.host.whitesource.com/api/"])
whitesourceStub = new WhitesourceRepository(nullScript, [whitesource: [serviceUrl: "http://some.host.whitesource.com/api/"]])
LibraryLoadingTestExecutionListener.prepareObjectInterceptors(whitesourceStub)
helper.registerAllowedMethod("fetchProductMetaInfo", [], {
@ -527,11 +529,13 @@ class WhitesourceExecuteScanTest extends BasePiperTest {
whitesourceOrgAdminRepositoryStub : whitesourceOrgAdminRepositoryStub,
descriptorUtilsStub : descriptorUtilsStub,
scanType : 'mta',
productName : 'SHC - Piper',
whitesource: [
productName : 'SHC - Piper',
orgToken : 'b39d1328-52e2-42e3-98f0-932709daf3f0'
],
buildDescriptorExcludeList : ["maven2${File.separator}pom.xml".toString(), "npm2${File.separator}package.json".toString()],
reporting : true,
juStabUtils : utils,
orgToken : 'b39d1328-52e2-42e3-98f0-932709daf3f0'
juStabUtils : utils
])
assertThat(loggingRule.log, containsString('Unstash content: buildDescriptor'))
@ -542,19 +546,26 @@ class WhitesourceExecuteScanTest extends BasePiperTest {
assertThat(parallelMap, hasKey('Whitesource - pip'))
assertThat(parallelMap.keySet(), hasSize(4))
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', 'pip'),
hasEntry('projectNames', ["com.sap.maven.test-java - 1.2.3", "com.sap.node.test-node - 1.2.3", "test-python - 1.2.3"]),
hasEntry('buildDescriptorFile', "pip${File.separator}setup.py".toString())
)))
assertThat(whitesourceCalls,
contains(
allOf(
hasEntry('scanType', 'maven'),
hasEntry('buildDescriptorFile', "maven1${File.separator}pom.xml".toString())
),
allOf(
hasEntry('scanType', 'npm'),
hasEntry('buildDescriptorFile', "npm1${File.separator}package.json".toString())
),
allOf(
hasEntry('scanType', 'pip'),
hasEntry('buildDescriptorFile', "pip${File.separator}setup.py".toString())
)
)
)
assertThat(whitesourceCalls[0]['whitesource']['projectNames'], contains("com.sap.maven.test-java - 1.2.3", "com.sap.node.test-node - 1.2.3", "test-python - 1.2.3"))
assertThat(whitesourceCalls[1]['whitesource']['projectNames'], contains("com.sap.maven.test-java - 1.2.3", "com.sap.node.test-node - 1.2.3", "test-python - 1.2.3"))
assertThat(whitesourceCalls[2]['whitesource']['projectNames'], contains("com.sap.maven.test-java - 1.2.3", "com.sap.node.test-node - 1.2.3", "test-python - 1.2.3"))
}
@Test
@ -669,36 +680,36 @@ class WhitesourceExecuteScanTest extends BasePiperTest {
@Test
void testNPMStatusCheckScanException() {
thrown.expect(AbortException.class)
stepRule.step.checkStatus(-1 & 0xFF, [licensingVulnerabilities: true])
stepRule.step.checkStatus(-1 & 0xFF, [whitesource:[licensingVulnerabilities: true]])
}
@Test
void testNPMStatusCheckPolicyViolation() {
thrown.expect(AbortException.class)
stepRule.step.checkStatus(-2 & 0xFF, [licensingVulnerabilities: true])
stepRule.step.checkStatus(-2 & 0xFF, [whitesource:[licensingVulnerabilities: true]])
}
@Test
void testNPMStatusCheckNoPolicyViolation() {
stepRule.step.checkStatus(-2 & 0xFF, [licensingVulnerabilities: false])
stepRule.step.checkStatus(-2 & 0xFF, [whitesource:[licensingVulnerabilities: false]])
}
@Test
void testNPMStatusCheckClientException() {
thrown.expect(AbortException.class)
stepRule.step.checkStatus(-3 & 0xFF, [licensingVulnerabilities: true])
stepRule.step.checkStatus(-3 & 0xFF, [whitesource:[licensingVulnerabilities: true]])
}
@Test
void testNPMStatusCheckConnectionException() {
thrown.expect(AbortException.class)
stepRule.step.checkStatus(-4 & 0xFF, [licensingVulnerabilities: true])
stepRule.step.checkStatus(-4 & 0xFF, [whitesource:[licensingVulnerabilities: true]])
}
@Test
void testNPMStatusCheckServerException() {
thrown.expect(AbortException.class)
stepRule.step.checkStatus(-3 & 0xFF, [licensingVulnerabilities: true])
stepRule.step.checkStatus(-3 & 0xFF, [whitesource:[licensingVulnerabilities: true]])
}
@Test
@ -736,8 +747,7 @@ class WhitesourceExecuteScanTest extends BasePiperTest {
@Test
void testFetchViolationCountProjectNotZero() {
def config = [projectNames: ["piper-java-cc - 0.0.1", "pipeline-test - 0.0.1"]]
def config = [whitesource: [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 ->
@ -976,7 +986,7 @@ class WhitesourceExecuteScanTest extends BasePiperTest {
void testCheckStatus_0() {
def error = false
try {
stepRule.step.checkStatus(0, [licensingVulnerabilities: true])
stepRule.step.checkStatus(0, [whitesource:[licensingVulnerabilities: true]])
} catch (e) {
error = true
}
@ -987,7 +997,7 @@ class WhitesourceExecuteScanTest extends BasePiperTest {
void testCheckStatus_255() {
def error = false
try {
stepRule.step.checkStatus(255, [licensingVulnerabilities: true])
stepRule.step.checkStatus(255, [whitesource:[licensingVulnerabilities: true]])
} catch (e) {
error = true
assertThat(e.getMessage(), is("[whitesourceExecuteScan] The scan resulted in an error"))
@ -999,7 +1009,7 @@ class WhitesourceExecuteScanTest extends BasePiperTest {
void testCheckStatus_254() {
def error = false
try {
stepRule.step.checkStatus(254, [licensingVulnerabilities: true])
stepRule.step.checkStatus(254, [whitesource:[licensingVulnerabilities: true]])
} catch (e) {
error = true
assertThat(e.getMessage(), is("[whitesourceExecuteScan] Whitesource found one or multiple policy violations"))
@ -1011,7 +1021,7 @@ class WhitesourceExecuteScanTest extends BasePiperTest {
void testCheckStatus_253() {
def error = false
try {
stepRule.step.checkStatus(253, [licensingVulnerabilities: true])
stepRule.step.checkStatus(253, [whitesource:[licensingVulnerabilities: true]])
} catch (e) {
error = true
assertThat(e.getMessage(), is("[whitesourceExecuteScan] The local scan client failed to execute the scan"))
@ -1023,7 +1033,7 @@ class WhitesourceExecuteScanTest extends BasePiperTest {
void testCheckStatus_252() {
def error = false
try {
stepRule.step.checkStatus(252, [licensingVulnerabilities: true])
stepRule.step.checkStatus(252, [whitesource:[licensingVulnerabilities: true]])
} catch (e) {
error = true
assertThat(e.getMessage(), is("[whitesourceExecuteScan] There was a failure in the connection to the WhiteSource servers"))
@ -1035,7 +1045,7 @@ class WhitesourceExecuteScanTest extends BasePiperTest {
void testCheckStatus_251() {
def error = false
try {
stepRule.step.checkStatus(251, [licensingVulnerabilities: true])
stepRule.step.checkStatus(251, [whitesource:[licensingVulnerabilities: true]])
} catch (e) {
error = true
assertThat(e.getMessage(), is("[whitesourceExecuteScan] The server failed to analyze the scan"))
@ -1047,7 +1057,7 @@ class WhitesourceExecuteScanTest extends BasePiperTest {
void testCheckStatus_250() {
def error = false
try {
stepRule.step.checkStatus(250, [licensingVulnerabilities: true])
stepRule.step.checkStatus(250, [whitesource:[licensingVulnerabilities: true]])
} catch (e) {
error = true
assertThat(e.getMessage(), is("[whitesourceExecuteScan] Pre-step failure"))
@ -1059,7 +1069,7 @@ class WhitesourceExecuteScanTest extends BasePiperTest {
void testCheckStatus_127() {
def error = false
try {
stepRule.step.checkStatus(127, [licensingVulnerabilities: true])
stepRule.step.checkStatus(127, [whitesource:[licensingVulnerabilities: true]])
} catch (e) {
error = true
assertThat(e.getMessage(), is("[whitesourceExecuteScan] Whitesource scan failed with unknown error code '127'"))
@ -1071,7 +1081,7 @@ class WhitesourceExecuteScanTest extends BasePiperTest {
void testCheckStatus_vulnerability() {
def error = false
try {
stepRule.step.checkStatus(0, [licensingVulnerabilities: false, securityVulnerabilities: true, severeVulnerabilities: 5, cvssSeverityLimit: 7])
stepRule.step.checkStatus(0, [whitesource:[licensingVulnerabilities: false, securityVulnerabilities: true, severeVulnerabilities: 5, cvssSeverityLimit: 7]])
} catch (e) {
error = true
assertThat(e.getMessage(), is("[whitesourceExecuteScan] 5 Open Source Software Security vulnerabilities with CVSS score greater or equal 7 detected. - "))

View File

@ -166,17 +166,6 @@ class ConfigurationHelperTest {
Assert.assertThat(configuration.deep.deeper.newStructure.new2, is('oldValue2'))
}
@Test
void testHandleCompatibilityFlatten() {
def configuration = ConfigurationHelper.newInstance(mockScript)
.mixin([old1: [deeper: 'oldValue1'], old2: [deeper: 'oldValue2'], test: 'testValue'], null, [new1: 'old1.deeper', new2: 'old2.deeper'])
.use()
Assert.assertThat(configuration.size(), is(5))
Assert.assertThat(configuration.new1, is('oldValue1'))
Assert.assertThat(configuration.new2, is('oldValue2'))
}
@Test
void testHandleCompatibilityNewAvailable() {
def configuration = ConfigurationHelper.newInstance(mockScript, [old1: 'oldValue1', newStructure: [new1: 'newValue1'], test: 'testValue'])
@ -207,6 +196,17 @@ class ConfigurationHelperTest {
Assert.assertThat(configuration.newStructure.new1, is(null))
}
@Test
void testHandleCompatibilityPremigratedValues() {
def configuration = ConfigurationHelper.newInstance(mockScript, [old1: null, test: 'testValue'])
.mixin([someValueToMigrate: 'testValue2'], null, [someValueToMigrateSecondTime: 'someValueToMigrate', newStructure: [new1: 'old1', new2: 'someValueToMigrateSecondTime']])
.use()
Assert.assertThat(configuration.size(), is(4))
Assert.assertThat(configuration.newStructure.new1, is(null))
Assert.assertThat(configuration.newStructure.new2, is('testValue2'))
}
@Test
public void testWithMandoryParameterReturnDefaultFailureMessage() {

View File

@ -29,7 +29,7 @@ class WhiteSourceConfigurationHelperTest extends BasePiperTest {
@Test
void testExtendConfigurationFileUnifiedAgentPip() {
WhitesourceConfigurationHelper.extendUAConfigurationFile(nullScript, utils, [scanType: 'pip', configFilePath: './config', orgToken: 'abcd', productName: 'name', productToken: '1234', userKey: '0000'], "./")
WhitesourceConfigurationHelper.extendUAConfigurationFile(nullScript, utils, [scanType: 'pip', configFilePath: './config', whitesource: [serviceUrl: "http://some.host.whitesource.com/api/", orgToken: 'abcd', productName: 'name', productToken: '1234', userKey: '0000']], "./")
assertThat(jwfr.files['./config.847f9aec2f93de9000d5fa4e6eaace2283ae6377'], containsString("apiKey=abcd"))
assertThat(jwfr.files['./config.847f9aec2f93de9000d5fa4e6eaace2283ae6377'], containsString("productName=name"))
assertThat(jwfr.files['./config.847f9aec2f93de9000d5fa4e6eaace2283ae6377'], containsString("productToken=1234"))
@ -39,7 +39,7 @@ class WhiteSourceConfigurationHelperTest extends BasePiperTest {
@Test
void testExtendConfigurationFileUnifiedAgentVerbose() {
WhitesourceConfigurationHelper.extendUAConfigurationFile(nullScript, utils, [scanType: 'pip', verbose: true, configFilePath: './config', orgToken: 'abcd', productName: 'name', productToken: '1234', userKey: '0000'], "./")
WhitesourceConfigurationHelper.extendUAConfigurationFile(nullScript, utils, [scanType: 'pip', configFilePath: './config', whitesource: [serviceUrl: "http://some.host.whitesource.com/api/", orgToken: 'abcd', productName: 'name', productToken: '1234', userKey: '0000', verbose: true]], "./")
assertThat(jwfr.files['./config.847f9aec2f93de9000d5fa4e6eaace2283ae6377'], containsString("apiKey=abcd"))
assertThat(jwfr.files['./config.847f9aec2f93de9000d5fa4e6eaace2283ae6377'], containsString("productName=name"))
assertThat(jwfr.files['./config.847f9aec2f93de9000d5fa4e6eaace2283ae6377'], containsString("productToken=1234"))
@ -47,5 +47,24 @@ class WhiteSourceConfigurationHelperTest extends BasePiperTest {
assertThat(jwfr.files['./config.847f9aec2f93de9000d5fa4e6eaace2283ae6377'], containsString("python.resolveDependencies=true"))
assertThat(jwfr.files['./config.847f9aec2f93de9000d5fa4e6eaace2283ae6377'], containsString("log.level=debug"))
}
@Test
void testExtendConfigurationFileUnifiedAgentEnforcement() {
def p = new Properties()
p.putAll(['python.resolveDependencies': 'false', 'python.ignoreSourceFiles': 'false', 'python.ignorePipInstallErrors': 'true','python.installVirtualenv': 'false'])
helper.registerAllowedMethod('readProperties', [Map], {return p})
WhitesourceConfigurationHelper.extendUAConfigurationFile(nullScript, utils, [scanType: 'pip', configFilePath: './config', whitesource: [serviceUrl: "http://some.host.whitesource.com/api/", orgToken: 'abcd', productName: 'name', productToken: '1234', userKey: '0000', verbose: true]], "./")
assertThat(jwfr.files['./config.847f9aec2f93de9000d5fa4e6eaace2283ae6377'], containsString("apiKey=abcd"))
assertThat(jwfr.files['./config.847f9aec2f93de9000d5fa4e6eaace2283ae6377'], containsString("productName=name"))
assertThat(jwfr.files['./config.847f9aec2f93de9000d5fa4e6eaace2283ae6377'], containsString("productToken=1234"))
assertThat(jwfr.files['./config.847f9aec2f93de9000d5fa4e6eaace2283ae6377'], containsString("userKey=0000"))
assertThat(jwfr.files['./config.847f9aec2f93de9000d5fa4e6eaace2283ae6377'], containsString("python.resolveDependencies=true"))
assertThat(jwfr.files['./config.847f9aec2f93de9000d5fa4e6eaace2283ae6377'], containsString("log.level=debug"))
assertThat(jwfr.files['./config.847f9aec2f93de9000d5fa4e6eaace2283ae6377'], containsString("python.resolveDependencies=true"))
assertThat(jwfr.files['./config.847f9aec2f93de9000d5fa4e6eaace2283ae6377'], containsString("python.ignoreSourceFiles=true"))
assertThat(jwfr.files['./config.847f9aec2f93de9000d5fa4e6eaace2283ae6377'], containsString("python.ignorePipInstallErrors=true"))
assertThat(jwfr.files['./config.847f9aec2f93de9000d5fa4e6eaace2283ae6377'], containsString("python.installVirtualenv=false"))
}
}

View File

@ -35,7 +35,7 @@ class WhitesourceOrgAdminRepositoryTest extends BasePiperTest {
@Before
void init() throws Exception {
repository = new WhitesourceOrgAdminRepository(nullScript, [serviceUrl: "http://some.host.whitesource.com/api/", verbose: true])
repository = new WhitesourceOrgAdminRepository(nullScript, [whitesource: [serviceUrl: "http://some.host.whitesource.com/api/"], verbose: true])
LibraryLoadingTestExecutionListener.prepareObjectInterceptors(repository)
}
@ -53,14 +53,14 @@ class WhitesourceOrgAdminRepositoryTest extends BasePiperTest {
} catch (e) {
errorCaught = true
assertThat(e, isA(AbortException.class))
assertThat(e.getMessage(), is("Parameter 'serviceUrl' must be provided as part of the configuration."))
assertThat(e.getMessage(), is("Parameter 'whitesource.serviceUrl' must be provided as part of the configuration."))
}
assertThat(errorCaught, is(true))
}
@Test
void testAccessor() {
new WhitesourceOrgAdminRepository(nullScript, [whitesourceAccessor: "com.sap.piper.integration.WhitesourceRepository", serviceUrl: "http://test.com"])
new WhitesourceOrgAdminRepository(nullScript, [whitesourceAccessor: "com.sap.piper.integration.WhitesourceRepository", whitesource: [serviceUrl: "http://test.com"]])
}
@Test
@ -83,7 +83,7 @@ class WhitesourceOrgAdminRepositoryTest extends BasePiperTest {
]
]
repository.config['productName'] = "Correct Name Cloud"
repository.config.putAll([whitesource: [productName: "Correct Name Cloud"]])
def result = repository.findProductMeta(whitesourceMetaResponse)

View File

@ -39,7 +39,7 @@ class WhitesourceRepositoryTest extends BasePiperTest {
void init() throws Exception {
nullScript.env['HTTP_PROXY'] = "http://proxy.wdf.sap.corp:8080"
repository = new WhitesourceRepository(nullScript, [serviceUrl: "http://some.host.whitesource.com/api/"])
repository = new WhitesourceRepository(nullScript, [whitesource: [serviceUrl: "http://some.host.whitesource.com/api/"]])
LibraryLoadingTestExecutionListener.prepareObjectInterceptors(repository)
}
@ -57,7 +57,7 @@ class WhitesourceRepositoryTest extends BasePiperTest {
} catch (e) {
errorCaught = true
assertThat(e, isA(AbortException.class))
assertThat(e.getMessage(), is("Parameter 'serviceUrl' must be provided as part of the configuration."))
assertThat(e.getMessage(), is("Parameter 'whitesource.serviceUrl' must be provided as part of the configuration."))
}
assertThat(errorCaught, is(true))
}
@ -126,7 +126,7 @@ class WhitesourceRepositoryTest extends BasePiperTest {
exception.expectMessage("Correct Project Name")
repository.config['projectNames'] = ["Correct Project Name"]
repository.config.putAll([whitesource : [ projectNames: ["Correct Project Name"]]])
repository.findProjectsMeta(whitesourceMetaResponse.projectVitals)
}

View File

@ -15,6 +15,10 @@ import static com.sap.piper.Prerequisites.checkScript
@Field String STEP_NAME = getClass().getName()
@Field Set GENERAL_CONFIG_KEYS = [
/**
* Wrapper object to bundle any of the other configuration settings on general and stage level.
*/
'whitesource',
/**
* Jenkins credentials ID referring to the organization admin's token.
*/
@ -148,21 +152,39 @@ import static com.sap.piper.Prerequisites.checkScript
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS
@Field Map CONFIG_KEY_COMPATIBILITY = [
whitesource : [
productName : 'whitesourceProductName',
productToken : 'whitesourceProductToken',
projectNames : 'whitesourceProjectNames',
userTokenCredentialsId : 'whitesourceUserTokenCredentialsId'
],
orgAdminUserTokenCredentialsId : 'whitesource.orgAdminUserTokenCredentialsId',
orgToken : 'whitesource.orgToken',
productName : 'whitesource.productName',
productVersion : 'whitesource.productVersion',
productToken : 'whitesource.productToken',
projectNames : 'whitesource.projectNames',
scanType : 'whitesource.scanType',
serviceUrl : 'whitesource.serviceUrl',
userTokenCredentialsId : 'whitesource.userTokenCredentialsId'
productName : 'whitesourceProductName',
productToken : 'whitesourceProductToken',
projectNames : 'whitesourceProjectNames',
userTokenCredentialsId : 'whitesourceUserTokenCredentialsId',
serviceUrl : 'whitesourceServiceUrl',
agentDownloadUrl : 'fileAgentDownloadUrl',
agentParameters : 'fileAgentParameters',
whitesource : [
orgAdminUserTokenCredentialsId : 'orgAdminUserTokenCredentialsId',
orgToken : 'orgToken',
productName : 'productName',
productToken : 'productToken',
projectNames : 'projectNames',
serviceUrl : 'serviceUrl',
userTokenCredentialsId : 'userTokenCredentialsId',
verbose : 'verbose',
agentDownloadUrl : 'agentDownloadUrl',
agentFileName : 'agentFileName',
agentParameters : 'agentParameters',
buildDescriptorExcludeList : 'buildDescriptorExcludeList',
buildDescriptorFile : 'buildDescriptorFile',
createProductFromPipeline : 'createProductFromPipeline',
emailAddressesOfInitialProductAdmins : 'emailAddressesOfInitialProductAdmins',
jreDownloadUrl : 'jreDownloadUrl',
licensingVulnerabilities : 'licensingVulnerabilities',
parallelLimit : 'parallelLimit',
reporting : 'reporting',
securityVulnerabilities : 'securityVulnerabilities',
cvssSeverityLimit : 'cvssSeverityLimit',
timeout : 'timeout',
vulnerabilityReportFileName : 'vulnerabilityReportFileName',
vulnerabilityReportTitle : 'vulnerabilityReportTitle'
]
]
/**
@ -199,16 +221,17 @@ void call(Map parameters = [:]) {
.dependingOn('scanType').mixin('dockerImage')
.dependingOn('scanType').mixin('dockerWorkspace')
.dependingOn('scanType').mixin('stashContent')
.withMandatoryProperty('serviceUrl')
.withMandatoryProperty('orgToken')
.withMandatoryProperty('userTokenCredentialsId')
.withMandatoryProperty('productName')
.withMandatoryProperty('whitesource/serviceUrl')
.withMandatoryProperty('whitesource/orgToken')
.withMandatoryProperty('whitesource/userTokenCredentialsId')
.withMandatoryProperty('whitesource/productName')
.use()
config.cvssSeverityLimit = config.cvssSeverityLimit == null ? -1 : Integer.valueOf(config.cvssSeverityLimit)
config.whitesource.cvssSeverityLimit = config.whitesource.cvssSeverityLimit == null ? -1 : Integer.valueOf(config.whitesource.cvssSeverityLimit)
config.stashContent = utils.unstashAll(config.stashContent)
config.projectNames = (config.projectNames instanceof List) ? config.projectNames : config.projectNames?.tokenize(',')
parameters.projectNames = config.projectNames
config.whitesource['projectNames'] = (config.whitesource['projectNames'] instanceof List) ? config.whitesource['projectNames'] : config.whitesource['projectNames']?.tokenize(',')
parameters.whitesource = parameters.whitesource ?: [:]
parameters.whitesource['projectNames'] = config.whitesource['projectNames']
script.commonPipelineEnvironment.setInfluxStepData('whitesource', false)
@ -223,7 +246,7 @@ void call(Map parameters = [:]) {
def whitesourceRepository = parameters.whitesourceRepositoryStub ?: new WhitesourceRepository(this, config)
def whitesourceOrgAdminRepository = parameters.whitesourceOrgAdminRepositoryStub ?: new WhitesourceOrgAdminRepository(this, config)
if(config.orgAdminUserTokenCredentialsId) {
if(config.whitesource.orgAdminUserTokenCredentialsId) {
statusCode = triggerWhitesourceScanWithOrgAdminUserKey(script, config, utils, descriptorUtils, parameters, whitesourceRepository, whitesourceOrgAdminRepository)
} else {
statusCode = triggerWhitesourceScanWithUserKey(script, config, utils, descriptorUtils, parameters, whitesourceRepository, whitesourceOrgAdminRepository)
@ -236,34 +259,34 @@ void call(Map parameters = [:]) {
private def triggerWhitesourceScanWithOrgAdminUserKey(script, config, utils, descriptorUtils, parameters, repository, orgAdminRepository) {
withCredentials ([script.string(
credentialsId: config.orgAdminUserTokenCredentialsId,
credentialsId: config.whitesource.orgAdminUserTokenCredentialsId,
variable: 'orgAdminUserKey'
)]) {
config.orgAdminUserKey = orgAdminUserKey
config.whitesource.orgAdminUserKey = orgAdminUserKey
triggerWhitesourceScanWithUserKey(script, config, utils, descriptorUtils, parameters, repository, orgAdminRepository)
}
}
private def triggerWhitesourceScanWithUserKey(script, config, utils, descriptorUtils, parameters, repository, orgAdminRepository) {
withCredentials ([string(
credentialsId: config.userTokenCredentialsId,
credentialsId: config.whitesource.userTokenCredentialsId,
variable: 'userKey'
)]) {
config.userKey = userKey
config.whitesource.userKey = userKey
def statusCode = 1
echo "Triggering Whitesource scan on product '${config.productName}'${config.productToken ? ' with token \'' + config.productToken + '\'' : ''} using product admin credentials with ID '${config.userTokenCredentialsId}'${config.orgAdminUserTokenCredentialsId ? ' and organization admin credentials with ID \'' + config.orgAdminUserTokenCredentialsId + '\'' : ''}"
echo "Triggering Whitesource scan on product '${config.whitesource.productName}'${config.whitesource.productToken ? ' with token \'' + config.whitesource.productToken + '\'' : ''} using product admin credentials with ID '${config.whitesource.userTokenCredentialsId}'${config.whitesource.orgAdminUserTokenCredentialsId ? ' and organization admin credentials with ID \'' + config.whitesource.orgAdminUserTokenCredentialsId + '\'' : ''}"
if (!config.productToken) {
if (!config.whitesource.productToken) {
def metaInfo = orgAdminRepository.fetchProductMetaInfo()
def key = "token"
if((null == metaInfo || !metaInfo[key]) && config.createProductFromPipeline) {
metaInfo = orgAdminRepository.createProduct()
key = "productToken"
} else if(null == metaInfo || !metaInfo[key]) {
error "[WhiteSource] Could not fetch/find requested product '${config.productName}' and automatic creation has been disabled"
error "[WhiteSource] Could not fetch/find requested product '${config.whitesource.productName}' and automatic creation has been disabled"
}
echo "Meta Info: ${metaInfo}"
config.productToken = metaInfo[key]
config.whitesource.productToken = metaInfo[key]
}
switch (config.scanType) {
@ -285,7 +308,7 @@ private def triggerWhitesourceScanWithUserKey(script, config, utils, descriptorU
this, mtaParameters, config.buildDescriptorExcludeList, 'Whitesource', 'setup.py', 'pip'
) { options -> whitesourceExecuteScan(options) })
// execute scan jobs
if (config.parallelLimit > 0 && config.parallelLimit < scanJobs.keySet().size()) {
if (config.whitesource.parallelLimit > 0 && config.whitesource.parallelLimit < scanJobs.keySet().size()) {
// block wise
def scanJobsAll = scanJobs
scanJobs = [failFast: false]
@ -293,7 +316,7 @@ private def triggerWhitesourceScanWithUserKey(script, config, utils, descriptorU
def index = i - 1
def key = scanJobsAll.keySet()[index]
scanJobs[key] = scanJobsAll[key]
if (i % config.parallelLimit == 0 || i == scanJobsAll.keySet().size()) {
if (i % config.whitesource.parallelLimit == 0 || i == scanJobsAll.keySet().size()) {
parallel scanJobs
scanJobs = [failFast: false]
}
@ -311,53 +334,53 @@ private def triggerWhitesourceScanWithUserKey(script, config, utils, descriptorU
switch (config.scanType) {
case 'npm':
gav = descriptorUtils.getNpmGAV(config.buildDescriptorFile)
config.projectName = gav.group + "." + gav.artifact
config.productVersion = gav.version
config.whitesource.projectName = gav.group + "." + gav.artifact
config.whitesource.productVersion = gav.version
break
case 'sbt':
gav = descriptorUtils.getSbtGAV(config.buildDescriptorFile)
config.projectName = gav.group + "." + gav.artifact
config.productVersion = gav.version
config.whitesource.projectName = gav.group + "." + gav.artifact
config.whitesource.productVersion = gav.version
break
case 'pip':
gav = descriptorUtils.getPipGAV(config.buildDescriptorFile)
config.projectName = gav.artifact
config.productVersion = gav.version
config.whitesource.projectName = gav.artifact
config.whitesource.productVersion = gav.version
break
default:
gav = descriptorUtils.getMavenGAV(config.buildDescriptorFile)
config.projectName = gav.group + "." + gav.artifact
config.productVersion = gav.version
config.whitesource.projectName = gav.group + "." + gav.artifact
config.whitesource.productVersion = gav.version
break
}
config.projectNames.add("${config.projectName} - ${config.productVersion}".toString())
config.whitesource['projectNames'].add("${config.whitesource.projectName} - ${config.whitesource.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 (config.whitesource.agentDownloadUrl) {
def agentDownloadUrl = new GStringTemplateEngine().createTemplate(config.whitesource.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()
sh "curl ${script.env.HTTP_PROXY ? '--proxy ' + script.env.HTTP_PROXY + ' ' : ''}--location --output ${config.whitesource.agentFileName} ${agentDownloadUrl}".toString()
}
def javaCmd = 'java'
if (config.jreDownloadUrl) {
if (config.whitesource.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()
sh "curl ${script.env.HTTP_PROXY ? '--proxy ' + script.env.HTTP_PROXY + ' ' : ''}--location --output jvm.tar.gz ${config.whitesource.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}'")
def options = ["-jar ${config.whitesource.agentFileName} -c \'${config.configFilePath}\'"]
if (config.whitesource.orgToken) options.push("-apiKey '${config.whitesource.orgToken}'")
if (config.whitesource.userKey) options.push("-userKey '${config.whitesource.userKey}'")
if (config.whitesource.productName) options.push("-product '${config.whitesource.productName}'")
statusCode = sh(script: "${javaCmd} ${options.join(' ')} ${config.agentParameters}", returnStatus: true)
statusCode = sh(script: "${javaCmd} ${options.join(' ')} ${config.whitesource.agentParameters}", returnStatus: true)
if (config.agentDownloadUrl) {
sh "rm -f ${config.agentFileName}"
if (config.whitesource.agentDownloadUrl) {
sh "rm -f ${config.whitesource.agentFileName}"
}
if (config.jreDownloadUrl) {
if (config.whitesource.jreDownloadUrl) {
sh "rm -rf ./bin ./conf ./legal ./lib ./man"
}
@ -381,18 +404,18 @@ void analyseWhitesourceResults(Map config, WhitesourceRepository repository) {
archiveArtifacts artifacts: pdfName
echo "A summary of the Whitesource findings was stored as artifact under the name ${pdfName}"
if(config.licensingVulnerabilities) {
if(config.whitesource.licensingVulnerabilities) {
def violationCount = fetchViolationCount(config, repository)
checkViolationStatus(violationCount)
}
if (config.securityVulnerabilities)
config.severeVulnerabilities = checkSecurityViolations(config, repository)
if (config.whitesource.securityVulnerabilities)
config.whitesource.severeVulnerabilities = checkSecurityViolations(config, repository)
}
int fetchViolationCount(Map config, WhitesourceRepository repository) {
int violationCount = 0
if (config.projectNames) {
if (config.whitesource?.projectNames) {
def projectsMeta = repository.fetchProjectsMetaInfo()
for (int i = 0; i < projectsMeta.size(); i++) {
def project = projectsMeta[i]
@ -415,22 +438,22 @@ void checkViolationStatus(int violationCount) {
}
int checkSecurityViolations(Map config, WhitesourceRepository repository) {
def whitesourceProjectsMetaInformation = repository.fetchProjectsMetaInfo()
def whitesourceVulnerabilities = repository.fetchVulnerabilities(whitesourceProjectsMetaInformation)
def projectsMetaInformation = repository.fetchProjectsMetaInfo()
def vulnerabilities = repository.fetchVulnerabilities(projectsMetaInformation)
def severeVulnerabilities = 0
whitesourceVulnerabilities.each {
vulnerabilities.each {
item ->
if ((item.vulnerability.score >= config.cvssSeverityLimit || item.vulnerability.cvss3_score >= config.cvssSeverityLimit) && config.cvssSeverityLimit >= 0)
if ((item.vulnerability.score >= config.whitesource.cvssSeverityLimit || item.vulnerability.cvss3_score >= config.whitesource.cvssSeverityLimit) && config.whitesource.cvssSeverityLimit >= 0)
severeVulnerabilities++
}
writeFile(file: "${config.vulnerabilityReportFileName}.json", text: new JsonUtils().getPrettyJsonString(whitesourceVulnerabilities))
writeFile(file: "${config.vulnerabilityReportFileName}.html", text: getReportHtml(config, whitesourceVulnerabilities, severeVulnerabilities))
writeFile(file: "${config.vulnerabilityReportFileName}.json", text: new JsonUtils().getPrettyJsonString(vulnerabilities))
writeFile(file: "${config.vulnerabilityReportFileName}.html", text: getReportHtml(config, vulnerabilities, 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 ${config.cvssSeverityLimit} detected."
if (whitesourceVulnerabilities.size() == 0)
if (vulnerabilities.size() - severeVulnerabilities > 0)
echo "[${STEP_NAME}] WARNING: ${vulnerabilities.size() - severeVulnerabilities} Open Source Software Security vulnerabilities with CVSS score below ${config.whitesource.cvssSeverityLimit} detected."
if (vulnerabilities.size() == 0)
echo "[${STEP_NAME}] No Open Source Software Security vulnerabilities detected."
return severeVulnerabilities
@ -439,9 +462,9 @@ int checkSecurityViolations(Map config, WhitesourceRepository repository) {
// 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 ${config.cvssSeverityLimit} detected. - "
if (config.licensingVulnerabilities)
if(config.whitesource.securityVulnerabilities && config.whitesource.severeVulnerabilities > 0)
errorMessage += "${config.whitesource.severeVulnerabilities} Open Source Software Security vulnerabilities with CVSS score greater or equal ${config.whitesource.cvssSeverityLimit} detected. - "
if (config.whitesource.licensingVulnerabilities)
switch (statusCode) {
case 0:
break
@ -505,12 +528,12 @@ def getReportHtml(config, vulnerabilityList, numSevereVulns) {
return SimpleTemplateEngine.newInstance().createTemplate(libraryResource('com.sap.piper/templates/whitesourceVulnerabilities.html')).make(
[
now : now,
reportTitle : config.vulnerabilityReportTitle,
reportTitle : config.whitesource.vulnerabilityReportTitle,
style : config.style,
totalSevereVulnerabilities : numSevereVulns,
totalVulnerabilities : vulnerabilityList.size(),
vulnerabilityTable : vulnerabilityTable,
whitesourceProductName : config.productName,
whitesourceProjectNames : config.projectNames
whitesourceProductName : config.whitesource.productName,
whitesourceProjectNames : config.whitesource.projectNames
]).toString()
}