mirror of
https://github.com/ansible-collections/community.docker.git
synced 2026-07-29 03:46:55 +00:00
Prevent RCE via inventory plugins (#815)
* Prevent RCE via inventory plugins. * Do not make ansible_connection unsafe. * Add test.
This commit is contained in:
@@ -96,6 +96,7 @@ from ansible.module_utils.common.text.converters import to_text
|
||||
from ansible.module_utils.common.process import get_bin_path
|
||||
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable, Cacheable
|
||||
from ansible.utils.display import Display
|
||||
from ansible.utils.unsafe_proxy import wrap_var as make_unsafe
|
||||
|
||||
from ansible_collections.community.library_inventory_filtering_v1.plugins.plugin_utils.inventory_filter import parse_filters, filter_host
|
||||
|
||||
@@ -178,7 +179,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
|
||||
def _inspect_docker_machine_host(self, node):
|
||||
try:
|
||||
inspect_lines = self._run_command(['inspect', self.node])
|
||||
inspect_lines = self._run_command(['inspect', node])
|
||||
except subprocess.CalledProcessError:
|
||||
return None
|
||||
|
||||
@@ -186,7 +187,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
|
||||
def _ip_addr_docker_machine_host(self, node):
|
||||
try:
|
||||
ip_addr = self._run_command(['ip', self.node])
|
||||
ip_addr = self._run_command(['ip', node])
|
||||
except subprocess.CalledProcessError:
|
||||
return None
|
||||
|
||||
@@ -208,13 +209,15 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
daemon_env = self.get_option('daemon_env')
|
||||
filters = parse_filters(self.get_option('filters'))
|
||||
try:
|
||||
for self.node in self._get_machine_names():
|
||||
self.node_attrs = self._inspect_docker_machine_host(self.node)
|
||||
if not self.node_attrs:
|
||||
for node in self._get_machine_names():
|
||||
node_attrs = self._inspect_docker_machine_host(node)
|
||||
if not node_attrs:
|
||||
continue
|
||||
|
||||
machine_name = self.node_attrs['Driver']['MachineName']
|
||||
if not filter_host(self, machine_name, self.node_attrs, filters):
|
||||
unsafe_node_attrs = make_unsafe(node_attrs)
|
||||
|
||||
machine_name = unsafe_node_attrs['Driver']['MachineName']
|
||||
if not filter_host(self, machine_name, unsafe_node_attrs, filters):
|
||||
continue
|
||||
|
||||
# query `docker-machine env` to obtain remote Docker daemon connection settings in the form of commands
|
||||
@@ -232,40 +235,40 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
# check for valid ip address from inspect output, else explicitly use ip command to find host ip address
|
||||
# this works around an issue seen with Google Compute Platform where the IP address was not available
|
||||
# via the 'inspect' subcommand but was via the 'ip' subcomannd.
|
||||
if self.node_attrs['Driver']['IPAddress']:
|
||||
ip_addr = self.node_attrs['Driver']['IPAddress']
|
||||
if unsafe_node_attrs['Driver']['IPAddress']:
|
||||
ip_addr = unsafe_node_attrs['Driver']['IPAddress']
|
||||
else:
|
||||
ip_addr = self._ip_addr_docker_machine_host(self.node)
|
||||
ip_addr = self._ip_addr_docker_machine_host(node)
|
||||
|
||||
# set standard Ansible remote host connection settings to details captured from `docker-machine`
|
||||
# see: https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html
|
||||
self.inventory.set_variable(machine_name, 'ansible_host', ip_addr)
|
||||
self.inventory.set_variable(machine_name, 'ansible_port', self.node_attrs['Driver']['SSHPort'])
|
||||
self.inventory.set_variable(machine_name, 'ansible_user', self.node_attrs['Driver']['SSHUser'])
|
||||
self.inventory.set_variable(machine_name, 'ansible_ssh_private_key_file', self.node_attrs['Driver']['SSHKeyPath'])
|
||||
self.inventory.set_variable(machine_name, 'ansible_host', make_unsafe(ip_addr))
|
||||
self.inventory.set_variable(machine_name, 'ansible_port', unsafe_node_attrs['Driver']['SSHPort'])
|
||||
self.inventory.set_variable(machine_name, 'ansible_user', unsafe_node_attrs['Driver']['SSHUser'])
|
||||
self.inventory.set_variable(machine_name, 'ansible_ssh_private_key_file', unsafe_node_attrs['Driver']['SSHKeyPath'])
|
||||
|
||||
# set variables based on Docker Machine tags
|
||||
tags = self.node_attrs['Driver'].get('Tags') or ''
|
||||
self.inventory.set_variable(machine_name, 'dm_tags', tags)
|
||||
tags = unsafe_node_attrs['Driver'].get('Tags') or ''
|
||||
self.inventory.set_variable(machine_name, 'dm_tags', make_unsafe(tags))
|
||||
|
||||
# set variables based on Docker Machine env variables
|
||||
for kv in env_var_tuples:
|
||||
self.inventory.set_variable(machine_name, 'dm_{0}'.format(kv[0]), kv[1])
|
||||
self.inventory.set_variable(machine_name, 'dm_{0}'.format(kv[0]), make_unsafe(kv[1]))
|
||||
|
||||
if self.get_option('verbose_output'):
|
||||
self.inventory.set_variable(machine_name, 'docker_machine_node_attributes', self.node_attrs)
|
||||
self.inventory.set_variable(machine_name, 'docker_machine_node_attributes', unsafe_node_attrs)
|
||||
|
||||
# Use constructed if applicable
|
||||
strict = self.get_option('strict')
|
||||
|
||||
# Composed variables
|
||||
self._set_composite_vars(self.get_option('compose'), self.node_attrs, machine_name, strict=strict)
|
||||
self._set_composite_vars(self.get_option('compose'), unsafe_node_attrs, machine_name, strict=strict)
|
||||
|
||||
# Complex groups based on jinja2 conditionals, hosts that meet the conditional are added to group
|
||||
self._add_host_to_composed_groups(self.get_option('groups'), self.node_attrs, machine_name, strict=strict)
|
||||
self._add_host_to_composed_groups(self.get_option('groups'), unsafe_node_attrs, machine_name, strict=strict)
|
||||
|
||||
# Create groups based on variable values and add the corresponding hosts to it
|
||||
self._add_host_to_keyed_groups(self.get_option('keyed_groups'), self.node_attrs, machine_name, strict=strict)
|
||||
self._add_host_to_keyed_groups(self.get_option('keyed_groups'), unsafe_node_attrs, machine_name, strict=strict)
|
||||
|
||||
except Exception as e:
|
||||
raise AnsibleError('Unable to fetch hosts from Docker Machine, this was the original exception: %s' %
|
||||
|
||||
Reference in New Issue
Block a user