From 05246f7db8661f250e17b3587b92bdded15982e4 Mon Sep 17 00:00:00 2001 From: Brian Coca Date: Thu, 15 Nov 2018 16:29:40 -0500 Subject: [PATCH] inventory now errors for invalid group/host names (#45499) * inventory now errors for invalid group/host names also made yaml inventory slightly smarte fixes #45493 * add some 'YAML protection' to ini plugin * better msg * avoid ranges as positive match * pepe * expand inherited instead of total override --- lib/ansible/inventory/data.py | 6 +++++- lib/ansible/plugins/inventory/ini.py | 18 +++++++++++++++++ lib/ansible/plugins/inventory/yaml.py | 29 ++++++++++++++++----------- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/lib/ansible/inventory/data.py b/lib/ansible/inventory/data.py index 640a059f751..5f3ca8993fb 100644 --- a/lib/ansible/inventory/data.py +++ b/lib/ansible/inventory/data.py @@ -25,7 +25,7 @@ from ansible import constants as C from ansible.errors import AnsibleError from ansible.inventory.group import Group from ansible.inventory.host import Host -from ansible.module_utils.six import iteritems +from ansible.module_utils.six import iteritems, string_types from ansible.utils.vars import combine_vars from ansible.utils.path import basedir @@ -162,6 +162,8 @@ class InventoryData(object): ''' adds a group to inventory if not there already ''' if group: + if not isinstance(group, string_types): + raise AnsibleError("Invalid group name supplied, expected a string but got %s for %s" % (type(group), group)) if group not in self.groups: g = Group(group) self.groups[group] = g @@ -187,6 +189,8 @@ class InventoryData(object): ''' adds a host to inventory and possibly a group if not there already ''' if host: + if not isinstance(group, string_types): + raise AnsibleError("Invalid host name supplied, expected a string but got %s for %s" % (type(host), host)) g = None if group: if group in self.groups: diff --git a/lib/ansible/plugins/inventory/ini.py b/lib/ansible/plugins/inventory/ini.py index 8b63a18e65e..8c26f822d3f 100644 --- a/lib/ansible/plugins/inventory/ini.py +++ b/lib/ansible/plugins/inventory/ini.py @@ -315,6 +315,24 @@ class InventoryModule(BaseFileInventoryPlugin): return hostnames, port, variables + def _expand_hostpattern(self, hostpattern): + ''' + do some extra checks over normal processing + ''' + # specification? + + hostnames, port = super(InventoryModule, self)._expand_hostpattern(hostpattern) + + if hostpattern.strip().endswith(':') and port is None: + raise AnsibleParserError("Invalid host pattern '%s' supplied, ending in ':' is not allowed, this character is reserved to provide a port." % + hostpattern) + for pattern in hostnames: + # some YAML parsing prevention checks + if pattern.strip() == '---': + raise AnsibleParserError("Invalid host pattern '%s' supplied, '---' is normally a sign this is a YAML file." % hostpattern) + + return (hostnames, port) + @staticmethod def _parse_value(v): ''' diff --git a/lib/ansible/plugins/inventory/yaml.py b/lib/ansible/plugins/inventory/yaml.py index f4b66e1197a..6549d8e0912 100644 --- a/lib/ansible/plugins/inventory/yaml.py +++ b/lib/ansible/plugins/inventory/yaml.py @@ -60,12 +60,14 @@ all: # keys must be unique, i.e. only one 'hosts' per group import os -from ansible.errors import AnsibleParserError +from ansible.errors import AnsibleError, AnsibleParserError from ansible.module_utils.six import string_types -from ansible.module_utils._text import to_native +from ansible.module_utils._text import to_native, to_text from ansible.module_utils.common._collections_compat import MutableMapping from ansible.plugins.inventory import BaseFileInventoryPlugin +NoneType = type(None) + class InventoryModule(BaseFileInventoryPlugin): @@ -112,9 +114,12 @@ class InventoryModule(BaseFileInventoryPlugin): def _parse_group(self, group, group_data): - if isinstance(group_data, (MutableMapping, type(None))): + if isinstance(group_data, (MutableMapping, NoneType)): - self.inventory.add_group(group) + try: + self.inventory.add_group(group) + except AnsibleError as e: + raise AnsibleParserError("Unable to add group %s: %s" % (group, to_text(e))) if group_data is not None: # make sure they are dicts @@ -124,24 +129,24 @@ class InventoryModule(BaseFileInventoryPlugin): if isinstance(group_data[section], string_types): group_data[section] = {group_data[section]: None} - if not isinstance(group_data[section], (MutableMapping, type(None))): + if not isinstance(group_data[section], (MutableMapping, NoneType)): raise AnsibleParserError('Invalid "%s" entry for "%s" group, requires a dictionary, found "%s" instead.' % (section, group, type(group_data[section]))) for key in group_data: - if key == 'vars': - for var in group_data['vars']: - self.inventory.set_variable(group, var, group_data['vars'][var]) + if key == 'vars': + for var in group_data[key]: + self.inventory.set_variable(group, var, group_data[key][var]) elif key == 'children': - for subgroup in group_data['children']: - self._parse_group(subgroup, group_data['children'][subgroup]) + for subgroup in group_data[key]: + self._parse_group(subgroup, group_data[key][subgroup]) self.inventory.add_child(group, subgroup) elif key == 'hosts': - for host_pattern in group_data['hosts']: + for host_pattern in group_data[key]: hosts, port = self._parse_host(host_pattern) - self._populate_host_vars(hosts, group_data['hosts'][host_pattern] or {}, group, port) + self._populate_host_vars(hosts, group_data[key][host_pattern] or {}, group, port) else: self.display.warning('Skipping unexpected key (%s) in group (%s), only "vars", "children" and "hosts" are valid' % (key, group))