dumping host_vars - how do I filter out sensitive data?

I’m using the following jinja2 code to dump my hostvars for diagnostics {{ hostvars | to_nice_json }}

I would like to pre-filter this dump to exclude sensitive data. I can manage a list of sensitive values but is there a way to scan the hostvars dict and blank out some variables?

I don’t think there’s a quick solution for this. I believe you’d need to write your own filter plugin: http://docs.ansible.com/developing_plugins.html#filter-plugins

Thanks Dan,
I like Ansible/Jinja2’s interfaces for writing custom filters. Easy work. As an example for others my code is below with some helpful references. Note: I’m a very junior Pythonian.

http://docs.ansible.com/developing_plugins.html#filter-plugins

plugins can be shipped in a subdirectory relative to a top-level playbook, in folders named the same as indicated above. +1

https://docs.python.org/2/library/copy.html - deepcopy

http://stackoverflow.com/questions/3232943/update-value-of-a-nested-dictionary-of-varying-depth

ansible-python-jinja2 filter that removes sensitive data

INPUT: dictionary - ie. Ansible’s hostvars dictionary that may contain passwords

OUTPUT: A filtered copy of dict with

sensitive data removed

METHOD: Make a copy of the incoming dictionary (don’t touch the source)

Recursively iterate through the whole tree

Replaces sensitive values with the string “hidden by remove_sensitive_data jinja2 filter”

Warning: I don’t think Lists are handled properly

The purpose is updating named strings so this is OK for now

Code Quality: poor - learning python and this is a spike

Sensitive data fields are hard coded

Future: The sensitive field list should be pulled from Ansible’s dict

import re
import collections
import yaml
import copy

Recursive traverse of the dict

Calling update_callback() for each element

and stuffing the results back into the dict

def update_dict(d, update_callback):

Check that d is a dictionary

if isinstance(d, collections.Mapping):
for k, v in d.items():
if isinstance(v, collections.Mapping):
updated = update_dict(v, update_callback)
d[k] = updated
#print “D: %s” % k
else:
d[k] = update_callback(k, v)
#print “V: %s” % k

always return d whether it was modified or not

return d

This is the callback func that filters/not each value in the dict

def rm_sensitive_data(key, value):
srchObj = re.search( r’ssh_pass’, key )
if( srchObj ):
return ‘value hidden by remove_sensitive_data jinja2 filter’
else:
return value

def remove_sensitive_data(arg):

Don’t change the original

mycopy = copy.deepcopy(arg)
update_dict( mycopy, rm_sensitive_data )
return mycopy

class FilterModule(object):
def filters(self):
return {‘remove_sensitive_data’: remove_sensitive_data}