1# -*- coding: utf-8 -*- 2# (c) 2015, Toshio Kuratomi <tkuratomi@ansible.com> 3# 4# This file is part of Ansible 5# 6# Ansible is free software: you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation, either version 3 of the License, or 9# (at your option) any later version. 10# 11# Ansible is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with Ansible. If not, see <http://www.gnu.org/licenses/>. 18 19# Make coding more python3-ish 20from __future__ import (absolute_import, division, print_function) 21__metaclass__ = type 22 23from units.compat import unittest 24from ansible.module_utils.basic import heuristic_log_sanitize 25 26 27class TestHeuristicLogSanitize(unittest.TestCase): 28 def setUp(self): 29 self.URL_SECRET = 'http://username:pas:word@foo.com/data' 30 self.SSH_SECRET = 'username:pas:word@foo.com/data' 31 self.clean_data = repr(self._gen_data(3, True, True, 'no_secret_here')) 32 self.url_data = repr(self._gen_data(3, True, True, self.URL_SECRET)) 33 self.ssh_data = repr(self._gen_data(3, True, True, self.SSH_SECRET)) 34 35 def _gen_data(self, records, per_rec, top_level, secret_text): 36 hostvars = {'hostvars': {}} 37 for i in range(1, records, 1): 38 host_facts = { 39 'host%s' % i: { 40 'pstack': { 41 'running': '875.1', 42 'symlinked': '880.0', 43 'tars': [], 44 'versions': ['885.0'] 45 }, 46 } 47 } 48 if per_rec: 49 host_facts['host%s' % i]['secret'] = secret_text 50 hostvars['hostvars'].update(host_facts) 51 if top_level: 52 hostvars['secret'] = secret_text 53 return hostvars 54 55 def test_did_not_hide_too_much(self): 56 self.assertEqual(heuristic_log_sanitize(self.clean_data), self.clean_data) 57 58 def test_hides_url_secrets(self): 59 url_output = heuristic_log_sanitize(self.url_data) 60 # Basic functionality: Successfully hid the password 61 self.assertNotIn('pas:word', url_output) 62 63 # Slightly more advanced, we hid all of the password despite the ":" 64 self.assertNotIn('pas', url_output) 65 66 # In this implementation we replace the password with 8 "*" which is 67 # also the length of our password. The url fields should be able to 68 # accurately detect where the password ends so the length should be 69 # the same: 70 self.assertEqual(len(url_output), len(self.url_data)) 71 72 def test_hides_ssh_secrets(self): 73 ssh_output = heuristic_log_sanitize(self.ssh_data) 74 self.assertNotIn('pas:word', ssh_output) 75 76 # Slightly more advanced, we hid all of the password despite the ":" 77 self.assertNotIn('pas', ssh_output) 78 79 # ssh checking is harder as the heuristic is overzealous in many 80 # cases. Since the input will have at least one ":" present before 81 # the password we can tell some things about the beginning and end of 82 # the data, though: 83 self.assertTrue(ssh_output.startswith("{'")) 84 self.assertTrue(ssh_output.endswith("}")) 85 self.assertIn(":********@foo.com/data'", ssh_output) 86 87 def test_hides_parameter_secrets(self): 88 output = heuristic_log_sanitize('token="secret", user="person", token_entry="test=secret"', frozenset(['secret'])) 89 self.assertNotIn('secret', output) 90