CI/CD流水线需严格遵循权限最小化原则:各环节仅拥有必要权限,部署账号须专用且无交互能力,禁用root/sudo-all;命令白名单精确到参数级,构建与部署环境分离,文件权限按角色收敛,进程全程降权并限制系统能力边界。

CI/CD 流水线不是特权通道,而是需要被严格约束的自动化执行环境。权限最小化在 CI/CD 中的核心是:流水线中每个环节(代码拉取、构建、测试、部署)只拥有完成该环节所必需的权限,不继承、不扩散、不越界。
部署账号必须专用且无交互能力
不要复用运维或开发人员的个人账号,也不要让 CI 工具(如 Jenkins、GitLab Runner)以 root 或 sudo-all 用户运行。应创建仅服务于部署任务的系统用户:
- 使用
useradd -r -s /usr/sbin/nologin deploy创建无登录 Shell 的专用账户 - 禁用密码认证:
passwd -l deploy,仅允许通过 SSH 密钥或 token 认证 - 该账户主目录设为
/opt/deploy,不挂载家目录,不分配 shell 环境变量 - 确保其 UID/GID 不与任何服务账户冲突(如避免与 www-data、nginx 同组)
部署脚本和命令白名单需精确到参数级
CI 执行部署时调用的命令,不能简单授权 /usr/bin/systemctl 全量权限,而应限定具体动作和目标:
- 在
/etc/sudoers.d/deploy中写死白名单,例如:deploy ALL=(www-data) NOPASSWD: /usr/bin/systemctl restart myapp.service - 禁止通配符、shell 转义和任意参数:
✅ 允许/bin/cp /tmp/myapp.tar.gz /var/www/app/
❌ 禁止/bin/cp /tmp/* /var/www/app/或/bin/bash - 对 rsync、tar 等工具,明确指定源路径和目标路径,避免路径遍历或递归覆盖
- 启用
Defaults env_reset, requiretty防止环境变量注入和伪终端绕过
构建与部署环境分离,文件权限按角色收敛
CI 构建产物(如二进制、包、静态资源)不应由构建用户直接写入生产路径,而应经权限校验后移交:
- 构建阶段使用独立用户(如
builder),输出物存于临时安全目录(如/tmp/build-XXXX),权限设为700,属主为 builder - 部署阶段由
deploy用户读取并验证签名/哈希,再复制到目标位置;目标目录(如/var/www/app)属主应为www-data:deploy,权限为750 - 敏感文件(如配置模板、env 文件)不在 Git 中明文存储,通过密钥管理服务注入,落地后立即设为
600,属主为服务运行用户(如www-data) - 禁止 CI 进程直接修改
/etc/下任何文件,配置变更须走配置中心或声明式模板渲染
流水线进程全程降权,限制系统能力边界
无论是自建 Runner 还是托管服务,运行 CI 作业的进程本身不能拥有冗余权限:
- GitLab Runner 启动时指定
--user=deploy,或 systemd unit 中设置User=deploy、NoNewPrivileges=yes - Docker-in-Docker 场景下,禁用
--privileged,改用--cap-drop=ALL --cap-add=NET_BIND_SERVICE等按需添加 - 限制文件系统访问:
ProtectSystem=strict、ProtectHome=read-only、RestrictAddressFamilies=AF_UNIX AF_INET - 禁用内核模块加载、ptrace 调试、信号转发等高危 capability,尤其避免
CAP_SYS_ADMIN


















