How to Secure Ansible Playbooks with Ansible Become

Published:9 February 2022 - 5 min. read

If you need to run commands on multiple machines with different users, then nothing could be better than using Ansible become. Ansible become allows you to become another user to deploy or manage the remote nodes, regardless of which user you’re logged into.

In this tutorial, you’ll learn how to work with Ansible become directives, Ansible become variables, and how to declare them in the Ansible playbook.

Read on and start securing your playbooks!

Prerequisites

This tutorial comprises step-by-step instructions. If you’d like to follow along, be sure you have the following in place:

  • A remote Linux computer to test the tomcat installation – This tutorial uses Ubuntu 20.04.3 LTS as the remote node.
  • An already user-created and Apache service installed on the remote node – This tutorial demonstrates a user named Shankym.
  • An inventory file and one or more hosts are configured to run Ansible commands and playbooks – The remote Linux computer is called myserver, and this tutorial uses an inventory group called web.
  • Python v3.6 or later installed both on your Ansible controller host and the remote node machine – This tutorial uses Python v3.9 on an Ubuntu machine.

Running Ansible Ad Hoc Commands with Ansible Become

Do you need an urgent security fix to deploy and restart the SSH service? Running ad hoc commands will do the trick. Ad hoc commands are a quick way to run a single command on a remote host and deploy the specified changes.

Open the terminal on your Ansible controller host, and run the ansible command below to connect to the host called web using the ansible.builtin.service module (-m).

The command passes an argument (-a) that lets Ansible restart the (apache) service on the remote node you specified in the command.

ansible web -m ansible.builtin.service -a "name=apache2 state=restarted" --become

If you wish for the Ansible ad hoc command to prompt you for a password, then consider using the -ask-become-pass command instead of just the --become parameter.

Once the command completes, you’ll see a CHANGED message, as shown below. The output below confirms Ansible successfully restarted the apache service on the remote host.

Restarting the Apache service on the Remote Node
Restarting the Apache service on the Remote Node

Now run the below command to check the status of the apache service using other users (shankym) with the --become-user parameter.

ansible web -m ansible.builtin.service -a "name=apache2 state=restarted" --become-user=shankym
Checking the Apache service on the Remote Node as Another User (shankym)
Checking the Apache service on the Remote Node as Another User (shankym)

Running Ansible Playbooks with Ansible become

In the previous section, you learned how to use Ansible ad hoc commands to fix or restart the apache service urgently. Now that the security threat is handled, you need to ensure that the threat is mitigated automatically in the future.

The best way to mitigate future threats is by using Ansible playbooks with the ansible-playbook command instead of ad-hoc commands.

1. Create a project directory in your home directory and switch to that directory. You can name the directory as you prefer, but for this demo, the directory is called ~/ansible_become_playbook_demo.

This directory will contain the playbook you’ll invoke later in the section.

mkdir ~/ansible_become_playbook_demo
cd ~/ansible_become_playbook_demo

2. Next, create a file called my_playbook.yml in the ~/ansible_become_playbook_demo directory and paste in the following YAML playbook contents.

This playbook has a task that uses the Ansible line-in-file module to check if ADMIN is present in the /etc/sudoers file; if not, the task adds it on the remote machine.

The Playbook also contains two parameters:

  • become_method – allows you to activate the privilege escalation,
  • become_user – allows switching to other users (shankym).

become_method overrides the default method set in ansible.cfg configuration file.

You can set the become: yes if you wish the currently logged-in user to run the task in the Ansible playbook.

---
- name: Ansible become Playbook demo
# Defining the remote server where Ansible Playbook will be executed.
  hosts: web
# Set become_method to su to activate privilege escalation.
  become_method: su
# Switching to the new user shankym
  become_user: shankym
  tasks:

# Task to Check the Sudoers file if Admins are allowed to perform all operations 
    - name: Validate the sudoers file before saving
      ansible.builtin.lineinfile:
         path: /etc/sudoers
         state: present
         regexp: '^%ADMIN ALL='
         line: '%ADMIN ALL=(ALL) NOPASSWD: ALL'

3. Run the below command to invoke the playbook (my_playbook.yml) you previously created (step two). The playbook then executes the tasks to add or update all the lines defined in the playbook on the remote host.

Validating the Ansible playbook using the --check flag with the ansible-playbook command shown below is a good practice before actually executing the playbook.

ansible-playbook my_playbook.yml 

Below, you can see that the TASK has the OK status, which shows tasks don’t require any changes.

Executing the Ansible Playbook
Executing the Ansible Playbook

4. Now, SSH into the remote host using your favorite SSH client.

5. Finally, run the cat command below to verify if the line defined in the my_playbook.yml are updated or added on the remote host. # To verify if admin is present with full privileges, and if not, add it cat /etc/sudoers

# To verify if admin is present with full privileges, and if not, add it
cat /etc/sudoers

The below screenshot confirms that the admin is already added in the /etc/sudoers file.

Verifying the /etc/sudoers file in the Remote Node
Verifying the /etc/sudoers file in the Remote Node

Working with Ansible become with Connection Variables

You previously learned how to run the Ansible playbook for a remote node with a particular user variable within the Ansible playbook. But if you need to manage different remote nodes or groups of remote nodes with different users or rights, consider declaring the Ansible connection variables.

Create a file named inventory in the same ~/ansible_become_playbook_demo directory and populate the file with the following lines.

The below inventory contains the following:

  • The hostname of the remote nodes (ip-10-111-11-149/150/151).
  • The user that will run the task within the playbook (ansible_user).
  • If the user needs to be run all tasks as root (ansible_become_method=su).

You could use ansible_become_password if you need to define the password of the ansible_user parameter. Or use ansible_common_remote_group if you declared all the remote nodes within a group in the inventory.

# Declaring the hostname of the first remote node and the user 
# to execute the task is ubuntu
ip-10-111-11-149 ansible_user=ubuntu
# Declaring the hostname of the second remote node and the user 
# to execute the task is ubuntu1
ip-10-111-11-150 ansible_user=ubuntu1 ansible_become_method=su
# Declaring the hostname of the third remote node and the user 
# to execute the task is ubuntu2
ip-10-111-11-151 ansible_user=ubuntu2 ansible_become_method=su

Now open the same playbook (my_playbook.yml), remove the become_user and become_method parameters, and replace hosts: web with hosts: ip-10-111-11-149.

The Ansible playbook below executes only on the ip-10-111-11-149 host with ubuntu user and executes the task to validate the /etc/sudoers file.

---
- name: Ansible become Playbook demo
# Defining the host server based on your inventory file
# where Ansible Playbook will be executed.
# ip-10-111-11-150 (ubuntu1) | ip-10-111-11-151 (ubuntu2)
	hosts: ip-10-111-11-149  # ubuntu
  tasks:
# Task to Check the Sudoers file if Admins can perform all operations
    - name: Validate the sudoers file before saving
# Executing the Ansible Lineinfile module in the Playbook
      ansible.builtin.lineinfile:
# Checking the sudoers file in etc directory
         path: /etc/sudoers
         state: present
         regexp: '^%ADMIN ALL='
         line: '%ADMIN ALL=(ALL) NOPASSWD: ALL'
Executing the Ansible Playbook to validate the sudoers file using the ansible-playbook command
Executing the Ansible Playbook to validate the sudoers file using the ansible-playbook command

Conclusion

In this tutorial, you’ve taken advantage of the Ansible become parameter to manage services with a single command. You also learned how to use various Ansible become parameters to become another user while deploying or managing remote nodes.

Now that you have sound knowledge of the Ansible become, which method or parameter will you implement next in your Ansible playbook?

Hate ads? Want to support the writer? Get many of our tutorials packaged as an ATA Guidebook.

Explore ATA Guidebooks

Looks like you're offline!