mirror of
https://github.com/SAP/jenkins-library.git
synced 2025-03-05 15:15:44 +02:00
Refactored to generally migrate config to deep structure
This commit is contained in:
parent
f2c7265986
commit
c96f73866a
@ -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' ]
|
||||
```
|
||||
|
@ -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 ->
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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. - "))
|
||||
|
@ -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() {
|
||||
|
||||
|
@ -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"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user