Ansible: Privilege escalation more secure using Ansible-Vault

INTRODUCTION

Sometimes it’s necessary to execute the tasks of the Playbook with root user in the remote servers. To escalate privileges we have to set become variable to yes: “become: yes”. There are different methods of privilege escalation but the most common to use that is sudo method.

For example I’m using in my inventory(/etc/ansible/hosts) the following variables:

# VARS
[all:vars]
ansible_user=remote
#ansible_ssh_pass=PASSWORD
ansible_port=22

With ansible_user variable I’m telling to Ansible which is the user that will connect by ssh to the remotes servers, in my case the user is always “remote“. But this user is not an user with enough privileges to install packages or change some configurations of the system. To do that it’s necessary to elevate privileges using sudo. Sudo means that when you execute a command with sudo the command is actually executed by the root user, instead the login user. And to activate it we just have to set become variable to yes.

Currently I have commented the line of ansible_ssh_pass variable because I prefer to use a ssh trust relationship (distribute ssh authorized key with ansible) between Ansible master and the remote servers. This means that I am able to connect via ssh with the remote user without entering the password.

For example, this is the header of a simple Playbook:

---
- hosts: web
  name: Install the apache web service
  become: yes

FAILED! => {“msg”: “Missing sudo password”}

But is still necessary to configure the sudo password in a secure way avoiding plain text passwords for security reasons. If we don’t have the sudo password correctly configured we will receive the following output:

[remote@ansible]$ ansible-playbook YOUR_PLAYBOOK.yml
PLAY [This is a play within a playbook] ****************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************
fatal: [node1]: FAILED! => {"msg": "Missing sudo password"}

PLAY RECAP *********************************************************************************************************************
node1                      : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0 

Option –ask-become-pass

Of course you can add the “–ask-become-pass” option to introduce your sudo password manually in the prompt:

[remote@ansible apache-basic-playbook]$ ansible-playbook --ask-become-pass YOUR_PLAYBOOK.yml 

BECOME password: 

USING ANSIBLE-VAULT

Ansible-Vault: A secure way to specify the sudo password

1. Add variables to your Playbook

Add the following variables to your Playbook:

  vars_files:
    - ~/.ansible/my_vault.yml

  vars:
    ansible_become_pass: '{{ su_password }}'
  • – ~/.ansible/my_vault.yml: is the encrypted file with the sudo password we will generate later using ansible-vault command.
  • ansible_become_pass: ‘{{ su_password }}’: is the variable that contain the sudo password value. We will generate later using ansible-vault command.

2. Generate an encrypted vars-file for your password with Ansible-Vault

The next step is create a new encrypted data file called my_vault.yml, executing this :

[remote@ansible]$ ansible-vault create my_vault.yml
New Vault password: 
Confirm New Vault password: 

After providing the Vault password, an editor will appear and we only need to add the following with our own sudo password, and save de file how we would do with Vi editor (:wq).

su_password: your_sudo_password_for_remote_servers

After executing the previous command, the my_vault.yml file has been created and the content of the file it would be similar to:

[remote@ansible]$ cat my_vault.yml
$ANSIBLE_VAULT;1.1;AES256
34641533663037383731303932356633646264643631353431313636643110643439393933646366
6666666239343761336536303930313537386366313434360a653236383634356466353339616332
61366161365555576365383436623437326434346235633336356634353730376463356136333262
3930356238353730330a326462366334353236664444303236666634646662383662656336303863
62653132353435333534313234343939343733646231366339356566313234383331

Then move my_vault.yml file to ~/.ansible folder:

[remote@ansible]$ mv my_vault.yml ~/.ansible/my_vault.yml

Create a file to keep your Vault password

Create .vault_pass.txt file to keep your vault password in it. The password should be a string stored as a single line in the file.

[remote@ansible]$ vi ~/.ansible/.vault_pass.txt

PASSWORD

Ensure permissions on the file are such that no one else can access your key and do not add your key to source control:

[remote@ansible]$ chmod 640 ~/.ansible/.vault_pass.txt

Add ANSIBLE_VAULT_PASSWORD_FILE environment variable

And add the environment variable ANSIBLE_VAULT_PASSWORD_FILE to .bash_profile file of the remote user:

[remote@ansible]$ vi ~/.bash_profile

# ANSIBLE
ANSIBLE_VAULT_PASSWORD_FILE=~/.ansible/.vault_pass.txt
export ANSIBLE_VAULT_PASSWORD_FILE

3. Executing the Playbook with Privilege Escalation

Finally to run our playbook using the privilege escalation option and the encrypted sudo password we’ve already created, we can execute the following command:

Introducing your Vault password in the prompt:

[remote@ansible]$ ansible-playbook --ask-vault-pass YOUR_PLAYBOOK.yml

Vault password: 

Or without any prompt:

[remote@ansible]$ ansible-playbook YOUR_PLAYBOOK.yml
PLAY [This is a play within a playbook] ********************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************
ok: [node1]

TASK [install httpd packages] ******************************************************************************************************************************
changed: [node1] => (item=[u'httpd', u'mod_wsgi'])

TASK [create site-enabled directory] ***********************************************************************************************************************
ok: [node1]

TASK [copy httpd.conf] *************************************************************************************************************************************
ok: [node1]

TASK [copy index.html] *************************************************************************************************************************************
changed: [node1]

TASK [start httpd] *****************************************************************************************************************************************
changed: [node1]

RUNNING HANDLER [restart apache service] *******************************************************************************************************************
changed: [node1]

PLAY RECAP *************************************************************************************************************************************************
node1                      : ok=7    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

Documentation:

https://docs.ansible.com/ansible/latest/user_guide/become.html

https://docs.ansible.com/ansible/latest/user_guide/playbooks_vault.html

Compartir:

This article was written by RoberMB

💻OS, ☁️Cloud, 🛡️Cybersecurity, ✈️Traveling #Linux, #Ansible, #AWS, #VMware, #Docker 🏴‍☠️ CEH v10, CPHE 🏴‍☠️ ... Always learning, always enjoying.

2 thoughts on “Ansible: Privilege escalation more secure using Ansible-Vault”

  1. Hello,
    can you please calibrate:
    1) su_password: your_sudo_password_for_remote_servers – if I need to input the actual ansible passwd
    that be used for sudo su – then at my company it will not be acceptable

    2) Create .vault_pass.txt file to keep your vault password in it. The password should be a string stored as a single line in the file.

    [remote@ansible]$ vi ~/.ansible/.vault_pass.txt

    PASSWORD = those lines from my_vault.yml ?

    Please reply back to me.

    Thank you.
    Michael.

    1. Hello,

      – “su_password: your_sudo_password_for_remote_servers: … if I need to input the actual ansible passwd
      that be used for sudo su – then at my company it will not be acceptable”
      So you should to choose your own become method:

      –become-method=BECOME_METHOD
      privilege escalation method to use (default=sudo), valid choices: [ sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas | machinectl ]

      Here you can check it in the official documentation.
      https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_privilege_escalation.html
      – “Create .vault_pass.txt file to keep your vault password in it.”, this step is only useful in case you need to save your vault password to a file. Normally in a professional environment you will use Ansible Tower, so you can add a ‘Credential’, so that Vault encrypted playbooks can be used with Tower.

      As an idea, you can securely store your SSH keys in your inventory using Ansible Vault. It allows encrypting them with a password or passphrase, protecting them from unauthorized access. Then create a .vault file in your inventory and store the SSH keys within. And use the –vault-password or –vault-file option when running Ansible to unlock the keys and execute tasks.

      I hope this helps you.

      Roberto

Leave a Reply

Your email address will not be published. Required fields are marked *