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

Discovering how the sausage is made…

Discovering how the sausage is made…

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 .