直接创建无登录能力的专用系统用户script-runner,通过sudoers白名单精确授权其执行特定命令,禁用shell逃逸,并在cron、Keepalived或systemd中以该用户身份运行脚本,确保最小权限原则落地。

直接给脚本配一个“只干一件事”的专用身份,比硬凑 root 权限安全得多,也更稳定。
创建真·受限系统用户
别用普通用户或 root 降权,要从零建一个无登录能力、无交互 shell 的系统账户:
- 运行
sudo useradd -r -s /usr/sbin/nologin -d /var/empty script-runner,创建名为script-runner的系统用户 - 立即锁定密码:
sudo passwd -l script-runner,防止任何密码登录可能 - 不分配家目录、不生成 shell 环境、不设主组——它只存在,只为脚本服务
精准授权:命令白名单 + 路径锁定
脚本能做什么,必须写死在 sudoers 里,不能靠 PATH 或通配符糊弄:
- 用
which systemctl或command -v pg_dump确认二进制绝对路径 - 在
/etc/sudoers.d/script-runner中写明权限,例如:script-runner ALL=(postgres) NOPASSWD: /usr/bin/pg_dump -h /var/run/postgresql -U backupdb myapp - 禁止 shell 逃逸:
Defaults:script-runner !shell_noop和script-runner ALL=(ALL) !/bin/sh, !/bin/bash, !/usr/bin/su - 设文件权限:
sudo chmod 440 /etc/sudoers.d/script-runner
脚本自身适配低权上下文
即使身份配对了,脚本若写法粗放,仍会失败或越权:
- 所有命令前加
sudo -n -u postgres(或目标用户),显式切换执行主体,不依赖环境变量 - 避免写入
/etc、/var/log等敏感路径;改用/var/lib/script-runner/或用户 home 下可写子目录 - 检查脚本中是否调用
sudo、su、pkexec——这些一律删掉,Keepalived、systemd 或 cron 都不提供 sudoers 上下文 - 若需访问数据库 socket 或 API,用
sudo usermod -aG mysql script-runner加组,而非 chmod 755 socket
集成到执行环境并验证
配置完不是终点,得让系统真正按低权方式跑起来,并确认它没偷偷提权:
- Cron 任务改用
sudo -u script-runner crontab -e编辑,而非 root crontab - Keepalived vrrp_script 中启用
script_user script-runner(需 Keepalived ≥ 2.0.20) - systemd 服务单元加
[Service] User=script-runner,并确保/var/lib/script-runner/所有者为该用户 - 验证命令可用性:
sudo -lU script-runner输出应仅含你授权的几行;测试越权:sudo -u script-runner /bin/bash必须被拒绝

















