Bootstrap FreeKB - Ansible - become parameter (sudo)
Ansible - become parameter (sudo)

Updated:   |  Ansible articles

Let's say you have the following playbook which will reboot target servers. reboot can only be run by root or by a user or group that has been granted sudo permission to the reboot command, because the reboot command is within the sbin directory (e.g. /usr/sbin/reboot).

---
- hosts: all
  tasks:
  - name: reboot the OS
    reboot:
      msg: "Reboot initiated by Ansible"
      connect_timeout: 5
      reboot_timeout: 600
      pre_reboot_delay: 0
      post_reboot_delay: 30
      test_command: whoami
...

 

Let's say John Doe has not been granted sudo access to the reboot command and John Doe runs this playbook.

[john.doe@control1 ~] ansible-playbook reboot.yml

 

Something like this should be returned.

TASK [reboot the OS] 
fatal: [server1.example.com]: FAILED! => {
  "changed": false, 
  "elapsed": 0, 
  "msg": "Reboot command failed. Error was Failed to set wall message, ignoring: Interactive authentication required.\r\nFailed to call ScheduleShutdown in logind, proceeding with immediate shutdown: Interactive authentication required.\r\nFailed to set wall message, ignoring: Interactive authentication required.\r\nFailed to reboot system via logind: Interactive authentication required.\r\nFailed to open initctl fifo: Permission denied\r\nFailed to talk to init daemon., Shared connection to docker1.software.eng.us closed.", 
  "rebooted": false, 
  "start": "2021-06-20T18:27:12.089854"
}

 

One solution is to invoke the ansible-playbook command as root on the control node.

[root@control1 ~]# ansible-playbook ssh.yml --ask-pass

 

Or by invoking the ansible-playbook as John Doe using the --user root command line option.

[john.doe@control1 ]# ansible-playbook ssh.yml --user root --ask-pass

 

Or by including the remote_user: root parameter in the playbook.

---
- hosts: all
  remote_user: root

 

However, all of these options are a bit uncommon. Most often, become is used, to "become" another user. For example, John Doe could issue the ansible-playbook command, including the become command line options to become root.

Notice here that the become method is su (switch user). This is needed when no other users or groups have been granted sudo permission to the reboot command.

ansible-playbook reboot.yml --become --become-user=root --become-method=su --ask-become-pass

 

Or by including the become directives in the playbook.

---
- hosts: all
  tasks:
  - name: reboot the OS
    reboot:
      msg: "Reboot initiated by Ansible"
      connect_timeout: 5
      reboot_timeout: 600
      pre_reboot_delay: 0
      post_reboot_delay: 30
      test_command: whoami
    become: yes
    become_user: root
    become_method: su
...

 

Or better yet, put the become options near the top of the playbook so that you become the user for all tasks in the playbook.

---
- hosts: all
  become: yes
  become_user: root
  become_method: su
  tasks:
  - name: reboot the OS
    reboot:
      msg: "Reboot initiated by Ansible"
      connect_timeout: 5
      reboot_timeout: 600
      pre_reboot_delay: 0
      post_reboot_delay: 30
      test_command: whoami
...

 

In this scenario, you would still need to include the --ask-become-pass command line option, because there isn't a way to include the become password in the playbook.

ansible-playbook reboot.yml --ask-become-pass

 

There are a few ways to not have to include the --ask-become-pass command line option. Probably the least preferred option would be to include the ansible_become_pass variable in a file, such as in the main ansible configuration file (ansible.cfg) or in your hosts/inventory file (e.g. hosts.yml).

ansible_become_pass: itsasecret

 

And then the reboot.yml playbook could be run as root without having to include the --ask-become-pass flag.

[root@control1 ~] ansible-playbook reboot.yml

 

However, this option is obviously a bad idea from a security perspective, as whenever possible, cleartext passwords should not be defined in a file. Plus, it's common to not allow access to root user account. In this scenario, a good option here would be to grant members of the wheel group permission to invoke the reboot command using sudo and ensure John Doe is a member of the wheel group. Here is how you could grant users that a members of the wheel group sudo permission, using the group, user and copy modules.

---
- hosts: all
  tasks:
  - name: ensure the wheel group exists
    group:
      name: wheel
      state: present

  - name: ensure john.doe is a member of the wheel group
    user:
      name: john.doe
      groups: wheel
      append: yes

  - name: copy sudoers file to /etc/sudoers
    copy:
      src: /usr/local/ansible/files/sudoers
      dest: /etc/sudoers
      owner: root
      group: root
      mode: "0440"
...

 

Notice in this example that the sudoers file is copied to the managed node. I prefer this over using something like the lineinfile module. In this example, the sudoers file would have something like this which allows users that are members of the wheel group to use sudo without having to provide their password.

%wheel All=(ALL)    NOPASSWD (ALL)

 

After the wheel group has been granted sudo access, John Doe can run the reboot.yml playbook without having to include the --ask-become-pass flag.

[john.doe@control1 ~] ansible-playbook sudo.yml --become

 

Or by include the become: yes flag in reboot.yml

---
- hosts: all
  tasks:
  - name: reboot the OS
    reboot:
      msg: "Reboot initiated by Ansible"
      connect_timeout: 5
      reboot_timeout: 600
      pre_reboot_delay: 0
      post_reboot_delay: 30
      test_command: whoami
    become: yes
...

 




Did you find this article helpful?

If so, consider buying me a coffee over at Buy Me A Coffee



Comments


Add a Comment


Please enter c3f5d0 in the box below so that we can be sure you are a human.