{"id":1703,"date":"2019-07-24T21:50:11","date_gmt":"2019-07-24T21:50:11","guid":{"rendered":"http:\/\/robermb.com\/blog\/?p=1703"},"modified":"2024-02-25T12:33:54","modified_gmt":"2024-02-25T11:33:54","slug":"privilege-escalation-with-ansible-more-secure-using-vault","status":"publish","type":"post","link":"https:\/\/robermb.com\/blog\/geeks\/privilege-escalation-with-ansible-more-secure-using-vault\/","title":{"rendered":"Ansible: Privilege escalation more secure using Ansible-Vault"},"content":{"rendered":"\n<h3 class=\"wp-block-heading\">&#8211; <span style=\"text-decoration: underline;\">INTRODUCTION<\/span><\/h3>\n\n\n\n<p>Sometimes it&#8217;s necessary to <strong>execute the tasks<\/strong> of the Playbook <strong>with root user<\/strong> in the remote servers. To <strong>escalate privileges<\/strong> we have to set become variable to yes: \u201c<strong>become: yes<\/strong>\u201d. There are different methods of privilege escalation but the most common to use that is <strong>sudo method<\/strong>.<\/p>\n\n\n\n<p>For example I&#8217;m using in my <strong>inventory<\/strong>(\/etc\/ansible\/hosts) the following <strong>variables<\/strong>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># VARS\n&#91;all:vars]\nansible_user=remote\n#ansible_ssh_pass=PASSWORD\nansible_port=22<\/code><\/pre>\n\n\n\n<p>With <strong>ansible_user<\/strong> variable I&#8217;m telling to Ansible which is the user that will connect by ssh to the remotes servers, in my case the user is always &#8220;<strong>remote<\/strong>&#8220;. But this user is not an user with enough privileges to install packages or change some configurations of the system. To do that it&#8217;s necessary to <strong>elevate privileges<\/strong> 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<strong> activate<\/strong> it we just have to <strong>set become variable to yes<\/strong>.<\/p>\n\n\n\n<p>Currently I have commented the line of <strong>ansible_ssh_pass<\/strong> variable because I prefer to use a <strong><a rel=\"noreferrer noopener\" href=\"https:\/\/robermb.com\/blog\/geeks\/configure-ssh-trust-relationship\/\" target=\"_blank\">ssh trust relationship<\/a><\/strong> (<a href=\"https:\/\/robermb.com\/blog\/geeks\/ansible-distribute-ssh-authorized-key-to-all-the-inventory\/\" data-type=\"URL\" data-id=\"https:\/\/robermb.com\/blog\/geeks\/ansible-distribute-ssh-authorized-key-to-all-the-inventory\/\" target=\"_blank\" rel=\"noreferrer noopener\">distribute ssh authorized key with ansible<\/a>) 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.<\/p>\n\n\n\n<p>For example, this is the header of a simple Playbook:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>---\n- hosts: web\n  name: Install the apache web service\n  become: yes<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">FAILED! =&gt; {&#8220;msg&#8221;: &#8220;Missing sudo password&#8221;}<\/h3>\n\n\n\n<p>But is still necessary to configure the sudo password in a secure way avoiding plain text passwords for security reasons. If we don&#8217;t have the sudo password correctly configured we will receive the following output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;remote@ansible]$ ansible-playbook YOUR_PLAYBOOK.yml<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>PLAY &#91;This is a play within a playbook] ****************************************************************************************\n\nTASK &#91;Gathering Facts] *********************************************************************************************************\nfatal: &#91;node1]: FAILED! =&gt; {\"msg\": \"Missing sudo password\"}\n\nPLAY RECAP *********************************************************************************************************************\nnode1                      : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0 <\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Option &#8211;ask-become-pass<\/h3>\n\n\n\n<p>Of course you can add the &#8220;&#8211;ask-become-pass&#8221; option to <strong>introduce your sudo password manually<\/strong> in the prompt:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;remote@ansible apache-basic-playbook]$ ansible-playbook --ask-become-pass YOUR_PLAYBOOK.yml \n\nBECOME password: <\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">&#8211; <span style=\"text-decoration: underline;\">USING ANSIBLE-VAULT<\/span><\/h3>\n\n\n\n<h3 class=\"wp-block-heading\">Ansible-Vault: A secure way to specify the sudo password<\/h3>\n\n\n\n<h3 class=\"wp-block-heading\">1. Add variables to your Playbook<\/h3>\n\n\n\n<p>Add the following variables to your Playbook:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  vars_files:\n    - ~\/.ansible\/my_vault.yml\n\n  vars:\n    ansible_become_pass: '{{ su_password }}'<\/code><\/pre>\n\n\n\n<ul><li><strong>&#8211; ~\/.ansible\/my_vault.yml<\/strong>: is the encrypted file with the sudo password we will generate later using ansible-vault command.<\/li><\/ul>\n\n\n\n<ul><li><strong>ansible_become_pass: &#8216;{{ su_password }}&#8217;<\/strong>: is the variable that contain the sudo password value. We will generate later using ansible-vault command.<\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">2. Generate an encrypted vars-file for your password with Ansible-Vault<\/h3>\n\n\n\n<p>The next step is <strong>create<\/strong> a new <strong>encrypted data file<\/strong> called <strong>my_vault.yml<\/strong>, executing this :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;remote@ansible]$ <strong>ansible-vault create my_vault.yml<\/strong>\nNew Vault password: \nConfirm New Vault password: <\/code><\/pre>\n\n\n\n<p>After providing the<strong> Vault password<\/strong>, an <strong>editor<\/strong> 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).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>su_password<\/strong>: your_sudo_password_for_remote_servers<\/code><\/pre>\n\n\n\n<p>After executing the previous command, the <strong>my_vault.yml<\/strong> file has been created and the content of the file it would be similar to:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;remote@ansible]$ cat my_vault.yml\n$ANSIBLE_VAULT;1.1;AES256\n34641533663037383731303932356633646264643631353431313636643110643439393933646366\n6666666239343761336536303930313537386366313434360a653236383634356466353339616332\n61366161365555576365383436623437326434346235633336356634353730376463356136333262\n3930356238353730330a326462366334353236664444303236666634646662383662656336303863\n62653132353435333534313234343939343733646231366339356566313234383331<\/code><\/pre>\n\n\n\n<p>Then <strong>move my_vault.yml<\/strong> file to <strong>~\/.ansible folder<\/strong>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;remote@ansible]$ mv my_vault.yml ~\/.ansible\/my_vault.yml<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Create a file to keep your Vault password<\/h3>\n\n\n\n<p>Create<strong> .vault_pass.txt<\/strong> file to keep your vault password in it. The password should be a string stored as a single line in the file.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;remote@ansible]$ vi ~\/.ansible\/.vault_pass.txt\n\nPASSWORD<\/code><\/pre>\n\n\n\n<p><strong>Ensure<\/strong> <strong>permissions<\/strong> on the file are such that no one else can access your key and do not add your key to source control:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;remote@ansible]$ chmod 640 ~\/.ansible\/.vault_pass.txt<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Add <strong>ANSIBLE_VAULT_PASSWORD_FILE<\/strong> environment variable<\/h3>\n\n\n\n<p>And add the environment variable <strong>ANSIBLE_VAULT_PASSWORD_FILE<\/strong> to <strong>.bash_profile<\/strong> file of the remote user:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;remote@ansible]$ vi ~\/.bash_profile\n\n# ANSIBLE\nANSIBLE_VAULT_PASSWORD_FILE=~\/.ansible\/.vault_pass.txt\nexport ANSIBLE_VAULT_PASSWORD_FILE<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">3. Executing the Playbook with Privilege Escalation<\/h3>\n\n\n\n<p>Finally to <strong>run our playbook<\/strong> using the privilege escalation option and the encrypted sudo password we&#8217;ve already created, we can execute the following command:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Introducing your Vault password in the prompt:<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;remote@ansible]$ ansible-playbook --ask-vault-pass YOUR_PLAYBOOK.yml\n\nVault password: <\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Or without any prompt:<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;remote@ansible]$ ansible-playbook YOUR_PLAYBOOK.yml<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>PLAY &#91;This is a play within a playbook] ********************************************************************************************************************\n\nTASK &#91;Gathering Facts] *************************************************************************************************************************************\nok: &#91;node1]\n\nTASK &#91;install httpd packages] ******************************************************************************************************************************\nchanged: &#91;node1] =&gt; (item=&#91;u'httpd', u'mod_wsgi'])\n\nTASK &#91;create site-enabled directory] ***********************************************************************************************************************\nok: &#91;node1]\n\nTASK &#91;copy httpd.conf] *************************************************************************************************************************************\nok: &#91;node1]\n\nTASK &#91;copy index.html] *************************************************************************************************************************************\nchanged: &#91;node1]\n\nTASK &#91;start httpd] *****************************************************************************************************************************************\nchanged: &#91;node1]\n\nRUNNING HANDLER &#91;restart apache service] *******************************************************************************************************************\nchanged: &#91;node1]\n\nPLAY RECAP *************************************************************************************************************************************************\nnode1                      : ok=7    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 <\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><span style=\"text-decoration: underline;\">Documentation<\/span>: <\/h3>\n\n\n\n<p><a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/become.html\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/become.html<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/playbooks_vault.html\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/playbooks_vault.html<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8211; INTRODUCTION Sometimes it&#8217;s necessary to execute the tasks of the Playbook with root user in the remote servers. To &hellip; <a href=\"https:\/\/robermb.com\/blog\/geeks\/privilege-escalation-with-ansible-more-secure-using-vault\/\" class=\"more-link\">More <span class=\"screen-reader-text\">Ansible: Privilege escalation more secure using Ansible-Vault<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":1809,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[103,2],"tags":[106,35],"_links":{"self":[{"href":"https:\/\/robermb.com\/blog\/wp-json\/wp\/v2\/posts\/1703"}],"collection":[{"href":"https:\/\/robermb.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/robermb.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/robermb.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/robermb.com\/blog\/wp-json\/wp\/v2\/comments?post=1703"}],"version-history":[{"count":32,"href":"https:\/\/robermb.com\/blog\/wp-json\/wp\/v2\/posts\/1703\/revisions"}],"predecessor-version":[{"id":2003,"href":"https:\/\/robermb.com\/blog\/wp-json\/wp\/v2\/posts\/1703\/revisions\/2003"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/robermb.com\/blog\/wp-json\/wp\/v2\/media\/1809"}],"wp:attachment":[{"href":"https:\/\/robermb.com\/blog\/wp-json\/wp\/v2\/media?parent=1703"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/robermb.com\/blog\/wp-json\/wp\/v2\/categories?post=1703"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/robermb.com\/blog\/wp-json\/wp\/v2\/tags?post=1703"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}