Ansible 执行特权命令时,最安全的方式是在目标主机配置 sudoers 允许特定用户免密执行,而不是在 Ansible 调用时传递 sudo 密码。适用场景为自动化运维环境,风险边界在于必须严格保护 Ansible 控制用户的 SSH 私钥权限。
先说结论:通过 sudoers 配置 NOPASSWD 规则替代密码传递,能消除密码在传输和日志中的泄露风险。
- 先判断:确认 Ansible 控制用户是否已通过 SSH 密钥认证登录。
- 优先做:在目标主机 /etc/sudoers.d/ 目录下为 Ansible 用户添加免密规则。
- 再验证:使用 ansible -m command -a "whoami" `--become` 测试提权是否无需密码。
命令速用版
直接在目标主机编辑 sudoers 配置文件,添加免密规则。
# 进入编辑模式,切勿直接 vim 编辑 sudoers
visudo -f /etc/sudoers.d/ansible_user
# 添加以下内容,将 ansible 替换为实际登录用户名
ansible ALL=(ALL) NOPASSWD: ALL
# 保存退出后,在控制机测试
ansible all -m command -a "whoami" `--become`为什么会这样
传递 sudo 密码会在进程列表、日志文件或 Ansible Vault 中留下明文或加密凭据,增加泄露面。
Ansible 默认通过 SSH 连接目标主机,若每次提权都要求输入 sudo 密码,用户往往倾向于将密码存入 vault 文件或通过命令行参数传递。一旦控制机被入侵或日志被窃取,攻击者可获取 sudo 密码。配置 sudoers 免密后,权限验证依赖 SSH 私钥,只要私钥保管得当,自动化流程无需接触明文密码。
分步处理
按顺序完成用户创建、密钥分发、sudoers 配置和权限回收。
步骤 1:准备专用账户
不要在目标主机使用 root 直接登录,创建专用运维账户。
# 在目标主机执行
useradd -m -s /bin/bash ansible
mkdir -p /home/ansible/.ssh
chmod 700 /home/ansible/.ssh步骤 2:分发 SSH 公钥
将控制机的公钥写入目标主机 authorized_keys。
# 在控制机执行
ssh-copy-id ansible@target_host步骤 3:配置 sudoers 免密
使用 visudo 命令编辑,确保语法正确。
# 在目标主机执行
visudo -f /etc/sudoers.d/ansible
# 写入:ansible ALL=(ALL) NOPASSWD: ALL
# 确保文件权限为 440
chmod 440 /etc/sudoers.d/ansible步骤 4:限制命令范围(可选)
若安全要求高,仅允许特定命令免密。
# 仅允许重启 nginx 和查看日志
ansible ALL=(ALL) NOPASSWD: /usr/sbin/service nginx restart, /usr/bin/tail -f /var/log/*怎么验证是否生效
通过 Ansible 命令检查提权后的用户身份和是否需要密码交互。
验证命令:
ansible all -i target_host, -m command -a "whoami" `--become` -u ansible预期结果:
- 输出包含 "root",说明提权成功。
- 命令执行过程中没有提示输入 SSH 密码或 sudo 密码。
- 若使用 -vvv 参数,日志中不应出现 password 相关字段。
检查 sudoers 语法:
sudo visudo -c -f /etc/sudoers.d/ansible
# 输出 parsed OK 表示配置无误常见坑
配置 sudoers 时容易因语法错误或权限问题导致无法提权或安全风险。
- 文件权限错误:/etc/sudoers.d/ 下的文件权限必须是 440 或 400,属主为 root,否则 sudo 会拒绝读取。
- 命令路径不全:限制命令时必须写绝对路径,例如 /usr/bin/systemctl 而不是 systemctl,否则规则不生效。
- 私钥泄露风险:开启 NOPASSWD 后,SSH 私钥等同于 root 权限,必须严格控制控制机私钥的访问权限(chmod 600)。
- Defaults 要求 tty:部分系统默认配置 requiretty,会导致 Ansible 后台执行失败,需在 sudoers 中添加 Defaults:ansible !requiretty。
常见问题
必须使用密码时如何安全传递?
若合规要求必须使用密码,建议使用 Ansible Vault 加密密码文件,并通过 `--ask-become-pass` 手动输入。
配置生效后还能审计操作吗?
可以,sudo 默认会将执行命令记录到 /var/log/secure 或 /var/log/auth.log,配置 NOPASSWD 不影响日志审计。
如何回收权限?
删除 /etc/sudoers.d/ 下对应用户配置文件,或在该文件中注释掉相关规则,无需重启服务立即生效。
参考来源
- Ansible Official Documentation, "Become (Privilege Escalation)", https://docs.ansible.com/ansible/latest/playbook_guide/playbook_privilege_escalation.html
- Linux Man Pages, "sudoers", https://www.man7.org/linux/man-pages/man5/sudoers.5.html