Version in base suite: 3.36.4-2 Base version: python-oslo.utils_3.36.4-2 Target version: python-oslo.utils_3.36.5-0+deb10u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/p/python-oslo.utils/python-oslo.utils_3.36.4-2.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/p/python-oslo.utils/python-oslo.utils_3.36.5-0+deb10u1.dsc .gitreview | 5 .zuul.yaml | 8 + debian/changelog | 8 + oslo_utils/strutils.py | 43 ++++--- oslo_utils/tests/test_strutils.py | 54 ++++++++++ releasenotes/notes/mask-dict-passwords-99357ffb7972fb0b.yaml | 9 + releasenotes/notes/mask-password-patterns-f41524069b8ae488.yaml | 8 + tox.ini | 2 8 files changed, 117 insertions(+), 20 deletions(-) diff -Nru python-oslo.utils-3.36.4/.gitreview python-oslo.utils-3.36.5/.gitreview --- python-oslo.utils-3.36.4/.gitreview 2018-07-18 03:43:01.000000000 +0000 +++ python-oslo.utils-3.36.5/.gitreview 2019-11-18 09:13:41.000000000 +0000 @@ -1,4 +1,5 @@ [gerrit] -host=review.openstack.org +host=review.opendev.org port=29418 -project=openstack/oslo.utils.git \ No newline at end of file +project=openstack/oslo.utils.git +defaultbranch=stable/rocky diff -Nru python-oslo.utils-3.36.4/.zuul.yaml python-oslo.utils-3.36.5/.zuul.yaml --- python-oslo.utils-3.36.4/.zuul.yaml 2018-07-18 03:43:01.000000000 +0000 +++ python-oslo.utils-3.36.5/.zuul.yaml 2019-11-18 09:13:41.000000000 +0000 @@ -5,3 +5,11 @@ gate: jobs: - openstack-tox-lower-constraints + templates: + - openstack-python-jobs + - openstack-python35-jobs + - publish-openstack-docs-pti + - check-requirements + - lib-forward-testing + - release-notes-jobs-python3 + - periodic-stable-jobs diff -Nru python-oslo.utils-3.36.4/debian/changelog python-oslo.utils-3.36.5/debian/changelog --- python-oslo.utils-3.36.4/debian/changelog 2018-09-03 21:20:56.000000000 +0000 +++ python-oslo.utils-3.36.5/debian/changelog 2019-12-21 20:37:40.000000000 +0000 @@ -1,3 +1,11 @@ +python-oslo.utils (3.36.5-0+deb10u1) buster; urgency=medium + + * CVE-2019-3866: Sensitive information leaked in mistral logs. Upgrade to + the tip of the upstream stable/rocky branch (as the upstream patch would + not otherwise apply). + + -- Thomas Goirand Sat, 21 Dec 2019 21:37:40 +0100 + python-oslo.utils (3.36.4-2) unstable; urgency=medium * Uploading to unstable. diff -Nru python-oslo.utils-3.36.4/oslo_utils/strutils.py python-oslo.utils-3.36.5/oslo_utils/strutils.py --- python-oslo.utils-3.36.4/oslo_utils/strutils.py 2018-07-18 03:43:01.000000000 +0000 +++ python-oslo.utils-3.36.5/oslo_utils/strutils.py 2019-11-18 09:13:41.000000000 +0000 @@ -54,11 +54,19 @@ SLUGIFY_HYPHENATE_RE = re.compile(r"[-\s]+") -# NOTE(flaper87): The following globals are used by `mask_password` -_SANITIZE_KEYS = ['adminPass', 'admin_pass', 'password', 'admin_password', +# NOTE(flaper87): The following globals are used by `mask_password` and +# `mask_dict_password` +_SANITIZE_KEYS = ['adminpass', 'admin_pass', 'password', 'admin_password', 'auth_token', 'new_pass', 'auth_password', 'secret_uuid', 'secret', 'sys_pswd', 'token', 'configdrive', - 'CHAPPASSWORD', 'encrypted_key', 'private_key'] + 'chappassword', 'encrypted_key', 'private_key', + 'encryption_key_id', 'fernetkey', 'sslkey', 'passphrase', + 'cephclusterfsid', 'octaviaheartbeatkey', 'rabbitcookie', + 'cephmanilaclientkey', 'pacemakerremoteauthkey', + 'designaterndckey', 'cephadminkey', 'heatauthencryptionkey', + 'cephclientkey', 'keystonecredential', + 'barbicansimplecryptokek', 'cephrgwkey', 'swifthashsuffix', + 'migrationsshkey', 'cephmdskey', 'cephmonkey'] # NOTE(ldbragst): Let's build a list of regex objects using the list of # _SANITIZE_KEYS we already have. This way, we only have to add the new key @@ -69,17 +77,18 @@ # NOTE(amrith): Some regular expressions have only one parameter, some # have two parameters. Use different lists of patterns here. -_FORMAT_PATTERNS_1 = [r'(%(key)s\s*[=]\s*)[^\s^\'^\"]+'] -_FORMAT_PATTERNS_2 = [r'(%(key)s\s*[=]\s*[\"\'])[^\"\']*([\"\'])', - r'(%(key)s\s+[\"\'])[^\"\']*([\"\'])', - r'([-]{2}%(key)s\s+)[^\'^\"^=^\s]+([\s]*)', - r'(<%(key)s>)[^<]*()', - r'([\"\']%(key)s[\"\']\s*:\s*[\"\'])[^\"\']*([\"\'])', - r'([\'"][^"\']*%(key)s[\'"]\s*:\s*u?[\'"])[^\"\']*' +_FORMAT_PATTERNS_1 = [r'(%(key)s[0-9]*\s*[=]\s*)[^\s^\'^\"]+'] +_FORMAT_PATTERNS_2 = [r'(%(key)s[0-9]*\s*[=]\s*[\"\'])[^\"\']*([\"\'])', + r'(%(key)s[0-9]*\s+[\"\'])[^\"\']*([\"\'])', + r'([-]{2}%(key)s[0-9]*\s+)[^\'^\"^=^\s]+([\s]*)', + r'(<%(key)s[0-9]*>)[^<]*()', + r'([\"\']%(key)s[0-9]*[\"\']\s*:\s*[\"\'])[^\"\']*' + '([\"\'])', + r'([\'"][^"\']*%(key)s[0-9]*[\'"]\s*:\s*u?[\'"])[^\"\']*' '([\'"])', - r'([\'"][^\'"]*%(key)s[\'"]\s*,\s*\'--?[A-z]+\'\s*,\s*u?' - '[\'"])[^\"\']*([\'"])', - r'(%(key)s\s*--?[A-z]+\s*)\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*)'] # 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" @@ -89,11 +98,11 @@ _SANITIZE_PATTERNS_2[key] = [] for pattern in _FORMAT_PATTERNS_2: - reg_ex = re.compile(pattern % {'key': key}, re.DOTALL) + reg_ex = re.compile(pattern % {'key': key}, re.DOTALL | re.IGNORECASE) _SANITIZE_PATTERNS_2[key].append(reg_ex) for pattern in _FORMAT_PATTERNS_1: - reg_ex = re.compile(pattern % {'key': key}, re.DOTALL) + reg_ex = re.compile(pattern % {'key': key}, re.DOTALL | re.IGNORECASE) _SANITIZE_PATTERNS_1[key].append(reg_ex) @@ -328,7 +337,7 @@ # specified in _SANITIZE_KEYS, if not then just return the message since # we don't have to mask any passwords. for key in _SANITIZE_KEYS: - if key in message: + if key.lower() in message.lower(): for pattern in _SANITIZE_PATTERNS_2[key]: message = re.sub(pattern, substitute2, message) for pattern in _SANITIZE_PATTERNS_1[key]: @@ -406,7 +415,7 @@ k_matched = False if isinstance(k, six.string_types): for sani_key in _SANITIZE_KEYS: - if sani_key in k: + if sani_key.lower() in k.lower(): out[k] = secret k_matched = True break diff -Nru python-oslo.utils-3.36.4/oslo_utils/tests/test_strutils.py python-oslo.utils-3.36.5/oslo_utils/tests/test_strutils.py --- python-oslo.utils-3.36.4/oslo_utils/tests/test_strutils.py 2018-07-18 03:43:01.000000000 +0000 +++ python-oslo.utils-3.36.5/oslo_utils/tests/test_strutils.py 2019-11-18 09:13:41.000000000 +0000 @@ -352,6 +352,43 @@ payload = """{ 'token' : 'token' }""" expected = """{ 'token' : '***' }""" self.assertEqual(expected, strutils.mask_password(payload)) + # Test 'fernetkey' + payload = """{ 'fernetkey' : 'token' }""" + expected = """{ 'fernetkey' : '***' }""" + self.assertEqual(expected, strutils.mask_password(payload)) + # Test 'FernetKey' + payload = """{ 'FernetKey' : 'token' }""" + expected = """{ 'FernetKey' : '***' }""" + self.assertEqual(expected, strutils.mask_password(payload)) + # Test 'sslkey' + payload = """{ 'sslkey' : 'token' }""" + expected = """{ 'sslkey' : '***' }""" + self.assertEqual(expected, strutils.mask_password(payload)) + # Test 'SslKey' + payload = """{ 'SslKey' : 'token' }""" + expected = """{ 'SslKey' : '***' }""" + self.assertEqual(expected, strutils.mask_password(payload)) + # Test 'passphrase' + payload = """{ 'passphrase' : 'token' }""" + expected = """{ 'passphrase' : '***' }""" + self.assertEqual(expected, strutils.mask_password(payload)) + # Test 'PassPhrase' + payload = """{ 'PassPhrase' : 'token' }""" + expected = """{ 'PassPhrase' : '***' }""" + self.assertEqual(expected, strutils.mask_password(payload)) + # Some real-life cases + # Test 'KeystoneFernetKey1' + payload = """{ 'KeystoneFernetKey1' : 'token' }""" + expected = """{ 'KeystoneFernetKey1' : '***' }""" + self.assertEqual(expected, strutils.mask_password(payload)) + # Test 'OctaviaCaKeyPassword' + payload = """{ 'OctaviaCaKeyPassword' : 'token' }""" + expected = """{ 'OctaviaCaKeyPassword' : '***' }""" + self.assertEqual(expected, strutils.mask_password(payload)) + # Test 'OctaviaCaKeyPassphrase' + payload = """{ 'OctaviaCaKeyPassphrase' : 'token' }""" + expected = """{ 'OctaviaCaKeyPassphrase' : '***' }""" + self.assertEqual(expected, strutils.mask_password(payload)) def test_xml(self): # Test 'adminPass' w/o spaces @@ -394,6 +431,10 @@ """ expected = """***""" self.assertEqual(expected, strutils.mask_password(payload)) + # Test 'Password1' - case-insensitive + number + payload = """TL0EfN33""" + expected = """***""" + self.assertEqual(expected, strutils.mask_password(payload)) def test_xml_attribute(self): # Test 'adminPass' w/o spaces @@ -458,6 +499,9 @@ payload = """body: {"rescue": {"password": "1234567"}}""" expected = """body: {"rescue": {"password": "***"}}""" self.assertEqual(expected, strutils.mask_password(payload)) + payload = """body: {"rescue": {"encryption_key_id": "1234567"}}""" + expected = """body: {"rescue": {"encryption_key_id": "***"}}""" + self.assertEqual(expected, strutils.mask_password(payload)) def test_xml_message(self): payload = """ @@ -647,6 +691,16 @@ self.assertEqual(expected, strutils.mask_dict_password(payload)) + payload = {'passwords': {'KeystoneFernetKey1': 'c5FijjS'}} + expected = {'passwords': {'KeystoneFernetKey1': '***'}} + self.assertEqual(expected, + strutils.mask_dict_password(payload)) + + payload = {'passwords': {'keystonecredential0': 'c5FijjS'}} + expected = {'passwords': {'keystonecredential0': '***'}} + self.assertEqual(expected, + strutils.mask_dict_password(payload)) + def test_do_no_harm(self): payload = {} expected = {} diff -Nru python-oslo.utils-3.36.4/releasenotes/notes/mask-dict-passwords-99357ffb7972fb0b.yaml python-oslo.utils-3.36.5/releasenotes/notes/mask-dict-passwords-99357ffb7972fb0b.yaml --- python-oslo.utils-3.36.4/releasenotes/notes/mask-dict-passwords-99357ffb7972fb0b.yaml 1970-01-01 00:00:00.000000000 +0000 +++ python-oslo.utils-3.36.5/releasenotes/notes/mask-dict-passwords-99357ffb7972fb0b.yaml 2019-11-18 09:13:41.000000000 +0000 @@ -0,0 +1,9 @@ +--- +security: + - | + This patch ensures that we mask sensitive data when masking dicts, even if + the case doesn't match. This means the behaviour of mask_password and + mask_dict_password is now the same. + - | + Additional password names were included from real world logs that contained + sensitive information. \ No newline at end of file diff -Nru python-oslo.utils-3.36.4/releasenotes/notes/mask-password-patterns-f41524069b8ae488.yaml python-oslo.utils-3.36.5/releasenotes/notes/mask-password-patterns-f41524069b8ae488.yaml --- python-oslo.utils-3.36.4/releasenotes/notes/mask-password-patterns-f41524069b8ae488.yaml 1970-01-01 00:00:00.000000000 +0000 +++ python-oslo.utils-3.36.5/releasenotes/notes/mask-password-patterns-f41524069b8ae488.yaml 2019-11-18 09:13:41.000000000 +0000 @@ -0,0 +1,8 @@ +--- +security: + - This patch ensures we actually mask sensitive data, even if case doesn't + match the static entry we have in the patterns. + - It also ensures that some fancy names with a common base, but added + number are actually taken care of. +fixes: + - https://bugs.launchpad.net/tripleo/+bug/1850843 diff -Nru python-oslo.utils-3.36.4/tox.ini python-oslo.utils-3.36.5/tox.ini --- python-oslo.utils-3.36.4/tox.ini 2018-07-18 03:43:01.000000000 +0000 +++ python-oslo.utils-3.36.5/tox.ini 2019-11-18 09:13:41.000000000 +0000 @@ -5,7 +5,7 @@ [testenv] install_command = pip install {opts} {packages} deps = - -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} + -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt?h=stable/rocky} -r{toxinidir}/test-requirements.txt -r{toxinidir}/requirements.txt commands = stestr run --slowest {posargs}