Harden matching running containers by "command" in the Docker module

Before this patch:

  - Command was matched if 'Command' field of docker-py
    representation of Docker container ends with 'command' passed
    to Ansible docker module by user.
  - That can give false positives and false negatives.
  - For example:
      a) If 'command' was set up with more than one spaces,
         like 'command=sleep  123', it would be never matched again
         with a container(s) launched by this task.
         Because after launching, command would be normalized and
         appear, in docker-py API call, just as 'sleep 123' - with one
         space. This is false negative case.
      b) If 'entrypoint + command = command', for example
         'sleep + 123 = sleep 123', module would give false positive
         match.

This patch fixes it, by making matching more explicit - against
'Config'->Cmd' field of 'docker inspect' output, provided by docker-py
API and with proper normalization of user input by splitting it to
tokens with 'shlex.split()'.
This commit is contained in:
Andrew Pashkin 2015-10-02 00:44:52 +03:00 committed by Matt Clay
parent 369fe78c60
commit 8342397427

View file

@ -1389,8 +1389,8 @@ class DockerManager(object):
""" """
command = self.module.params.get('command') command = self.module.params.get('command')
if command: if command is not None:
command = command.strip() command = shlex.split(command)
name = self.module.params.get('name') name = self.module.params.get('name')
if name and not name.startswith('/'): if name and not name.startswith('/'):
name = '/' + name name = '/' + name
@ -1417,13 +1417,10 @@ class DockerManager(object):
details = _docker_id_quirk(details) details = _docker_id_quirk(details)
running_image = normalize_image(details['Config']['Image']) running_image = normalize_image(details['Config']['Image'])
running_command = container['Command'].strip()
image_matches = running_image in repo_tags image_matches = running_image in repo_tags
# if a container has an entrypoint, `command` will actually equal command_matches = command == details['Config']['Cmd']
# '{} {}'.format(entrypoint, command)
command_matches = (not command or running_command.endswith(command))
matches = image_matches and command_matches matches = image_matches and command_matches