Adding support for privilege escalation to Ansible’s docker connection driver
Update 2019-05-09 Pull request
#55816
has merged, so you can now use sudo
with the docker
connection driver even when sudo
is configured to require a password.
I often use Docker to test out Ansible playbooks. While normally that works great, I recently ran into an unexpected problem with privilege escalation. Given a simple playbook like this:
---
- hosts: all
gather_facts: false
become: true
tasks:
- ping:
And an inventory like this:
all:
vars:
ansible_user: example
ansible_connection: docker
hosts:
server1:
ansible_host: sudostuff_server1_1
server2:
ansible_host: sudostuff_server2_1
server3:
ansible_host: sudostuff_server3_1
And containers with sudo
configured to require a password, Ansible would fail like this (note that I’ve configured Ansible to use the debug
plugin for stdout_callback
):
fatal: [server1]: FAILED! => {
"changed": false,
"rc": 1
}
MSG:
MODULE FAILURE
See stdout/stderr for the exact error
MODULE_STDERR:
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
#1) Respect the privacy of others.
#2) Think before you type.
#3) With great power comes great responsibility.
[sudo via ansible, key=rzrfiifcqoggklmehivtcrrlnnbphwbp] password:
In the above output, you’ll note that there are no actual errors, but unexpectedly we’re seeing the privilege escalation prompt show up in the stderr
of the command. A quick search revealed bugs #31759 and #53385, both of which confirm that privilege escalation simply doesn’t work using the docker
connection plugin.
Use the source, Luke⌗
Looking at the source, I was surprised: while Ansible has individual plugins for different privilege escalation methods, it is entirely up to the individual connection plugin to implement the logic necessary to make use of these mechanisms. I had expected privilege escalation support to be implemented in the base connection plugin (ConnectionBase
in lib/ansible/plugins/connection/__init__.py
), but it’s not. So while the ssh plugin has a fairly complex set of logic for handing the become
prompt, and the local plugin had a relatively simple solution, the docker
connection had none.
Fortunately, in many ways the docker
plugin is almost identical to the local
plugin, which means that rather than doing actual work I was able to largely cut-and-paste the privilege escalation support from the local
plugin into the docker
plugin. You can find this work in pull request
#55816
.