文件引用

背景

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

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

引用方式

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

注意:

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

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

 1main:
 2  push:
 3    - env:
 4        CNB_CONFIG_URL: https://cnb.cool/<your-repo-slug>/-/blob/main/xxx
 5        CNB_CONFIG_FILE: account.yml
 6      imports:
 7        # 假设 env1.yml 声明变量 CNB_ENV_FILE_URL
 8        - https://cnb.cool/<your-repo-slug>/-/blob/main/xxx/env1.yml
 9        # imports后面的文件路径支持使用前面文件中声明的环境变量
10        - ${CNB_ENV_FILE_URL}/env2.yml
11      stages:
12        - name: echo
13          script: echo 1
14        - name: 内置任务
15          type: some-type
16          optionsFrom:
17            - ${CNB_CONFIG_URL}/${CNB_CONFIG_FILE}
18        - name: 插件任务
19          image: some-image
20          settingsFrom:
21            - ${CNB_CONFIG_URL}/${CNB_CONFIG_FILE}

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

 1main:
 2  push:
 3    - env:
 4        CNB_CONFIG_URL: https://xxx.com/p1/xxx
 5        CNB_CONFIG_FILE: account.yml
 6      stages:
 7        - name: echo
 8          script: echo some-content > ./path/to/file-not-in-git
 9        - name: 内置任务
10          type: some-type
11          optionsFrom:
12            # 引用仓库不存在但流水线生成的文件
13            - ./path/to/file-not-in-git
14        - name: 插件任务
15          image: some-image
16          settingsFrom:
17            # 引用仓库存在的文件
18            - ./path/to/file-in-git

文件类型

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

yaml 文件

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

account.yml

1SOME_ACCOUNT: some-account
2SOME_PASSWORD: some-password

json 文件

文件名后缀为 .json,如:

account.json

1{
2  "SOME_ACCOUNT": "some-account",
3  "SOME_PASSWORD": "some-password"
4}

文本文件

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

account.txt

1SOME_ACCOUNT=some-account
2SOME_PASSWORD=some-password

权限检查

对于公开或同源仓库的配置文件,流水线可直接引用。

对于私有且非同源仓库的配置文件,可声明四个字段:allow_slugsallow_eventsallow_branchesallow_images 控制可被访问范围,四个字段均为 glob 模式字符串字符串数组

若未声明上述四个字段,则会检查流水线触发者是否有用配置文件所属仓库的读权限

其中:

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

整体流程:

  
    flowchart LR
    subgraph allow检查
      slug检查 --> branch检查 --> image检查 --> event检查
    end
    subgraph allow必要性检查
      allow_events必要性检查 --> allow_images必要性检查
    end
    start([开始]) --> 公开仓库{公开仓库?}
    公开仓库 --是--> 可访问
    公开仓库 --否--> 同源仓库{同源仓库?}
    同源仓库 --是--> 可访问
    同源仓库 --否--> allow必要性检查[allow必要性检查]
    allow必要性检查 --> 必要性检查通过{检查通过?}
    必要性检查通过 -- 是 --> allow声明{有allow声明?}
    必要性检查通过 -- 否 --> 不可访问
    allow声明 -- 否 --> 有文件读权限{文件读权限?}
    allow声明 -- 是 --> allow检查[allow检查]
    有文件读权限 --有--> 可访问
    有文件读权限 --无--> 不可访问
    allow检查 --> allow检查通过{检查通过?}
    allow检查通过 --是--> 可访问
    allow检查通过 --否--> 不可访问
  

流程图说明:

  
    flowchart LR
  strat([allow必要性检查]) --> pull_request事件{pull_request事件?}
    pull_request事件 --否--> 镜像任务{镜像任务?}
    pull_request事件 --是--> 声明allow_events{声明allow_events?}
    声明allow_events --是--> 镜像任务{镜像任务?}
    声明allow_events --否--> 不通过
    镜像任务 --否--> 通过
    镜像任务 --是--> 声明allow_images{声明allow_images?}
    声明allow_images --否--> 不通过
    声明allow_images --是--> 通过
  

allow 必要性检查说明:

  
    flowchart LR
  strat([slug检查]) --> 声明allow_slugs{声明allow_slugs?}
  声明allow_slugs --是--> slug匹配allow_slugs{slug匹配allow_slugs?}
  声明allow_slugs --否--> 通过
  slug匹配allow_slugs --是--> 通过
  slug匹配allow_slugs --否--> 不通过
  
  
    flowchart LR
  strat([branch检查]) --> 声明allow_branches{声明allow_branches?}
  声明allow_branches --是--> branch匹配allow_branches{branch匹配allow_branches?}
  声明allow_branches --否--> 通过
  branch匹配allow_branches --是--> 通过
  branch匹配allow_branches --否--> 不通过
  

allow_branches 检查的 branch 同 CNB_BRANCH

  
    flowchart LR
  strat([event检查]) --> 声明allow_events{声明allow_events?}
  声明allow_events --是--> event匹配allow_events{event匹配allow_events?}
  声明allow_events --否--> 通过
  event匹配allow_events --是--> 通过
  event匹配allow_events --否--> 不通过
  
  
    flowchart LR
  strat([image检查]) --> 声明allow_images{声明allow_images?}
  声明allow_images --是--> image匹配allow_images{image匹配allow_images?}
  声明allow_images --否--> 通过
  image匹配allow_images --是--> 通过
  image匹配allow_images --否--> 不通过
  

image 检查说明:

示例

流水线密钥文件引用

 1# 密钥仓库中的配置文件 secret.yml
 2allow_slugs:
 3  - "p1/**"
 4allow_events:
 5  - push
 6allow_branches:
 7  - main
 8# dockerhub 用户名和密码
 9DOCKER_USER: docker-user
10DOCKER_PWD: docker-pwd
 1# 流水线配置文件 .cnb.yml
 2main:
 3  push:
 4    - services:
 5        - docker
 6      imports: https://cnb.cool/<your-repo-slug>/-/blob/main/xxx/secret.yml
 7      stages:
 8        - name: docker login
 9          script: |
10            # 登录到 dockerhub
11            docker login -u ${DOCKER_USER} -p "${DOCKER_PWD}"
12            # docker build xxx
13            # docker push xxx

流水线引用其他密钥仓库中的配置文件 secret.yml,但流水线触发者无该文件读权限。

被引用文件 secret.yml 声明了 allow_slugsallow_eventsallow_branches

p1 组织下的仓库的分支 main 触发了 push 事件,那么流水线就能引用该密钥文件,使用其中的敏感信息。

这样限制了只有密钥仓库的负责人、管理员才能查看、修改 secret.yml 中的敏感内容,同时又能被符合条件的流水线引用。

插件任务参数引用

1# 密钥仓库中的配置文件 image-settings.yml
2allow_images:
3  - "registry.com/image1/**"
4allow_slugs:
5  - "p1/**"
6arg1: arg1
7arg2: arg2
1# 流水线配置文件 .cnb.yml 配置插件任务
2name: image job
3image: registry.com/image1/print:latest
4settingsFrom:
5  - https://cnb.cool/<your-repo-slug>/-/blob/main/xxx/image-settings.yml

镜像如果是第三方制作的,可能存在泄漏信息的风险,可以通过 allow_images 限制该配置文件只能被确定安全性的特定镜像名的插件任务使用。

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

allow_slugs 指定了只能被组织 p1 下的仓库流水线引用,进一步控制配置文件的使用范围。