1
2
3
4
5
作者:李晓辉

微信联系:Lxh_Chat

联系邮箱: 939958092@qq.com

在 Ansible 任务中,特权提升其实就是让你以管理员权限来执行一些需要更高权限的操作,就像用 sudo 提升权限一样。这个功能特别有用,尤其是在配置服务器、部署应用或者管理基础设施时,它让你能在不每次输入密码的情况下,顺利完成高权限的操作。

Ansible 提供了几个相关的选项,比如 becomebecome_userbecome_method,让你可以灵活地在不同的权限级别间切换。只要在 Playbook 或任务中启用 become,就能轻松执行那些需要管理员权限的命令,保持自动化流程的顺畅和一致,既安全又高效!

在ansible.cfg中定义特权升级

1
2
3
4
5
[privilege_escalation]
become=true
become_method=sudo
become_user=root
become_ask_pass=false

具体意思是:

  • become=true

    • 启用了权限提升功能(Privilege Escalation)。

    • 这意味着 Ansible 在执行任务时会尝试以更高权限(例如管理员权限)运行命令。

  • become_method=sudo

    • 指定了使用 sudo 作为权限提升的方法。

    • sudo 是一个常见的工具,允许用户以特定权限(通常是 root)执行命令。

  • become_user=root

    • 定义了提升后的目标用户,这里是 root

    • 任务执行时,Ansible 会切换到 root 用户执行。

  • become_ask_pass=false

    • 指定了不提示输入密码。

    • 这通常意味着 sudo 已被配置为无需密码使用(例如通过 sudo 配置文件设置了 NOPASSWD 选项)。

在 Play 中定义特权升级

在play上定义become是true还是false,如果没有定义,就使用ansible.cfg中提供的默认值

1
2
3
4
5
---
- name: Become the user "manager"
hosts: webservers
become: true
tasks:

任务中的特权升级

在task中也可以定义become为true或false

1
2
3
4
5
6
7
8
9
10
---
- name: Play with two tasks, one uses privilege escalation
hosts: all
become: false
tasks:
- name: This task needs privileges
ansible.builtin.yum:
name: perl
state: installed
become: true

上面这个有点冲突,在play上我们定义了become: false,而模块上定义了become: true,那到底是什么?

分析:

  1. Play 层级的 become: false:

    • 在顶层的 Play 中设置了 become: false,这意味着默认情况下,此 Play 中的所有任务都不会启用特权提升。
  2. 任务级别的 become: true:

    • 对于某些特定任务(如安装 perl 的任务),显式启用了 become: true

    • 由于任务级别的 become 优先级高于 Play 层级的设置,因此这个任务会启用特权提升。

最终的 become 值:

  • Play: become: false(整个 Play 默认不使用特权提升)。

  • Task: become: true(具体任务级别设置的特权提升覆盖了 Play 层的默认值)。

因此,这段 Playbook 中:

  • 大部分任务默认不会启用特权提升

  • 安装 perl 的任务会使用特权提升来执行,例如通过 sudo 切换到高权限用户(如 root)。

使⽤Block分组做特权升级

如果 play 中有⼀部分任务需要(或不需要)特权升级,可以对块设置 become。 块中的所有任务共享相同的特权升级设置,它将覆盖在 play 级别上进⾏的设置。

简单回顾一下block相关的知识

block

  • 作用:定义一个逻辑任务块,将一组相关任务组织在一起。

  • 特点:可以统一应用条件(如 when)、权限提升(如 become)等设置,简化配置。

rescue

  • 作用:用于处理 block 中任务失败后的补救措施。

  • 特点:只有当 block 中的任意任务失败时,rescue 中的任务才会运行。

always

  • 作用:无论 block 中的任务是否成功或失败,always 中的任务都会运行。

  • 特点:适用于清理、日志记录等任务,确保它们始终被执行。

了解了基本知识之后,我们来看下面的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
---
- name: Deploy web services
hosts: webservers
become: false
tasks:

- name: Tasks that need privilege escalation
block:
- name: Ensure httpd is installed
ansible.builtin.yum:
name: httpd
state: installed
- name: Start and enable webserver
ansible.builtin.service:
name: httpd
state: started
enabled: true
become: true

在这段 Playbook 中,blockbecome 的结合使用非常重要,它为特定的一组任务(block 内的任务)启用了权限提升功能。

block 内的 become 用法

  1. 层级覆盖规则

    • block 中的 become: true 会覆盖 Playbook 顶层设置的 become: false

    • 这意味着只有 block 内的任务会启用权限提升,而 block 外的任务仍然保持非特权模式运行。

  2. 作用范围

    • block 内的所有任务共享 become: true,即所有任务(如安装 httpd 和启动服务)都以高权限(如 sudo)运行,而无需在每个任务中重复设置。
  3. 执行效果

    • 安装 httpd启动 web 服务 都需要管理员权限。在没有特权提升的情况下,这些任务可能会因为权限不足而失败。

    • 使用 blockbecome: true 提升了权限,使这些任务能够顺利执行。

在⻆⾊中应⽤特权升级

  • 在 Ansible 的角色中应用 become 是为了确保角色中的某些或全部任务以提升权限的方式(例如通过 sudo 切换到管理员用户)执行,这在需要修改系统文件、安装软件等场景中尤为重要。

应用方式如下

在角色的任务中启用 become

  • 可以直接在角色的任务文件中(例如 tasks/main.yml)为特定任务或任务块设置 become: true,实现权限提升。

  • 这种方式的优先级最高,适用于单独任务需要权限提升的场景。

  • 在角色中全局启用 become

    • 如果角色中的大多数任务都需要权限提升,可以在 role 的定义中配置 become: true。比如在 Playbook 中如下使用:

      这种方式会对整个角色中的所有任务生效,无需在每个任务中重复定义。

1
2
3
4
5
- name: Example play with one role
hosts: localhost
roles:
- role: role-name
become: true

使⽤连接变量列出特权升级

需要注意的是,这种方法并不常见

连接变量将覆盖配置⽂件中的 become 设置,以及 play、任务、块和⻆⾊中的相应设置。

使⽤这些连接变量来配置特权升级时要⼩⼼,因为其优先级要⾼于配置和 playbook指令

  1. ansible_become

  2. ansible_become_method

  3. ansible_become_user

  4. ansible_become_pass

1
2
3
4
5
6
webservers:
hosts:
servera.lab.example.com:
serverb.lab.example.com:
vars:
ansible_become: true
1
2
3
4
5
webservers:
hosts:
servera.lab.example.com:
ansible_become: true
serverb.lab.example.com:
1
2
3
4
5
6
7
8
9
10
---
- name: Example play using connection variables
hosts: webservers
vars:
ansible_become: true
tasks:
- name: Play will use privilege escalation even if inventory says no
ansible.builtin.yum:
name: perl
state: installed

选择特权升级⽅法

  • 在使用 Ansible 管理任务时,特权升级(Privilege Escalation)是一项常见且必要的功能,确保任务可以以更高权限完成系统级操作。但为了提升安全性和效率,特权升级的选择和应用应该经过仔细规划,以下是一些详细的建议:

  • 如果可能,请使用最低特权运行任务

    在任务执行中,应尽量遵循最小特权原则(Principle of Least Privilege)。仅在需要特权的任务上开启权限提升,而无需全局默认启用。这不仅能够减少潜在的安全隐患,还能降低因误操作导致的风险。例如,如果某个任务只是读取文件或获取信息,无需 root 权限即可完成,应避免使用 become。这样既保持任务的轻量化,也能更好地保护系统的核心安全。

  • 始终开启特权升级的场景

    某些任务本质上必须以高权限用户(如 root)身份运行,例如:

    • 安装、移除或升级系统级软件包。

    • 修改系统配置文件(如 /etc 下的文件)。

    • 启动、停止或重新配置系统服务。

      在这些场景中,特权升级应作为默认设置。这可以通过为 Play 或 Block 启用 become: true 来实现,同时避免单独为每个任务重复配置权限。

  • 明确需要特权升级的层级(Task、Play 或 Block)

    在配置特权升级时,应优先明确权限的应用范围:

    • Task 级别:适用于个别需要特权的任务。在任务上直接声明 become: true 可显式限定权限的范围。

    • Block 级别:当一组任务需要统一开启特权时,可以通过 block 在一个逻辑单元中启用特权提升,同时保持其他任务的不受影响。这种方法便于管理需要特权的多个相关任务,增强代码清晰性。

    • Play 级别:适用于 Play 中所有任务都需要高权限的情况。通过在 Play 顶层设置 become: true,可以减少重复配置,但需要注意任务安全性,避免对某些任务赋予不必要的权限。

通过在 Task、Block 和 Play 三个层次上有针对性地管理特权升级,你可以更灵活地满足特定任务的需求,同时最大限度地优化安全性与效率。