最近做了 Black Duck 与 Jenkins 的集成,目标是给测试和开发提供定制化、定时的对开发代码仓库的进行源码以及许可信息扫描。
在产品开发中经常需要引入一些开源组件,但这些开源的代码的漏洞和许可信息等问题会给产品带来安全以及商业风险,因此在发布产品前需要对这些开源组件的漏洞和许可信息进行扫描。
Black Duck(黑鸭)是一款可以对源代码进行扫描、审计和代码管理的软件工具,能够搜索安全的开源代码,检测产品的开源代码使用情况和风险情况。
同类型的工具还有 JFrog Xray
但是,如果不能及时的进行代码扫描,在产品发布快要发布甚至发布后才进行扫描,这时候发现问题再去解决就会变得非常被动,因此团队需要尽早发现并解决问题安全以及许可信息等问题,因此将 Black Duck 与 CI 工具集成进行每月、每周、甚至每日构建就变得十分重要。
--blackduck.url # 你的 Black Duck 网址
--blackduck.username # 你的登录用户
--blackduck.api.token # 你的登录用户 Token
--detect.project.name # Black Duck 下面的项目
--detect.project.version.name # 项目版本号
--detect.source.path # 要扫描的代码目录
--logging.level.com.synopsys.integration # 扫描日志级别
--blackduck.trust.cert=TRUE # 是否信任 socket (SSL)
--detect.blackduck.signature.scanner.snippet.matching # 扫描片段模式
更多其他参数可以参照官方的 CI 集成文档 Synopsys Detect for Jenkins https://synopsys.atlassian.net/wiki/spaces/INTDOCS/pages/71106939/Synopsys+Detect+for+Jenkins
首先,安装 Black Duck 插件 Synopsys Detect 到 Jenkins
然后,配置 Synopsys Detect 插件
pipeline{
agent {
node {
label 'black-duck'
customWorkspace "/agent/workspace/blackduck"
}
}
parameters {
choice(
name: 'VERSION',
choices: ['MVSURE_v1.1', 'MVSURE_v1.2', 'MVSURE_v2.2'],
description: 'Which version do you want scan on black duck? MVSURE_v1.1, MVSURE_v1.2 or others?')
choice(
name: 'REPO',
choices: ['blog-server', 'blog-client', 'blog-docker'],
description: 'Which repository code does above VERSION belong to?')
string(
name: 'BRANCH',
defaultValue: 'develop',
description: 'Which branch does above VERSION belong to?')
choice(
name: 'SNIPPET-MODES',
choices: ['SNIPPET_MATCHING', 'SNIPPET_MATCHING_ONLY', 'FULL_SNIPPET_MATCHING', 'FULL_SNIPPET_MATCHING_ONLY', 'NONE'],
description: 'What snippet scan mode do you want to choose?')
}
environment {
ROBOT = credentials("d1cbab74-823d-41aa-abb7-858485121212")
hub_detect = 'https://blackducksoftware.github.io/hub-detect/hub-detect.sh'
blackduck_url = 'https://yourcompany.blackducksoftware.com'
blackduck_user = 'robot@yourcompany.com'
detect_project = 'GITHUB'
detect_project_version = '${VERSION}'
detect_source_path = '${WORKSPACE}/${REPO}/src'
}
# 只保留最近十次 Jenkins 执行结果
options {buildDiscarder(logRotator(numToKeepStr:'10'))}
# 定时触发可以在这里添加
stages {
stage("git clone"){ # 参数化 git clone 代码过程
steps{
sh '''
if [ -d ${REPO} ]; then
rm -rf ${REPO}
fi
git clone -b ${BRANCH} --depth 1 https://$ROBOT_USR:"$ROBOT_PSW"@git.yourcompany.com/scm/github/${REPO}.git
'''
}
}
stage("black duck scan"){ # 参数化 Black Duck 所用到的参数值
steps {
withCredentials([string(credentialsId: 'robot-black-duck-scan', variable: 'TOKEN')]) { # 用 withCredentials 来获得 Token
synopsys_detect 'bash <(curl -s ${hub_detect}) --blackduck.url=${blackduck_url} --blackduck.username=${blackduck_user} --blackduck.api.token=${TOKEN} --detect.project.name=${detect_project} --detect.project.version.name=${detect_project_version} --detect.source.path=${detect_source_path} --logging.level.com.synopsys.integration=debug --blackduck.trust.cert=TRUE --detect.blackduck.signature.scanner.snippet.matching=${SNIPPET-MODES}'
}
}
}
}
post {
# 不论结果任何都给执行者发送邮件通知
always {
script {
def email = load "vars/email.groovy"
wrap([$class: 'BuildUser']) {
def user = env.BUILD_USER_ID
email.build(currentBuild.result, "${user}")
}
}
}
success {
echo "success, cleanup blackduck workspace"
cleanWs()
}
}
}