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