本篇是cicd-goat靶场系列的第三篇文章,这篇文章涉及环境中CI/CD的工作流是如何工作的。
解题记录参见第一篇文章第二篇文章

CI/CD工作流是如何工作的?

Jenkins: Multibranch Pipeline

以管理员admin用户登录Jenkins后,可以查看每个项目的配置,比较重要的是下面两个配置:

  1. Branch Sources指定CI/CD工作流的输入,即要被自动化处理的内容,比如要构建的源代码等;
    比较复杂的选项是Behaviours,这里定义了大量的动作,比如发现分支、标签,或是检查PR等。

  2. Build Configuration定义了构建过程的配置,主要是指定Jenkinsfile文件的来源。
    它可以是本地项目里的Jenkinsfile,也可以是远程的Jenkinsfile提供插件(比如其他git项目)。

我整理了cicd-goat靶场环境中各环境的Jenkins项目配置,汇总情况如下表:
(注:项目中twiddle和dodo这两个项目是文件夹形式、而非Mulitbranch Pipeline,后面单独分析。)

Branch Sources -> Behaviours选项中:

  • 第一项Filter by name (with wildcards),是指包含哪些名称会被包含/排除,这里的名称应用在分支、标签和变更请求上,根据StackOverflow上的这个回答,必须要同时使用Discover branches
  • 第二项Discover branches决定哪些分支会被Jenkins发现,有三种选项:排除掉作为PR提交的分支、仅包含作为PR提交的分支、所有分支。
  • 第三项Discover pull requests from origin,是否发现源仓库的PR请求,只有一个选项是对PR的处理策略:合并之后处理、合并前处理、合并前后都处理
  • 第四项Discover pull requests from forks,是否发现来自Fork仓库的PR请求,有两个细分选项,一个是对PR的处理策略:合并之后处理、合并前处理、合并前后都处理;另一个是信任谁:都不信任(当Jenkins需要一个受信任的文件(如Jenkinsfile)时,会从原项目中取得、而不是PR分支里),贡献者和所有人。
  • 最后一项所有设置了Property strategy属性的项目,设置的值都是All branches get the same properties
    指所有的分支都得到相同的属性,我理解这里的分支指的是Jenkins里的分支,而不是Git版本管理里的代码分支。

注:Filter by name (with wildcards)中name指的是Git里的name还是Jenkins里的name,我自己没找到确定的说明,我个人更倾向于后者,或者说是Jenkins Job的name。

根据Jenkins中项目的配置,回顾靶场解题步骤,可以梳理出工作流执行的逻辑:

  1. white rabbit中,Jenkins监听所有分支且类型为PR的变动,而且gitea用户可以在项目中创建分支、提交PR,因此能触发工作流;
  2. mad hatter中使用mad-hatter-pipeline项目中的Jenkinsfile文件,Jenkins监听没有提交PR、且名字不是main的分支,因此修改Makefile、新建分支即可触发工作流;
  3. catepillar-test中Jenkins监听来自Fork的PR而且信任所有人,导致可以泄露GITEA_TOKEN,进而通过API直接修改main分支、篡改Jenkinsfile,从而窃取catepillar-prod生产环境中的敏感信息;
  4. cheshire-cat的工作流逻辑与white rabbit一致,区别是指定任务运行节点、进而拿到Jenkins Controller节点权限、实现了提权;
  5. dormouse中我们并不能对源项目进行任何修改,只能选择运行工作流。但工作流中的依赖组件可以被污染,从而影响了dormouse环境;
  6. mock-turtle工作流逻辑与white rabbit基本一致,主要区别是1)mock-turtle采用远程项目的Jenkinsfile实现了拉取Gitea仓库代码与执行代码合并逻辑的Gitea用户分离,2)mock-turtle工作流中对PR进行了三重简单校验。

Jenkins: Freestyle project

twiddle项目是个文件夹,里面只包含一个Freestyle类型的任务job:twiddledum,这是一种自由度比较高的任务类型,我理解是从手工构建走向CI/CD过渡早期时的选择。

Freestyle类型任务配置项包括源代码设置、构建的触发条件设置、构建前环境准备设置、构建的具体命令步骤、构建后的动作设置等。

其中构建条件支持周期执行、通用Webhook触发和源代码变动监控等。

Jenkins: Pipeline

cov-reportcov项目类型为PipelineMultibranch Pipeline由一系列不同分支的Pipeline组成。

在Jenkins中cov-reportcov项目的触发方式设置为Webhook,同时在Gitea的reportcov项目对应设置Webhooks。

在Gitea中配置什么情况下发送Webhook请求:

Jenkins中项目里使用比较复杂的配置来提取Gitea传递的请求,并以环境变量形式传递给Jenkinsfile。

Jenkins: Multi-configuration project (Matrix)

这种项目类型由Matrix Project插件提供,旨在提供对相似的构建过程但是不同的版本、环境中进行批量构建。

Matrix的思路在Github Action中也有实现,可以参考这篇文章:Running variations of jobs in a workflow,文章将Matirx的思路理解成定义了多个变量、并对这些变量的可能取值进行排列组合,按照所有的组合情况运行任务。

Gitlab CI中也有类似的实现,可以参考Gitlba的文档:Parallelize large jobs

Gitlab任务触发

cicd-goat靶场环境里Gitlab环境通过CICD - Schedules配置定时任务来周期性执行构建任务,任务在项目的.gitlab-ci.yaml文件中定义。