From b8646991dbd069701fca2d219b322b45ab43ed5e Mon Sep 17 00:00:00 2001 From: James Cammarata Date: Thu, 13 Feb 2014 14:23:49 -0600 Subject: [PATCH] Filter out messages that match the pattern username:password@host This filtering is done in both the module invocation logging and in the regular verbose() logging output. Fixes #4087 --- lib/ansible/callbacks.py | 1 + lib/ansible/module_utils/basic.py | 19 +++++++++++++++-- lib/ansible/utils/__init__.py | 34 +++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/lib/ansible/callbacks.py b/lib/ansible/callbacks.py index ccee06ebd20..b56d1f90695 100644 --- a/lib/ansible/callbacks.py +++ b/lib/ansible/callbacks.py @@ -179,6 +179,7 @@ def vvvv(msg, host=None): return verbose(msg, host=host, caplevel=3) def verbose(msg, host=None, caplevel=2): + msg = utils.sanitize_output(msg) if utils.VERBOSITY > caplevel: if host is None: display(msg, color='blue') diff --git a/lib/ansible/module_utils/basic.py b/lib/ansible/module_utils/basic.py index 8f630b98972..82bca0c3b04 100644 --- a/lib/ansible/module_utils/basic.py +++ b/lib/ansible/module_utils/basic.py @@ -761,7 +761,13 @@ class AnsibleModule(object): # Sanitize possible password argument when logging. log_args = dict() passwd_keys = ['password', 'login_password'] - + + filter_re = [ + # filter out things like user:pass@foo/whatever + # and http://username:pass@wherever/foo + re.compile('^(?P.*:)(?P.*)(?P\@.*)$'), + ] + for param in self.params: canon = self.aliases.get(param, param) arg_opts = self.argument_spec.get(canon, {}) @@ -772,7 +778,16 @@ class AnsibleModule(object): elif param in passwd_keys: log_args[param] = 'NOT_LOGGING_PASSWORD' else: - log_args[param] = self.params[param] + found = False + for filter in filter_re: + m = filter.match(str(self.params[param])) + if m: + d = m.groupdict() + log_args[param] = d['before'] + "********" + d['after'] + found = True + break + if not found: + log_args[param] = self.params[param] module = 'ansible-%s' % os.path.basename(__file__) msg = '' diff --git a/lib/ansible/utils/__init__.py b/lib/ansible/utils/__init__.py index 49e9316d9ad..0f3f7f36e3b 100644 --- a/lib/ansible/utils/__init__.py +++ b/lib/ansible/utils/__init__.py @@ -623,6 +623,40 @@ def getch(): termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) return ch +def sanitize_output(str): + ''' strips private info out of a string ''' + + private_keys = ['password', 'login_password'] + + filter_re = [ + # filter out things like user:pass@foo/whatever + # and http://username:pass@wherever/foo + re.compile('^(?P.*:)(?P.*)(?P\@.*)$'), + ] + + parts = str.split() + output = '' + for part in parts: + try: + (k,v) = part.split('=', 1) + if k in private_keys: + output += " %s=VALUE_HIDDEN" % k + else: + found = False + for filter in filter_re: + m = filter.match(v) + if m: + d = m.groupdict() + output += " %s=%s" % (k, d['before'] + "********" + d['after']) + found = True + break + if not found: + output += " %s" % part + except: + output += " %s" % part + + return output.strip() + #################################################################### # option handling code for /usr/bin/ansible and ansible-playbook # below this line