应为ci/cd机器人配置最小化sudo权限:仅允许deployer用户以www-data身份在指定路径执行预置、不可篡改的部署脚本,并辅以脚本内环境校验、审计日志与目录隔离。

为 CI/CD 自动部署机器人(如 Jenkins Agent、GitLab Runner 所用用户)配置受限的 sudo 权限,核心是:**只允许它以指定身份,在指定目录下,执行指定脚本(且脚本本身不可被篡改)**。这不是给“用户宽泛提权”,而是构建一条受控、可审计、防逃逸的执行通道。
一、创建专用运行用户与隔离目录
避免复用 root 或普通运维账号,从源头隔离风险:
- 新建无登录能力的系统用户:
sudo useradd -r -s /sbin/nologin deployer - 创建专属部署目录并设属主:
sudo mkdir -p /opt/deploy/scripts,然后sudo chown deployer:deployer /opt/deploy/scripts - 脚本必须由运维人员预置、签名或通过 CI 流水线安全分发;禁止该用户对脚本目录有写权限(
chmod 755 /opt/deploy/scripts,不开放 group/o 写位)
二、用 sudoers.d 配置白名单脚本权限
绝不编辑 /etc/sudoers 主文件,使用独立规则文件:
- 运行
sudo visudo -f /etc/sudoers.d/cicd-deploy - 添加如下内容(路径、参数、目标用户全部显式固定):
Cmnd_Alias DEPLOY_SCRIPTS = /opt/deploy/scripts/deploy.sh, /opt/deploy/scripts/rollback.shdeployer ALL=(www-data) NOPASSWD: DEPLOY_SCRIPTS - 关键约束说明:
• 脚本路径必须是绝对路径,且不能含通配符或变量
•(www-data)表示脚本将以 www-data 身份运行(适配 Web 服务属主),不是 root
• 不加! /bin/sh等逃逸入口,也不允许/bin/bash -c类调用
三、脚本内强制校验执行上下文
仅靠 sudo 规则不够,脚本自身需防御性编程:
- 开头加入环境检查:
if [ "$(id -un)" != "deployer" ] || [ "$EUID" -ne "0" ]; then echo "ERROR: Must be run via sudo by deployer"; exit 1; fi - 校验当前工作目录是否在预期路径:
[[ "$PWD" == "/opt/deploy" ]] || { echo "ERROR: Run from /opt/deploy only"; exit 1; } - 若脚本需操作应用目录(如
/var/www/myapp),应提前用setfacl授予deployer有限读写权,而非依赖 sudo 提权去改所有者
四、启用审计与限制非交互式调用
确保每次执行都可追溯,且无法绕过 CI 环境:
- 在
/etc/sudoers顶部统一开启审计:Defaults logfile="/var/log/sudo-cicd.log", log_input, log_output, requiretty -
requiretty可防 SSH 后台调用,但 CI 工具常依赖伪终端——若 Jenkins/GitLab Runner 报错 “no tty present”,可在该条规则后追加:deployer ALL=(www-data) NOPASSWD: SETENV: DEPLOY_SCRIPTS,并配合Defaults:deployer !requiretty单独豁免 - 验证方式:
sudo -u deployer -i sudo -l -U deployer查看生效规则;再以 deployer 身份实测:sudo -u www-data /opt/deploy/scripts/deploy.sh --dry-run











