dumping host_vars - how do I filter out sensitive data?

89 views
Skip to first unread message

Larry Fast

unread,
Mar 5, 2015, 10:23:58 AM3/5/15
to ansible...@googlegroups.com
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?

Dan Vaida

unread,
Mar 6, 2015, 4:39:13 AM3/6/15
to ansible...@googlegroups.com
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

Larry Fast

unread,
Mar 9, 2015, 3:13:07 PM3/9/15
to ansible...@googlegroups.com
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.

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


# 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}


Reply all
Reply to author
Forward
0 new messages