Ansible Privilege Escalation and Variable Precedence
When orchestrating bare-metal nodes, managing execution environments and user privileges is critical. This document details the mechanics of Privilege Escalation within Ansible and how Variable Precedence (Ansible) can lead to subtle bugs.
Variable Precedence and the remote_user Trap
Ansible allows you to define variables in multiple places: playbooks, inventory files, command-line arguments, etc. However, understanding the order of precedence is vital to avoid silent failures.
The Apt Lock Bug
A common scenario during initial node provisioning:
- You define the standard SSH user in the inventory file:
- You attempt to force a specific playbook to run entirely as root:
Symptom: Tasks that require root access (like apt install) fail with Failed to lock apt for exclusive operation.
Cause: Inventory variables (ansible_user) have a higher precedence than playbook variables (remote_user). Ansible silently ignores the remote_user: root directive and logs in as leva. Because leva does not yet have sudo privileges on a raw installation, the apt module executes as a standard user and fails.
Solution: Do not mix ansible_user and remote_user to attempt privilege escalation. If you need root execution, use Ansible's native become system.
The become System: su vs sudo
Ansible relies heavily on sudo for privilege escalation. However, fresh minimal OS installations (like Debian netinst) do not include the sudo package by default.
To bootstrap sudo itself, you must use an alternative become_method, such as su.
Escalating with su
- name: Install sudo
apt:
name: sudo
state: present
become: true
become_method: su
become_user: root
The Missing $PATH Gotcha
When Ansible escalates via become_method: su, it executes a non-login shell. Unlike su -, a non-login shell does not execute the root user's profile scripts (/etc/profile, .bashrc).
Consequently, system paths like /usr/sbin/ and /sbin/ are omitted from the $PATH environment variable.
Symptom:
Solution:
When executing commands via raw su that rely on system binaries, you must provide the absolute path.