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
...
A 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 command
- Use "become" to become a user that has permission to run the command
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. 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
...
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