文件引用

# 背景

流水线配置文件可以引用其他文件,用作流水线配置、环境变量、任务参数等。

文件中可能存在敏感信息,需要对文件引用进行权限检查,以避免敏感信息泄漏。

# 引用方式

CNB 中有如下四种配置文件引用方式:

注意:

为了方便灵活的配置流水线任务的参数,importsoptionsFromsettingsFrom 声明的文件路径支持使用环境变量。

可事先在流水线中声明环境变量,然后在任务中引用,如:

main:
  push:
    - env:
        CNB_CONFIG_URL: https://xxx.com/p1/xxx
        CNB_CONFIG_FILE: account.yml
      imports:
        # 假设 env1.yml 声明变量 CNB_ENV_FILE_URL
        - https://xxx.com/p1/xxx/env1.yml
        # imports后面的文件路径支持使用前面文件中声明的环境变量
        - ${CNB_ENV_FILE_URL}/env2.yml
      stages:
        - name: echo
          script: echo 1
        - name: 内置任务
          type: some-type
          optionsFrom:
            - ${CNB_CONFIG_URL}/${CNB_CONFIG_FILE}
        - name: 插件任务
          image: some-image
          settingsFrom:
            - ${CNB_CONFIG_URL}/${CNB_CONFIG_FILE}

同时 optionsFromsettingsFrom 支持读取本地文件,即便仓库中无 ./path/to/file,但可以在流水线中写入该文件,让流水线执行时加载,如:

main:
  push:
    - env:
        CNB_CONFIG_URL: https://xxx.com/p1/xxx
        CNB_CONFIG_FILE: account.yml
      stages:
        - name: echo
          script: echo some-content > ./path/to/file-not-in-git
        - name: 内置任务
          type: some-type
          optionsFrom:
            # 引用仓库不存在但流水线生成的文件
            - ./path/to/file-not-in-git
        - name: 插件任务
          image: some-image
          settingsFrom:
            # 引用仓库存在的文件
            - ./path/to/file-in-git

# 文件类型

CNB 中,支持引用的配置文件分为三种类型:

# yaml 文件

文件名后缀为 .yml.yaml,如:

account.yml

SOME_ACCOUNT: some-account
SOME_PASSWORD: some-password

# json 文件

文件名后缀为 .json,如:

account.json

{
  "SOME_ACCOUNT": "some-account",
  "SOME_PASSWORD": "some-password"
}

# 文本文件

非以上两种文件类型,会被当作文本文件解析,如:

account.txt

SOME_ACCOUNT=some-account
SOME_PASSWORD=some-password

# 权限检查

配置文件可声明四个字段:allow_imagesallow_eventsallow_slugsallow_branches 控制可访问范围,四个字段均为 glob 模式字符串或字符串数组。

CNB 关于流水线是否可以加载目标文件的权限检查流程图如下:

关于以上流程图的说明:

  • 同源仓库:流水线和目标文件属于同一个仓库。
  • pull_request事件:PR 中,特别是 fork 仓库提 PR 时,源分支代码未经管理员评审,代码不可信。出于安全考虑,配置文件必须配置了 allow_events 才能被 pull_request 流水线引用。
  • 插件任务:
    • 参数可以通过 settingsFrom 设置,也可以 imports 引入后通过环境变量的方式设置,这两种方式均被认为是插件任务引用文件。
    • 镜像名不带标签时,会以 镜像名镜像名:latest 去匹配 allow_images,匹配一个即算通过。
    • 注意:job 同时设置了 image、script 属于脚本任务,image作为执行环境,此场景下 image 视为空字符串,不能匹配 **
  • branch: allow_branches 检查的 branch 同CNB_BRANCH

# 示例

# 流水线模版引用

# 被引用配置文件 template.yml
allow_slugs:
  - "p1/**"
main:
  push:
    - stages:
        - name: echo
          script: echo 1
# 流水线配置文件 .cnb.yml
include:
  - https://xxx.com/p1/xxx/-/blob/main/template.yml

流水线配置文件引用其他私有仓库中的配置文件 template.yml,流水线触发者无其 pull 权限,但被引用文件声明 allow_slugs 指定了 p1/**,流水线仓库若在组织 p1 下,slug 检查通过,否则不通过。

这样避免了流水线模版文件被恶意修改,同时又能被特定组织下的仓库流水线引用。

# 插件任务参数引用

# 被引用配置文件
allow_images:
  - "registry.com/image1/**"
allow_slugs:
  - "p1/**"
arg1: arg1
arg2: arg2
# 配置文件 插件任务
name: image job
image: registry.com/image1/print:latest
settingsFrom:
  - xxx.com/xxx/image-settings.yml

image: registry.com/image1/print:latest 符合 registry.com/image1/**,image 检查通过。

allow_slugs 指定了 p1/**,流水线仓库在组织 p1 下,slug 检查通过,否则不通过。

这样限制了配置文件只能在特定组织下的仓库流水线中特定镜像名的插件任务中使用,避免了敏感信息泄漏。

# 限制事件、分支

一种常见场景是,在仓库主分支 pushtag_push 事件中发布到 npm 、docker hub。

为保护敏感信息,可将 passwordtoken 等敏感信息配置在其他私有仓库文件中。

为了避免开发人员在其他其他分支 push 事件中随意发布到 npm 、docker hub,或 fork 仓库后在 pull_request 事件中打印出敏感信息

可在配置文件中声明 allow_eventsallow_branches 字段,限制使用范围。

allow_events:
  - tag_push
  - tag_deploy.*

SOME_ACCOUNT: some-account
SOME_PASSWORD: some-password

allow_events:
  - push
allow_branches:
  - main

SOME_ACCOUNT: some-account
SOME_PASSWORD: some-password