---
url: /zh/build/file-reference.md
description: 说明流水线配置中的四种文件引用方式（include、imports、optionsFrom、settingsFrom）及其权限控制机制。
---
## 背景

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

被引用的文件可能含有敏感信息，因此需要对文件引用做权限检查，避免敏感信息泄露。

## 引用方式

CNB 支持以下四种配置文件引用方式：

* 流水线模板引用：[include](./grammar.md#include)
* 环境变量引用：[imports](./grammar.md#pipeline-imports)
* 内置任务参数引用：[optionsFrom](./grammar.md#job-optionsfrom)
* 插件任务参数引用：[settingsFrom](./grammar.md#job-settingsfrom)

**注意：**

`imports`、`optionsFrom` 和 `settingsFrom` 声明的文件路径支持使用环境变量。

```yaml title=".cnb.yml"
main:
  push:
    - env:
        CNB_CONFIG_URL: https://cnbprod.alpha.qq.com/<your-repo-slug>/-/blob/main/xxx
        CNB_CONFIG_FILE: account.yml
        CNB_ENV_FILE_URL: https://cnbprod.alpha.qq.com/<your-repo-slug>/-/blob/main/xxx
      imports:
        - https://cnbprod.alpha.qq.com/<your-repo-slug>/-/blob/main/xxx/env1.yml
        - ${CNB_ENV_FILE_URL}/env2.yml
      stages:
        - name: echo
          script: echo 1
```

`optionsFrom` 和 `settingsFrom` 同样支持环境变量：

```yaml title=".cnb.yml"
main:
  push:
    - env:
        CNB_CONFIG_URL: https://cnbprod.alpha.qq.com/<your-repo-slug>/-/blob/main/xxx
        CNB_CONFIG_FILE: account.yml
      stages:
        - name: 内置任务
          type: some-type
          optionsFrom:
            - ${CNB_CONFIG_URL}/${CNB_CONFIG_FILE}
        - name: 插件任务
          image: some-image
          settingsFrom:
            - ${CNB_CONFIG_URL}/${CNB_CONFIG_FILE}
```

`optionsFrom` 和 `settingsFrom` 也支持读取本地文件。
即便仓库中没有 `./path/to/file`，也可以在流水线中写入该文件，供流水线执行时加载：

```yaml title=".cnb.yml"
# 在 stages 中将上面的远程路径改成本地路径即可，其余保持不变
main:
  push:
    - stages:
        - name: 写入配置
          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
```

## 权限检查

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

对于私有且非同源仓库的配置文件，可通过
`allow_slugs`、`allow_events`、`allow_branches`、`allow_images`
四个字段控制可被访问范围。四个字段均为 `glob` 模式的字符串
（多个表达式以 `,` 或 `|` 分隔）或字符串数组。

::: tip glob 匹配规则

* `*` 匹配任意字符，但**不匹配** `/`。例如：`my-group/*` 可匹配 `my-group/repo`，但不能匹配 `my-group/sub/repo`。
* `**` 匹配任意字符，**包括** `/`。例如：`my-group/**` 可匹配 `my-group/repo` 和 `my-group/sub/repo`。

如果需要匹配含 `/` 的路径（如多级组织下的仓库），请使用 `**`。
:::

如：

```yaml
allow_slugs: "group/project,some/another-project/feature-*"
allow_events:
  - push
  - tag_push
  - "tag_deploy.*"
allow_images: "cnbcool/ssh"
allow_branches:
  - main
  - "feature/*"
```

多个表达式推荐使用字符串数组声明，可读性更强。
若配置文件为文本格式不支持声明数组，可用字符串格式。

若未声明上述四个字段，则会检查流水线触发者是否为配置文件所属仓库的 `开发者` 或以上角色，有则可访问，否则不可访问。

其中：

* `allow_slugs`：声明允许哪些仓库的流水线读取当前文件。
* `allow_events`：声明允许哪些事件下流水线可以读取当前文件，
  可配置的事件名参考 [触发事件](./trigger-rule.md#trigger-event)。
* `allow_branches`：声明允许哪些分支下流水线可以读取当前文件。
* `allow_images`：声明允许哪些镜像插件可以读取当前文件。

CNB 流水线加载目标文件的权限检查流程如下：

```mermaid
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检查通过 --否--> 不可访问
```

流程图说明：

* 同源仓库：流水线和目标文件属于同一个仓库。
* allow检查：声明的 allow 字段依次检查，每个都通过了才算通过。
* 文件读权限：参见 [角色权限](../guide/role-permissions.md)

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

allow 必要性检查说明：

* [不可信事件](./trigger-rule.md#untrusted-events) 中流水线配置或触发者不可控，
  配置文件必须声明 `allow_events` 才能被不可信事件流水线引用
* 流水线可使用第三方插件，配置文件必须声明 `allow_images` 才能被插件任务引用

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

```mermaid
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](./build-in-env.md#CNB_BRANCH)。

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

```mermaid
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 检查说明：

* 镜像任务参数可通过 `settingsFrom` 设置，也可通过 `imports` 引入后以环境变量方式设置，
  两种方式均视为插件任务引用文件
* 镜像名不带标签或带 `:latest` 时，会以 `镜像名` 和 `镜像名:latest` 匹配 `allow_images`，匹配一个即可
* 非插件任务的 image 为空字符串，无法匹配任何 glob 表达式；
  配置文件声明了 `allow_images` 将不能被非插件任务引用
* **Job 同时设置 image 和 script 属于以 image 作为执行环境的脚本任务**
* 语法上流水线可声明 image 作为构建环境，但不属于插件任务；
  配置文件声明了 `allow_images` 不能在流水线级别被引用

## 示例

### 流水线密钥文件引用

```yaml
# 密钥仓库中的配置文件 secret.yml
allow_slugs: "p1/**"
allow_events: push
allow_branches: main
DOCKER_USER: docker-user
DOCKER_PWD: docker-pwd
```

```yaml title=".cnb.yml"
main:
  push:
    - services:
        - docker
      imports: https://cnbprod.alpha.qq.com/<your-repo-slug>/-/blob/main/xxx/secret.yml
      stages:
        - name: docker login
          script: |
            docker login -u ${DOCKER_USER} -p "${DOCKER_PWD}"
            # docker build xxx
            # docker push xxx
```

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

`secret.yml` 声明了 `allow_slugs`、`allow_events` 和 `allow_branches`：
若 `p1` 组织下的仓库在 `main` 分支触发 `push` 事件，流水线即可引用该密钥文件。

这样只有密钥仓库的负责人或管理员能查看和修改其中的敏感内容，
同时又能被符合条件的流水线引用。

### 插件任务参数引用

```yaml
# 密钥仓库中的配置文件 image-settings.yml
allow_images: "registry.com/image1/**"
allow_slugs: "p1/**"
arg1: arg1
arg2: arg2
```

```yaml title=".cnb.yml"
main:
  push:
    - stages:
        - name: image job
          image: registry.com/image1/print:latest
          settingsFrom:
            - https://cnbprod.alpha.qq.com/<your-repo-slug>/-/blob/main/xxx/image-settings.yml
```

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

`image: registry.com/image1/print:latest` 符合 `registry.com/image1/**`，image 检查通过。
`allow_slugs` 进一步限制只能被组织 `p1` 下的仓库流水线引用。
