Let's say you have a playbook that contains a command that requires some sort of elevated privilege, such as reboot.
---
- hosts: all
tasks:
- name: reboot OS
ansible.builtin.reboot:
msg: "Reboot initiated by Ansible"
connect_timeout: 5
reboot_timeout: 600
pre_reboot_delay: 0
post_reboot_delay: 30
test_command: whoami
...
And john.doe does not have permission to issue the reboot command on the target server.
[john.doe@server1 ~]# reboot
reboot: Permission denied
When running the playbook as john.doe, "permission denied" will be returned.
[Errno 13] Permission denied
There are a couple way to handle this.
- Run the playbook as a user that has permission to run the task that is causing permission denied to be returned
- Use "become" to become a user that has permission to run the task that is causing permission denied to be returned
Let's say john.doe is a member of the wheel group on the target server.
[john.doe@server1 ~]# groups
john.doe wheel
And members of the wheel group have been granted sudo NOPASSWD to ALL commands on the target server.
]# cat /etc/sudoers.d/wheel
%wheel ALL = (ALL) NOPASSWD: ALL
In this scenario, instead of using the reboot module, you could use the shell module with sudo and the task should run properly. In this example, the target system should be rebooted.
---
- hosts: all
tasks:
- ansible.builtin.shell: sudo reboot
...
But this approach is discouraged and should return WARNINGS. Instead, using "become" is the recommended approach.
[WARNING]: Consider using 'become', 'become_method', and 'become_user' rather than running sudo
In this scenario, if we are running the playbook as john.doe, adding the become: yes and become_method: sudo options to the task in the playbook that are only permitted with sudo should resolve permission denied and WARNINGS. In other words, the target server should be rebooted.
---
- hosts: all
tasks:
- name: reboot OS
become: yes
become_method: sudo
ansible.builtin.reboot:
msg: "Reboot initiated by Ansible"
connect_timeout: 5
reboot_timeout: 600
pre_reboot_delay: 0
post_reboot_delay: 30
test_command: whoami
...
Or you can set become: yes and become_method: sudo at the play level (before pre_tasks / tasks / post_tasks) so that all tasks in the playbook are run with become sudo. In this example, if john.doe has been granted sudo permission to run both the reboot command and the /root/example.sh script then it may make sense to set become at the play level.
---
- hosts: all
become: yes
become_method: sudo
tasks:
- name: reboot OS
ansible.builtin.reboot:
msg: "Reboot initiated by Ansible"
connect_timeout: 5
reboot_timeout: 600
pre_reboot_delay: 0
post_reboot_delay: 30
test_command: whoami
- name: run /root/example.sh
ansible.builtin.shell: /root/example.sh
...
Or you can set become: yes and become_method: sudo in a block so that all of the tasks in the block are run with the become permissions. In this example, the task that creates the /tmp/example.log file is not run with become sudo permissions, but the tasks in the block are run with become sudo permissions.
---
- hosts: all
tasks:
- name: create the /tmp/example.log file
ansible.builtin.file:
path: /tmp/example.log
state: touch
- block:
- name: reboot OS
ansible.builtin.reboot:
msg: "Reboot initiated by Ansible"
connect_timeout: 5
reboot_timeout: 600
pre_reboot_delay: 0
post_reboot_delay: 30
test_command: whoami
- name: run /root/example.sh
ansible.builtin.shell: /root/example.sh
become: yes
become_method: sudo
...
It is also noteworthy that on a systemd system, the systemctl command is used to reboot the system, and only root has permission to execute the systemctl command.
[john.doe@server1 ~]# ls -l /bin/systemctl
-rwxr-xr-x. 1 root root 717568 Feb 4 10:30 /bin/systemctl
Let's say john.doe uses sudo to invoke the reboot command.
[john.doe@server1 ~]# sudo reboot
If john.doe has not been added to the /etc/sudoers file, the following will be displayed.
john.doe is not in the sudoers file. This incident will be reported.
If john.doe has been added to the /etc/sudoers file, but has not been granted permission to the command being issued, the following will be displayed.
john.doe is not allowed to run sudo on server1. This incident will be reported.
John Doe can be granted permission to the reboot command (or any other command).
If John Doe is granted sudo permission with password, John will be prompted to provide his password, like this.
[john.doe@server1 ~]# sudo reboot
Password for john.doe: ******
If John Doe is granted sudo permission with the NOPASSWD option, John will not be prompted to provide his password and the system will reboot.
[john.doe@server1 ~]# sudo reboot
Let's say john.doe attempts to reboot server1 using the shell module and sudo.
---
- hosts: all
tasks:
- name: "reboot using sudo"
shell: "sudo reboot"
Assuming the following option is commented out in ansible.cfg or set to true . . .
# command_warnings = False
. . . and you are not using the warn parameter, like this . . .
- name: "reboot using sudo"
shell: "sudo reboot"
warn: "false"
Invoking the play should return the following warning.
[WARNING]: Consider using 'become', 'become_method', and 'become_user' rather than running sudo
As the warning suggests, "become" should be used. There are different ways to use "become":
- Use the become command line flags - this will take precendence over all other approaches
- Use the become parameters in a playbook
- Use the become connection variables
- Use the become directives in ansible.cfg
Did you find this article helpful?
If so, consider buying me a coffee over at