跳到主要内容

密钥仓库:把密码从 YAML 里赶出去

.cnb.yml 是进版本库的,写死密码等于把密码公开。CNB 的答案是密钥仓库。

一、它特殊在哪​

密钥仓库是一个专用仓库类型,和普通仓库相比少了两个能力、多了两个:

能力普通仓库密钥仓库
Clone 到本地✅❌ 禁止
本地推送✅❌ 禁止
Web 界面编辑✅✅ 只能这样改
被流水线引用✅✅ 核心用途

也就是说:数据只进不出,所有变更都在受审计的 Web 界面完成。

另外两个安全细节:

  • 所有页面带动态水印(当前用户名),截图外泄可溯源
  • 完整的审计日志:记录每个文件何时被哪条流水线引用

二、建一个​

登录后进入 https://cnb.cool/new/repos,仓库类型选 密钥仓库,填名字即可。

建议按环境或项目拆文件,别塞一个大文件:

密钥仓库/
├── env.prod.yml # 生产
├── env.staging.yml # 预发布
└── env.dev.yml # 开发

格式就一行一个键值:

DOCKER_USER: "prod_username"
DOCKER_TOKEN: "prod_token_123456"
DOCKER_REGISTRY: "registry.prod.com"

三、四种把文件引进来​

方式配置项用途
环境变量引用imports把 yml 文件变成环境变量
流水线模板引用include复用整段流水线配置
内置任务参数引用optionsFrom内置任务的 options 从文件读
插件任务参数引用settingsFrom插件任务的 settings 从文件读

后三种支持环境变量拼接路径:

.cnb.yml
main:
push:
- env:
SECRET_BASE: https://cnb.cool/my/secrets/-/blob/main
imports:
- ${SECRET_BASE}/env.prod.yml
stages:
- name: 用密钥
script: echo "user=$DOCKER_USER"

optionsFrom / settingsFrom 还支持本地路径——甚至可以是流水线上刚写出来的文件,不用提交进仓库。

四、谁能引用:allow_* 规则​

默认规则:只有密钥仓库的管理员和负责人触发的流水线才有权引用。

想让更广的人用,必须在密钥文件里声明四个字段:

allow_slugs: "group/project,group/another-*" # 哪些仓库可以引用
allow_events: # 哪些事件可以引用
- push
- tag_push
- "tag_deploy.*"
allow_branches: # 哪些分支可以引用
- main
- "feature/*"
allow_images: "cnbcool/ssh" # 哪些镜像插件可以引用

:::warning 一配 allow_* 就换规则 只要你声明了任一 allow_*,系统就完全忽略触发者角色,只按规则校验,且所有规则都要通过。 好处是可预期,坏处是配漏一条就全拒。 :::

glob 记法:* 不跨 /,** 跨 /。多级组织路径必须用 **。

五、四条最佳实践​

1. 最小权限

  • allow_events 只放 tag_push / tag_deploy.*,别放 push——每次推代码都摸密钥没意义
  • allow_branches 只放 main 等保护分支

2. 环境分离 生产、预发、开发各用各的文件,别一个文件塞三套。

3. 收敛配置入口 把带 imports 的流水线放进一个权限受控的仓库,通过 include 给其他仓库用。改的人少,风险点就少。

4. 定期轮换 + 审计 换密钥只需在 Web 界面改文件,所有引用的流水线自动拿到新值。定期清掉不用的引用规则。

六、密钥进来了也可能泄漏​

密钥仓库本身安全,但注入到流水线之后:

  • 脚本里 echo 一下就进了日志
  • 第三方命令可能把环境变量打进错误输出

所以:不要在脚本里打印任何密钥变量;调试时用 echo "${TOKEN:0:4}***" 这种脱敏写法。