diff --git a/oslo_utils/strutils.py b/oslo_utils/strutils.py index ae4d00d..10ebac0 100644 --- a/oslo_utils/strutils.py +++ b/oslo_utils/strutils.py @@ -17,6 +17,7 @@ System-level utilities and helper functions. """ +import copy import math import re import unicodedata @@ -353,7 +354,7 @@ def mask_dict_password(dictionary, secret="***"): # nosec raise TypeError("Expected a dictionary, got %s instead." % type(dictionary)) - out = {} + out = copy.deepcopy(dictionary) for k, v in dictionary.items(): if isinstance(v, dict): diff --git a/oslo_utils/tests/test_strutils.py b/oslo_utils/tests/test_strutils.py index 0560d08..138ff64 100644 --- a/oslo_utils/tests/test_strutils.py +++ b/oslo_utils/tests/test_strutils.py @@ -15,6 +15,7 @@ # License for the specific language governing permissions and limitations # under the License. +import copy import math import mock @@ -640,6 +641,29 @@ class MaskDictionaryPasswordTestCase(test_base.BaseTestCase): self.assertEqual(expected, strutils.mask_dict_password(payload)) + def test_other_non_str_values(self): + payload = {'password': 'DK0PK1AK3', 'bool': True, + 'dict': {'cat': 'meow', 'password': "*aa38skdjf"}, + 'float': 0.1, 'int': 123, 'list': [1, 2], 'none': None, + 'str': 'foo'} + expected = {'password': '***', 'bool': True, + 'dict': {'cat': 'meow', 'password': '***'}, + 'float': 0.1, 'int': 123, 'list': [1, 2], 'none': None, + 'str': 'foo'} + self.assertEqual(expected, + strutils.mask_dict_password(payload)) + + def test_argument_untouched(self): + """Make sure that the argument passed in is not modified""" + payload = {'password': 'DK0PK1AK3', 'bool': True, + 'dict': {'cat': 'meow', 'password': "*aa38skdjf"}, + 'float': 0.1, 'int': 123, 'list': [1, 2], 'none': None, + 'str': 'foo'} + pristine = copy.deepcopy(payload) + # Send the payload into the function, to see if it gets modified + strutils.mask_dict_password(payload) + self.assertEqual(pristine, payload) + class IsIntLikeTestCase(test_base.BaseTestCase): def test_is_int_like_true(self):