提权解决什么问题
Ansible 默认用连接用户(通常是一个普通运维账号)的身份在目标机上执行任务,装包、写系统配置、重启服务这些动作都需要管理员权限,于是有了提权机制:连接仍用普通账号,执行动作前先换成 root 等特权身份。三件套是 become 开开关、become_user 定目标身份、become_method 选切换方式(sudo/su/doas/runas 等)。这套机制可以只加在某个任务上,也可以放在 play、block、role 上整段生效。
基本信息
| 开关与目标 | become、become_user(默认 root) |
|---|---|
| 切换方式 | become_method:sudo 为 Linux 默认,另有 su、doas;Windows 用 runas |
| 生效层级 | ansible.cfg 全局、play、role、block、task 逐级可覆盖 |
| 按主机定制 | 清单变量 ansible_become、ansible_become_user、ansible_become_method |
| 密码来源 | 交互式 --ask-become-pass,或按主机变量指定 |
| 依赖条件 | 目标机必须真的装了所选方式(如没有 sudo 就不能用 sudo) |
典型使用场景
- 批量装机基线:apt/yum 装包与写 /etc 下的配置,全程需要 root
- 服务编排:重启 systemd 单元、改限流参数,普通账号无权限
- 普通账号加密钥登录、禁止口令登录这类安全加固动作
- 多账号分工:连接用审计账号,业务动作切到应用专用账号而非 root
- Windows 主机:改用 runas 提权,凭据与 SSH 场景完全不同
- 网络设备:命令行里进入特权视图(enable)才能下发配置
三种粒度的写法
三种粒度的写法
# 全局默认:ansible.cfg
# [privilege_escalation]
# become = True
# become_method = sudo
# become_user = root
- hosts: web
become: true # play 级:整段提权
tasks:
- name: 装 nginx
ansible.builtin.package:
name: nginx
state: present
- name: 只查版本,不提权
ansible.builtin.command: nginx -v
become: false # 任务级覆盖,保持普通身份
- name: 以应用账号写业务目录
ansible.builtin.copy:
src: app.conf
dest: /opt/app/app.conf
become_user: appsvc # 换成非 root 的特权身份切换方式怎么选
| 方式 | 适用场景 | 注意点 |
|---|---|---|
| sudo | Linux/Unix 主流发行版默认选择 | 需要目标账号在 sudoers 中有权限,可要求免密或输入密码 |
| su | 目标机没有 sudo 但有 su、且有 root 口令 | 需要提供 root 口令,审计上不如 sudo 精细 |
| doas | BSD 系与部分精简发行版 | 依赖 /etc/doas.conf 放行 |
| runas | Windows 主机(配合 WinRM/PSRP 连接) | 与 Linux 的 sudo 无对应关系,凭据走 WinRM |
| enable | 网络设备的特权视图 | 由网络连接插件处理,与 sudo 机制不是一回事 |
提权是“换执行身份”,不是“换连接身份”:SSH 仍然用原来的运维账号建立,所有提权动作都会在该账号的 sudo 审计日志里留痕(RHEL 系通常是 /var/log/secure,Debian 系是 /var/log/auth.log),这正好是事后追责的依据。
提权口令不要写进 playbook、清单或仓库文件。需要非交互执行的场合,用 vault 加密的变量文件存放,或在目标机 sudoers 中对该运维账号做最小范围的免密放行(限定具体命令,不要整条 ALL)。
排查思路
提权失败通常只有三类原因:目标账号没有提权权限、所选方式在目标机上不存在、密码与提示符不匹配。先手工在被管机上用同一账号执行一次对应命令(例如 sudo -n id 或 sudo -l)确认权限与免密状态,再看 ansible 返回的报错文本;如果返回停在等待口令,就是缺密码或方式选错。