跳过正文
Background Image
  1. Posts/

Black Duck 与 Jenkins 集成

·1010 字·3 分钟· ·
沈显鹏
作者
沈显鹏
目录

最近做了 Black Duck 与 Jenkins 的集成,目标是给测试和开发提供定制化、定时的对各个开发代码仓库的进行源码扫描。

为什么要做源码扫描
#

在产品开发中经常需要引入一些开源组件,但这些开源的代码会给产品风险。因此我们在发布自己产品的时候需要对这些开源组件的漏洞和许可信息进行评估。

开源不等于安全

Black Duck(黑鸭)是一款对源代码进行扫描、审计和代码管理的软件工具(同类型的工具还有 JFrog Xray)。能够搜索安全的开源代码,检测产品的开源代码使用情况,以检查外来代码的开源代码使用情况和风险情况。

如果不能及时的进行代码扫描,在产品发布快要发布才进行扫描,如果发现问题这时候再去解决就会变得非常被动,因此团队需要尽早发现并解决问题,将 CI 工具进行集成,进行每日、每周、每月扫描就变得十分重要。

Black Duck 手动执行一般步骤
#

  1. 手动下载指定 Git 仓库及分支代码
  2. 去掉不相关的代码(也可以通过 Black Duck 参数去指定要扫描的特定文件或文件夹)
  3. 手动执行 Black Duck 扫描命令​
  4. 扫描成功后,结果传到内部 Black Duck 网站供相关人员进行审查

Black Duck 与 Jenkins 的集成目标
#

  1. 一个流水线支持定制化仓库的代码下载
  2. 给开发和测试提供简单的、可随时可以执行源码扫描的界面
  3. 支持定期自动扫描,以及与其他 Jenkins 任务联动执行​

Black Duck 参数介绍
#

--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

Black Duck 配置
#

首先,安装 Black Duck 插件 Synopsys Detect 到 Jenkins

然后,配置 Synopsys Detect 插件

  • Jenkins -> Confiruration(系统配置)
  • Black Duck URL: 公司内部的 Black Duck 网址,例如 https://yourcompany.blackducksoftware.com
  • Black Duck credentials: 注意要选择 credentials 类型为 Secret text, Secret 填写你用户的 Token
    Secret text 配置
  • 配置完成后点击 Test connections to Black Duck,显示 Connection successful 表示配置成功。
    Connection successful

Black Duck 流水线任务效果
#

Build with Parameters

Black Duck 流水线代码
#

pipeline{
  agent {
    node {
      label 'black-duck'
      customWorkspace "/agent/workspace/blackduck"
    }
  }

  parameters {
    choice(
      name: 'VERSION',
      choices: ['MVSURE_v1.1', 'MVSURE_v1.2', 'MVSURE_v2.2'],
      summary: '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'],
      summary: 'Which repository code does above VERSION belong to?')
    string(
      name: 'BRANCH',
      defaultValue: 'develop',
      summary: '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'],
      summary: '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()
    }
  }
}

相关文章

如何通过 Jenkins 进行资源的锁定和释放
·901 字·2 分钟
本文介绍了如何使用 Jenkins 的 Lockable Resources 插件来管理和锁定资源,确保在多任务环境中资源的独占性和安全性。
通过 Jenkins 来提交修改的代码 git push by Jenkins
·439 字·1 分钟
如何通过 Jenkins Pipeline 脚本来提交修改的代码到 Git 仓库,包括克隆仓库、修改代码和推送更改等步骤。
Jenkins Linux Agent 配置
·353 字·1 分钟
本文提供了 Jenkins Linux Agent 的逐步配置指南,包括 Java 运行时的准备、节点创建以及常见问题的排查方法。
Jenkins Windows Agent 配置
·608 字·2 分钟
本文提供 Jenkins Windows Agent 的详细配置步骤,包括 Java 运行时准备、节点创建以及常见问题的排查方法。
Jenkinsfile 配置
·256 字·1 分钟
本文介绍了如何使用 Jenkinsfile 配置 Jenkins Pipeline,包括构建、测试和发布阶段的示例,以及如何处理邮件通知。
北京48小时:记一次参加 DevOps 训练营
·1884 字·4 分钟
记录我在北京参加 JFrog DevOps 训练营的经历,分享培训内容和个人感受,以及对未来工作的思考。