summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHervé Beraud <hberaud@redhat.com>2021-11-03 17:16:50 +0100
committerDaniel Bengtsson <dbengt@redhat.com>2022-02-04 11:14:45 +0100
commit473f300b07641d79d5253208a4058e773857bec5 (patch)
tree7d47dad8c39dc3647d395cd0aa0a7e4763fd56f5
parented7c5780d3ad598f266a962e750d9b1e364aaba4 (diff)
downloadoslo-utils-473f300b07641d79d5253208a4058e773857bec5.tar.gz
Fix regex used to mask password
Some use cases are poorly handled by the regex used to mask password. Indeed when the password contains quotes or double quotes in the middle such as `pass"word`, the mask_password method will return `***"word`. For more details please see https://bugs.launchpad.net/oslo.utils/+bug/1949623 Closes-Bug: #1949623 Change-Id: I941750b4d49d2d75f0831b24d6dd17f4040f70a2 (cherry picked from commit 6e17ae1f7959c64dfd20a5f67edf422e702426aa) (cherry picked from commit 5ce8a7f0f8ecec7a85a23ec3d7a7fb1cad14ceba) (cherry picked from commit 143d3fbfa1e04778884de5acc08fa6f7fdabb265) (cherry picked from commit 65aa4226d4bf286468da6df6759e364c1eb3e049) (cherry picked from commit 5e9dfa3408a6fac7e870a9b86ee774b5fd71a595)
-rw-r--r--oslo_utils/strutils.py15
-rw-r--r--oslo_utils/tests/test_strutils.py14
-rw-r--r--releasenotes/notes/fix_mask_password_regex-c0661f95a23369a4.yaml7
3 files changed, 35 insertions, 1 deletions
diff --git a/oslo_utils/strutils.py b/oslo_utils/strutils.py
index b7ad5b8..760693b 100644
--- a/oslo_utils/strutils.py
+++ b/oslo_utils/strutils.py
@@ -74,6 +74,7 @@ _SANITIZE_KEYS = ['adminpass', 'admin_pass', 'password', 'admin_password',
# for XML and JSON automatically.
_SANITIZE_PATTERNS_2 = {}
_SANITIZE_PATTERNS_1 = {}
+_SANITIZE_PATTERNS_WILDCARD = {}
# NOTE(amrith): Some regular expressions have only one parameter, some
# have two parameters. Use different lists of patterns here.
@@ -89,6 +90,7 @@ _FORMAT_PATTERNS_2 = [r'(%(key)s[0-9]*\s*[=]\s*[\"\'])[^\"\']*([\"\'])',
r'([\'"][^\'"]*%(key)s[0-9]*[\'"]\s*,\s*\'--?[A-z]+'
'\'\s*,\s*u?[\'"])[^\"\']*([\'"])',
r'(%(key)s[0-9]*\s*--?[A-z]+\s*)\S+(\s*)']
+_FORMAT_PATTERNS_WILDCARD = [r'([\'\"][^\"\']*%(key)s[0-9]*[\'\"]\s*:\s*u?[\'\"].*[\'\"])[^\"\']*([\'\"])'] # noqa: E501
# NOTE(dhellmann): Keep a separate list of patterns by key so we only
# need to apply the substitutions for keys we find using a quick "in"
@@ -96,6 +98,7 @@ _FORMAT_PATTERNS_2 = [r'(%(key)s[0-9]*\s*[=]\s*[\"\'])[^\"\']*([\"\'])',
for key in _SANITIZE_KEYS:
_SANITIZE_PATTERNS_1[key] = []
_SANITIZE_PATTERNS_2[key] = []
+ _SANITIZE_PATTERNS_WILDCARD[key] = []
for pattern in _FORMAT_PATTERNS_2:
reg_ex = re.compile(pattern % {'key': key}, re.DOTALL | re.IGNORECASE)
@@ -105,6 +108,10 @@ for key in _SANITIZE_KEYS:
reg_ex = re.compile(pattern % {'key': key}, re.DOTALL | re.IGNORECASE)
_SANITIZE_PATTERNS_1[key].append(reg_ex)
+ for pattern in _FORMAT_PATTERNS_WILDCARD:
+ reg_ex = re.compile(pattern % {'key': key}, re.DOTALL | re.IGNORECASE)
+ _SANITIZE_PATTERNS_WILDCARD[key].append(reg_ex)
+
def int_from_bool_as_string(subject):
"""Interpret a string as a boolean and return either 1 or 0.
@@ -332,6 +339,7 @@ def mask_password(message, secret="***"): # nosec
substitute1 = r'\g<1>' + secret
substitute2 = r'\g<1>' + secret + r'\g<2>'
+ substitute_wildcard = r'\g<1>'
# NOTE(ldbragst): Check to see if anything in message contains any key
# specified in _SANITIZE_KEYS, if not then just return the message since
@@ -342,7 +350,12 @@ def mask_password(message, secret="***"): # nosec
message = re.sub(pattern, substitute2, message)
for pattern in _SANITIZE_PATTERNS_1[key]:
message = re.sub(pattern, substitute1, message)
-
+ # NOTE(hberaud): Those case are poorly handled by previous
+ # patterns. They are passwords with quotes or double quotes.
+ # They also needs a different way to substitute group this is why
+ # they aren't fix in the pattern 1 or 2.
+ for pattern in _SANITIZE_PATTERNS_WILDCARD[key]:
+ message = re.sub(pattern, substitute_wildcard, message)
return message
diff --git a/oslo_utils/tests/test_strutils.py b/oslo_utils/tests/test_strutils.py
index 25e974c..f9fdf5e 100644
--- a/oslo_utils/tests/test_strutils.py
+++ b/oslo_utils/tests/test_strutils.py
@@ -617,11 +617,20 @@ class MaskPasswordTestCase(test_base.BaseTestCase):
expected = 'test = "param1" : "value"'
self.assertEqual(expected, strutils.mask_password(payload))
+ payload = 'test = "original_password" : "aaaaa"aaaa"'
+ expected = 'test = "original_password" : "***"'
+ self.assertEqual(expected, strutils.mask_password(payload))
+
payload = """{'adminPass':'TL0EfN33'}"""
payload = six.text_type(payload)
expected = """{'adminPass':'***'}"""
self.assertEqual(expected, strutils.mask_password(payload))
+ payload = """{'adminPass':'TL0E'fN33'}"""
+ payload = str(payload)
+ expected = """{'adminPass':'***'}"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+
payload = """{'token':'mytoken'}"""
payload = six.text_type(payload)
expected = """{'token':'***'}"""
@@ -697,6 +706,11 @@ class MaskDictionaryPasswordTestCase(test_base.BaseTestCase):
self.assertEqual(expected,
strutils.mask_dict_password(payload))
+ payload = {'password': 'TL0Ef"N33'}
+ expected = {'password': '***'}
+ self.assertEqual(expected,
+ strutils.mask_dict_password(payload))
+
payload = {'user': 'admin', 'password': 'TL0EfN33'}
expected = {'user': 'admin', 'password': '***'}
self.assertEqual(expected,
diff --git a/releasenotes/notes/fix_mask_password_regex-c0661f95a23369a4.yaml b/releasenotes/notes/fix_mask_password_regex-c0661f95a23369a4.yaml
new file mode 100644
index 0000000..e7bc558
--- /dev/null
+++ b/releasenotes/notes/fix_mask_password_regex-c0661f95a23369a4.yaml
@@ -0,0 +1,7 @@
+---
+fixes:
+ - |
+ Fix regex used to mask password. The ``strutils.mask_password``
+ function will now correctly handle passwords that contain
+ single or double quotes. Previously, only the characters before the
+ quote were masked.