When parsing json from untrusted sources, remove templating tags
This commit is contained in:
parent
eeb597360e
commit
8ed6350e65
5 changed files with 41 additions and 19 deletions
|
@ -49,7 +49,7 @@ class InventoryScript(object):
|
|||
def _parse(self, err):
|
||||
|
||||
all_hosts = {}
|
||||
self.raw = utils.parse_json(self.data)
|
||||
self.raw = utils.parse_json(self.data, from_remote=True)
|
||||
all = Group('all')
|
||||
groups = dict(all=all)
|
||||
group = None
|
||||
|
|
|
@ -497,7 +497,7 @@ class Runner(object):
|
|||
cmd2 = conn.shell.remove(tmp, recurse=True)
|
||||
self._low_level_exec_command(conn, cmd2, tmp, sudoable=False)
|
||||
|
||||
data = utils.parse_json(res['stdout'])
|
||||
data = utils.parse_json(res['stdout'], from_remote=True)
|
||||
if 'parsed' in data and data['parsed'] == False:
|
||||
data['msg'] += res['stderr']
|
||||
return ReturnData(conn=conn, result=data)
|
||||
|
|
|
@ -43,8 +43,7 @@ class ReturnData(object):
|
|||
self.diff = diff
|
||||
|
||||
if type(self.result) in [ str, unicode ]:
|
||||
self.result = utils.parse_json(self.result)
|
||||
|
||||
self.result = utils.parse_json(self.result, from_remote=True)
|
||||
|
||||
if self.host is None:
|
||||
raise Exception("host not set")
|
||||
|
|
|
@ -313,7 +313,38 @@ def json_loads(data):
|
|||
|
||||
return json.loads(data)
|
||||
|
||||
def parse_json(raw_data):
|
||||
def _clean_data(orig_data):
|
||||
''' remove template tags from a string '''
|
||||
data = orig_data
|
||||
if isinstance(orig_data, basestring):
|
||||
for pattern,replacement in (('{{','{#'), ('}}','#}'), ('{%','{#'), ('%}','#}')):
|
||||
data = data.replace(pattern, replacement)
|
||||
return data
|
||||
|
||||
def _clean_data_struct(orig_data):
|
||||
'''
|
||||
walk a complex data structure, and use _clean_data() to
|
||||
remove any template tags that may exist
|
||||
'''
|
||||
if isinstance(orig_data, dict):
|
||||
data = orig_data.copy()
|
||||
for key in data:
|
||||
new_key = _clean_data_struct(key)
|
||||
new_val = _clean_data_struct(data[key])
|
||||
if key != new_key:
|
||||
del data[key]
|
||||
data[new_key] = new_val
|
||||
elif isinstance(orig_data, list):
|
||||
data = orig_data[:]
|
||||
for i in range(0, len(data)):
|
||||
data[i] = _clean_data_struct(data[i])
|
||||
elif isinstance(orig_data, basestring):
|
||||
data = _clean_data(orig_data)
|
||||
else:
|
||||
data = orig_data
|
||||
return data
|
||||
|
||||
def parse_json(raw_data, from_remote=False):
|
||||
''' this version for module return data only '''
|
||||
|
||||
orig_data = raw_data
|
||||
|
@ -322,7 +353,7 @@ def parse_json(raw_data):
|
|||
data = filter_leading_non_json_lines(raw_data)
|
||||
|
||||
try:
|
||||
return json.loads(data)
|
||||
results = json.loads(data)
|
||||
except:
|
||||
# not JSON, but try "Baby JSON" which allows many of our modules to not
|
||||
# require JSON and makes writing modules in bash much simpler
|
||||
|
@ -332,7 +363,6 @@ def parse_json(raw_data):
|
|||
except:
|
||||
print "failed to parse json: "+ data
|
||||
raise
|
||||
|
||||
for t in tokens:
|
||||
if "=" not in t:
|
||||
raise errors.AnsibleError("failed to parse: %s" % orig_data)
|
||||
|
@ -347,6 +377,10 @@ def parse_json(raw_data):
|
|||
results[key] = value
|
||||
if len(results.keys()) == 0:
|
||||
return { "failed" : True, "parsed" : False, "msg" : orig_data }
|
||||
|
||||
if from_remote:
|
||||
results = _clean_data_struct(results)
|
||||
|
||||
return results
|
||||
|
||||
def smush_braces(data):
|
||||
|
|
|
@ -80,7 +80,6 @@ class Flags:
|
|||
|
||||
FILTER_PLUGINS = None
|
||||
_LISTRE = re.compile(r"(\w+)\[(\d+)\]")
|
||||
JINJA2_OVERRIDE='#jinja2:'
|
||||
|
||||
def lookup(name, *args, **kwargs):
|
||||
from ansible import utils
|
||||
|
@ -231,16 +230,6 @@ def template_from_file(basedir, path, vars, vault_password=None):
|
|||
except:
|
||||
raise errors.AnsibleError("unable to read %s" % realpath)
|
||||
|
||||
|
||||
# Get jinja env overrides from template
|
||||
if data.startswith(JINJA2_OVERRIDE):
|
||||
eol = data.find('\n')
|
||||
line = data[len(JINJA2_OVERRIDE):eol]
|
||||
data = data[eol+1:]
|
||||
for pair in line.split(','):
|
||||
(key,val) = pair.split(':')
|
||||
setattr(environment,key.strip(),ast.literal_eval(val.strip()))
|
||||
|
||||
environment.template_class = J2Template
|
||||
try:
|
||||
t = environment.from_string(data)
|
||||
|
|
Loading…
Reference in a new issue