AnsibleXIX · Privilege EscalationPrivilege escalation
Escalation methods and where they apply
What you'll learn
- List the become plugins shipped in ansible-core and name where the others come from
- Choose an escalation method appropriate to a platform and account model
- Set become_method per group in inventory rather than globally
- Explain why su behaves differently from sudo for a non-interactive run
- Recognise the plugins that belong to platforms other than a Linux server fleet
Prerequisites
Verified against ansible-core 2.21.x · ansible (community package) 14.x · Python (controller) 3.12+ · ansible-lint 26.x · Molecule 26.x · Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL / Rocky / AlmaLinux 9.x · 2026-08-11
Lists of Ansible escalation methods circulate freely — sudo, su,
pbrun, pfexec, doas, dzdo, ksu, machinectl, runas,
enable — and they are misleading in a way that costs a debugging
session. Most of those are not in ansible-core.
Ask the installation:
$ ansible-doc -t become -lansible.builtin.runas Run As user
ansible.builtin.su Substitute User
ansible.builtin.sudo Substitute User DOEverything else lives in a collection. doas, dzdo, ksu,
machinectl, pbrun, pfexec, pmrun, sesu and sudosu come from
community.general; enable, for network devices, comes from
ansible.netcommon.
What is relevant to a Linux server fleet
| Plugin | Collection | Relevance to a Linux fleet |
|---|---|---|
sudo | ansible.builtin | The default and the right answer in almost every case |
su | ansible.builtin | Hosts with no sudo, or a policy that forbids it |
doas | community.general | OpenBSD, and Linux hosts that deliberately chose doas over sudo |
machinectl | community.general | When a full pam_systemd session is genuinely required |
dzdo | community.general | Centrify-managed estates |
pbrun, pmrun | community.general | BeyondTrust PowerBroker estates |
ksu | community.general | Kerberos-authenticated escalation |
sesu | community.general | CA Privileged Access Manager |
sudosu | community.general | sudo su - as one step, for policies that mandate it |
pfexec | community.general | Solaris RBAC — not a Linux plugin |
runas | ansible.builtin | Windows only |
enable | ansible.netcommon | Network devices, covered in Part XLII |
Three of those rows exist because a commercial privilege-management product owns escalation in that estate. If you are in one, the product’s rules — not sudoers — are where least privilege is expressed, and the Ansible side is just naming the method. The design questions in lesson 4 still apply; the file you edit is different.
su is not sudo with a different name
su is the fallback when sudo is absent, and it behaves differently in
three ways that matter for unattended runs.
It always requires a password. sudo can be configured NOPASSWD
for a specific rule. su authenticates as the target user, so it wants
that user’s password, every time. For root, that means the root password
is in your automation — which is a considerably worse secret to hold
than a service account’s, because it is the same on every host in most
estates.
It cannot be restricted. There is no su-equivalent of a sudoers
rule listing permitted commands. Access to su as root is total access.
Any least-privilege design that depends on restricting what the
automation may do is unavailable.
Prompt detection is fragile. The plugin matches the password prompt
by string, and ansible-doc -t become su documents a prompt_l10n
option for exactly this reason: a localised system prints a translated
prompt the built-in list does not match, and the run fails with a
timeout rather than an authentication error. The option’s own note warns
against adding a colon to custom entries, because the plugin appends
one.
$ ansible-doc -t become su | grep -A2 'become_flags\\|become_user User' become_flags Options to pass to su
default: ''
become_user User you 'become' to execute the task
default: rootSetting the method where it belongs
become_method can be set in ansible.cfg, on the command line, as a
play or task keyword, or as ansible_become_method in inventory.
Inventory is usually right, because the correct method is a property of
the host, not of the playbook.
# inventories/prod/group_vars/all.yml
ansible_become_method: sudo
ansible_become_user: root
# inventories/prod/group_vars/openbsd_hosts.yml
ansible_become_method: community.general.doas
# inventories/prod/group_vars/centrify_estate.yml
ansible_become_method: community.general.dzdoTwo habits make this hold up.
Use the fully qualified name for anything outside ansible.builtin.
become_method: doas resolves through the collection search path and
depends on what happens to be installed; community.general.doas names
exactly one plugin. The same argument as for module FQCNs, for the same
reason.
Do not set it globally in ansible.cfg for a mixed estate. A global
setting is invisible at the point of use and wrong for some subset of
hosts. Inventory keeps the exception next to the hosts it applies to,
and ansible-inventory --host will show you the effective value.
ansible-inventory -i inventories/prod --host bsd01.example.com \
| grep -E 'ansible_become'When the method choice is really an environment problem
The become documentation notes that escalated processes may not have
access to environment variables set by pam_systemd, and offers
become_method: machinectl as the way to force a new systemd session.
That is worth understanding rather than copying. sudo by default does
not create a login session in the systemd sense, so XDG_RUNTIME_DIR
and the user session bus are absent. Anything that needs them — a
user-level systemd unit, systemctl --user, some desktop or container
tooling — fails with an error about a missing bus rather than about
permissions.
Switching the whole fleet’s become method to fix one task is
disproportionate. The alternatives, in order of preference: use the
system service manager rather than the user one; set the variables
explicitly on the task with environment:; or set the method on that
single task with become_method rather than for the play.
Knowledge check
Knowledge check · 4 questions
Q1. Which become plugins ship with ansible-core 2.21?
Q2. Which are genuine operational differences between su and sudo for unattended automation? Select all that apply.
Q3. Setting become_method: doas in a playbook is safe on any controller, because ansible-playbook --syntax-check will report the missing plugin before the run.
Q4. A mixed estate has Linux hosts using sudo and a handful of OpenBSD hosts using doas. Where does the method belong?
Passing score: 75%. Answers are checked in this browser.