How to switch a user per task or set of tasks?
A recurring theme that's in my ansible playbooks is that I often must execute a command with sudo privileges (sudo: yes
) because I'd like to do it for a certain user. Ideally I'd much rather use sudo to switch to that user and execute the commands normally. Because then I won't have to do my usual post commands clean up such as chowning directories. Here's a snippet from one of my playbooks:
- name: checkout repo
git: repo=https://github.com/some/repo.git version=master dest={{ dst }}
sudo: yes
- name: change perms
file: dest={{ dst }} state=directory mode=0755 owner=some_user
sudo: yes
Ideally I could run commands or sets of commands as a different user even if it requires sudo to su to that user.
With Ansible 1.9 or later
Ansible uses the become
, become_user
, and become_method
directives to achieve privilege escalation. You can apply them to an entire play or playbook, set them in an included playbook, or set them for a particular task.
- name: checkout repo
git: repo=https://github.com/some/repo.git version=master dest={{ dst }}
become: yes
become_user: some_user
You can use become_with
to specify how the privilege escalation is achieved, the default being sudo
.
The directive is in effect for the scope of the block in which it is used (examples).
See Hosts and Users for some additional examples and Become (Privilege Escalation) for more detailed documentation.
In addition to the task-scoped become
and become_user
directives, Ansible 1.9 added some new variables and command line options to set these values for the duration of a play in the absence of explicit directives:
-
Command line options for the equivalent
become
/become_user
directives. - Connection specific variables which can be set per host or group.
As of Ansible 2.0.2.0, the older sudo
/sudo_user
syntax described below still works, but the deprecation notice states, "This feature will be removed in a future release."
Previous syntax, deprecated as of Ansible 1.9 and scheduled for removal:
- name: checkout repo
git: repo=https://github.com/some/repo.git version=master dest={{ dst }}
sudo: yes
sudo_user: some_user
In Ansible 2.x, you can use the block
for group of tasks:
- block:
- name: checkout repo
git:
repo: https://github.com/some/repo.git
version: master
dest: "{{ dst }}"
- name: change perms
file:
dest: "{{ dst }}"
state: directory
mode: 0755
owner: some_user
become: yes
become_user: some user
In Ansible >1.4 you can actually specify a remote user at the task level which should allow you to login as that user and execute that command without resorting to sudo. If you can't login as that user then the sudo_user solution will work too.
---
- hosts: webservers
remote_user: root
tasks:
- name: test connection
ping:
remote_user: yourname
See http://docs.ansible.com/playbooks_intro.html#hosts-and-users
A solution is to use the include
statement with remote_user
var (describe there : http://docs.ansible.com/playbooks_roles.html) but it has to be done at playbook instead of task level.