2、GitLab CI模板目录结构基础

目录结构是模板权限边界的第一道防线。在GitLab CI中,模板的存放位置决定了谁能读取、谁能引用、谁能覆盖。理解默认路径、自定义配置和层级规范,是后续进行权限评审的前提。

2.1 默认模板目录位置

GitLab官方将内置CI模板统一存放在安装目录下的固定路径:

/opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/ci/templates/

该目录包含所有官方维护的模板文件(如 Auto-DevOps.gitlab-ci.yml、Security/SAST.gitlab-ci.yml 等),由GitLab版本发布时打包,普通用户无权修改。下表列出该目录的核心特征:

属性 说明
物理路径 lib/gitlab/ci/templates/(相对于Rails应用根目录)
访问方式 通过 include:template 关键字引用,如 template: Jobs/Test.gitlab-ci.yml
权限模型 只读,仅GitLab系统管理员可通过升级包更新
可见范围 全局可见,所有项目均可引用
评审要点:默认目录中的模板是“可信基础镜像”。评审时需确认是否有非官方文件混入该目录,以及是否有用户通过include:template意外引用了已被废弃或存在漏洞的旧版本模板。

2.2 自定义模板目录配置

企业通常需要维护私有模板库。GitLab支持通过项目级设置或实例级配置来定义自定义模板目录。常见方式有两种:

  • 项目内模板目录:在项目仓库根目录下创建 .gitlab/ci/templates/ 文件夹,该目录下的 .gitlab-ci.yml 文件可通过相对路径 include:local 引用。
  • 实例级自定义模板目录:通过 gitlab.rb 配置文件中的 gitlab_ci['custom_template_dirs'] 参数指定一个或多个额外目录。
# /etc/gitlab/gitlab.rb 配置示例
gitlab_ci['custom_template_dirs'] = [
  "/var/opt/gitlab/custom-ci-templates",
  "/data/shared/security-templates"
]

配置生效后,这些目录下的模板文件可通过 include:template 以 Custom/ 前缀引用。下表对比两种自定义方式的差异:

维度 项目内模板目录 实例级自定义模板目录
作用域 仅限单个项目 整个GitLab实例
管理方式 开发者通过Git提交管理 系统管理员通过文件系统管理
引用语法 include:local include:template + Custom/ 前缀
权限风险 低(受项目权限控制) 高(需确保目录权限最小化)
边界风险:实例级自定义模板目录如果权限配置不当(如 777 或属主为非git用户),攻击者可能通过写入恶意模板实现横向移动。评审时必须检查 custom_template_dirs 中每个目录的POSIX权限和SELinux上下文。

2.3 目录层级规范

GitLab CI模板目录遵循一套清晰的层级约定,用于组织不同类别的模板。官方模板的层级结构如下:

templates/
├── Auto-DevOps.gitlab-ci.yml
├── Jobs/
│   ├── Build.gitlab-ci.yml
│   ├── Test.gitlab-ci.yml
│   └── Deploy.gitlab-ci.yml
├── Security/
│   ├── SAST.gitlab-ci.yml
│   ├── Secret-Detection.gitlab-ci.yml
│   └── DAST.gitlab-ci.yml
├── Verify/
│   ├── Browser-Performance.gitlab-ci.yml
│   └── Code-Quality.gitlab-ci.yml
└── Workflows/
    ├── Merge-Request.gitlab-ci.yml
    └── Branch-Pipelines.gitlab-ci.yml

层级规范的核心原则包括:

  • 一级目录:按功能领域命名(如 Security/、Jobs/),首字母大写,使用单数形式。
  • 模板文件:使用帕斯卡命名法(PascalCase),以 .gitlab-ci.yml 为后缀。
  • 禁止嵌套过深:官方规范限制最多两级子目录,避免引用路径过长导致维护困难。
  • 索引文件:每个目录下可包含 index.md 描述该分类的模板清单和使用说明。
评审检查项:在自定义模板目录中,是否遵循了相同的层级规范?是否存在目录名与文件名冲突?是否有模板文件位于非标准位置导致 include:template 解析失败?层级混乱会直接导致权限覆盖逻辑不可预测。
GitLab CI模板目录层级与权限边界 GitLab CI模板目录层级与权限边界 默认模板目录(全局只读) Auto-DevOps.gitlab-ci.yml Jobs/ Security/ Verify/ Workflows/ 权限:只读 · 仅系统管理员可写 路径:/opt/gitlab/.../templates/ 自定义模板目录(实例级可写) Custom/Deploy-Templates/ Custom/Security/ Custom/Compliance/ Custom/Monitoring/ 权限:可读写 · 需严格ACL控制 路径:/var/opt/gitlab/custom-ci-templates/ 配置:gitlab_ci['custom_template_dirs'] include:template 评审重点:检查自定义目录的POSIX权限、属主、SELinux标签,防止未授权写入

2.4 目录结构与权限的关联

目录层级直接影响模板的引用路径和权限继承关系。在权限评审中,需要关注以下映射:

  • 路径即身份:模板的引用路径(如 Security/SAST.gitlab-ci.yml)决定了它在权限模型中的“身份标识”。
  • 目录权限继承:文件系统层面,子目录默认继承父目录的权限。如果自定义模板目录的父目录权限过宽,所有子模板都会暴露。
  • 覆盖优先级:当默认目录和自定义目录中存在同名模板时,自定义目录中的版本会覆盖默认版本。评审时需确认是否存在非预期的覆盖。
最佳实践:建议为自定义模板目录单独创建系统用户(如 gitlab-ci-templates),并设置 750 权限(属主读写执行、属组读执行、其他无权限)。同时启用GitLab审计日志,记录所有模板文件的变更操作。