Privilege Escalation: How a `remote_user` and a `become_user` works

One of its Ansible’s features is the ability to execute tasks with elevated privileges, often necessary for managing system configurations. This process is known as privilege escalation.
Let’s dive into the details of how privilege escalation works in Ansible, how to configure it using different variables, and the best practices for secure and effective use.
Understanding Privilege Escalation
Privilege escalation in Ansible refers to the ability to run tasks with higher permissions than the user who initially connects to the remote system. This is crucial for operations that require root or administrator access, such as installing packages, modifying system configurations, or managing services.
To see all configuration possibilities you can use the following command
Ansible documentationansible-config init --disabled -t all > ansible.cfg
Users in Ansible Context
user: This is the user account on the control machine running Ansible.remote_user: This is the user account on the managed nodes that Ansible connects to via SSH.become_user: This is the user account on the managed nodes to which Ansible escalates privileges.
Key Variables for Privilege Escalation
Ansible uses several variables to control privilege escalation. Let’s explore each one:
become: This boolean variable enables or disables privilege escalation.become_method: Specifies the privilege escalation method (e.g., sudo, su, pbrun).become_user: Defines the user to become for privilege escalation.become_ask_pass: Determines whetherAnsibleshould prompt for a password.become_pass: This defines the password for privilege escalation.become_pass_file: This specifies a file containing the password for privilege escalation.become_flags: This sets the flags to pass to the privilege escalation command.
Let’s look at how to configure each of these variables with examples.
1. become
The become variable is the master switch for privilege escalation. When set to true, Ansible will attempt to escalate privileges for the specified tasks.
Example:
- name: Install nginx
  apt:
    name: nginx
    state: present
  become: true2. become_method
The become_method variable specifies how Ansible should escalate privileges. Common values include:
- sudo
 - su
 - pbrun
 - pfexec
 - doas
 - dzdo
 - ksu
 - runas
 - pmrun
 
Example:
- name: Restart nginx service
  service:
    name: nginx
    state: restarted
  become: true
  become_method: sudo3. become_user
The become_user variable allows you to specify which user Ansible should become when escalating privileges. This is particularly useful when you need to perform actions as a specific system user.
Example:
- name: Create a directory as www-data
  file:
    path: /var/www/new_site
    state: directory
  become: true
  become_user: www-data4. become_ask_pass
When set to true, become_ask_pass prompts for a password for privilege escalation. This is useful when you can’t store the sudo password in plain text or when you need to enter it interactively.
Example:
[privilege_escalation]
# (boolean) Toggle to prompt for privilege escalation password.
become_ask_pass=TrueOnce it is set and when you execute a playbook you should expect a prompt
> ansible-playbook play-one.yml 
BECOME password: Combining Variables: Password and Password File Examples
Let’s look at two common scenarios for handling passwords:
1. Interactive Password Prompt for the login user (SSH User, remote_user)
Let’s configure ansible.cfg with the required properties
# (boolean) This controls whether an Ansible playbook should prompt for a login password. If using SSH keys for authentication, you probably do not need to change this setting.
ask_pass=True
# (string) Sets the login user for the target machines
# When blank it uses the connection plugin's default, normally the user currently executing Ansible.
remote_user=ruser- hosts: all
  tasks:
    - name: Run a command as root
      command: whoami
      register: who
    - debug:
        var: who.stdoutNow when you run the playbook you should expect a password prompt
> ansible-playbook play-two.yml
SSH password: 
PLAY [all] ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [Run a command as root] *********************************************************************************************************************************************************************************************************************************************************************************************************************************************
changed: [localhost]
TASK [debug] *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "who.stdout": "ruser"
}
PLAY RECAP ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
You can configure the password file as well
# (boolean) This controls whether an Ansible playbook should prompt for a login password. If using SSH keys for authentication, you probably do not need to change this setting.
ask_pass=False
# (path) The password file to use for the connection plugin. --connection-password-file.
connection_password_file=./connection.ymlI added the password information in the local directory and now if you run you should be prompted for password
> ansible-playbook play-two.yml
PLAY [all] ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [Run a command as root] *********************************************************************************************************************************************************************************************************************************************************************************************************************************************
changed: [localhost]
TASK [debug] *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "who.stdout": "ruser"
}
PLAY RECAP ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   Combining with become user now.
- hosts: all
  become: true
  become_method: sudo
  tasks:
    - name: Run a command as root
      command: whoami
      register: who
    - debug:
        var: who.stdoutNow when I run with the configuration already defined in sections above.
TASK [debug] *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "who.stdout": "root"
}Who is the ssh login user can be defined in two ways
remote_user: Property in the ansible.cfgansible_user: Property in the inventory for each host.
