--- Begin Message ---
Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock
Dear release team,
Moritz Mühlenhoff (aka jmm) made me aware of CVE-2014-7231, which has been
fixed in the release 0.2.0 of python-oslo.utils. This version has never been
uploaded to Sid (I uploaded it to Experimental instead), as I didn't want to
risk changing anything in OpenStack Icehouse in Jessie.
But since it fixes CVE-2014-7231, I'd like now to have version 0.2.0 replacing
version 0.1.1 in Jessie. Indeed, the patch available here:
https://review.openstack.org/gitweb?p=openstack%2Foslo.utils.git;a=commitdiff;h=e0425691d90bce0bbe847a9ff49468ce0fab5486
which fixes the issue, cannot be applied on top of version 0.1.1. I don't want
to risk doing a backport by myself, and would very much prefer to use what's
been done by upstream, which is "gated" (eg: tested by a CI / CD system).
Note that upstream currently declares that any version of python-oslo.utils
lower than version 1.0.0 can work with OpenStack Icehouse currently in Jessie,
as per the "global-requirements.txt" maintained for OpenStack Icehouse:
https://github.com/openstack/requirements/blob/stable/icehouse/global-requirements.txt#L53
So even version 0.3.0 would work, and may even be preferred, since that's what
the OpenStack gate uses right now to test Icehouse.
I have attached the debdiff between 0.1.1-1, and 0.2.0-1 (as per the package I
uploaded in Experimental, available in snapshot.d.o).
Will the release team accept such an unblock? Do I have your go-ahead to
upload version 0.2.0-1 to Sid?
Cheers,
Thomas Goirand (zigo)
diff -Nru python-oslo.utils-0.1.1/debian/changelog python-oslo.utils-0.2.0/debian/changelog
--- python-oslo.utils-0.1.1/debian/changelog 2014-08-07 10:19:33.000000000 +0200
+++ python-oslo.utils-0.2.0/debian/changelog 2014-09-05 10:07:10.000000000 +0200
@@ -1,3 +1,10 @@
+python-oslo.utils (0.2.0-1) experimental; urgency=medium
+
+ * New upstream release.
+ * Uploading to experimental before Jessie's freeze.
+
+ -- Thomas Goirand <zigo@debian.org> Fri, 05 Sep 2014 15:50:43 +0800
+
python-oslo.utils (0.1.1-1) unstable; urgency=medium
* Initial release. (Closes: #757325)
diff -Nru python-oslo.utils-0.1.1/debian/gbp.conf python-oslo.utils-0.2.0/debian/gbp.conf
--- python-oslo.utils-0.1.1/debian/gbp.conf 2014-08-07 10:19:33.000000000 +0200
+++ python-oslo.utils-0.2.0/debian/gbp.conf 2014-09-05 10:07:10.000000000 +0200
@@ -1,6 +1,6 @@
[DEFAULT]
upstream-branch = master
-debian-branch = debian/unstable
+debian-branch = debian/experimental
upstream-tag = %(version)s
compression = xz
diff -Nru python-oslo.utils-0.1.1/debian/rules python-oslo.utils-0.2.0/debian/rules
--- python-oslo.utils-0.1.1/debian/rules 2014-08-07 10:19:33.000000000 +0200
+++ python-oslo.utils-0.2.0/debian/rules 2014-09-05 10:07:10.000000000 +0200
@@ -24,18 +24,18 @@
override_dh_auto_test:
ifeq (,$(findstring nocheck, $(DEB_BUILD_OPTIONS)))
- @echo "===> Running tests"
- set -e && set -x && for i in 2.7 $(PYTHON3S) ; do \
- PYMAJOR=`echo $$i | cut -d'.' -f1` ; \
- echo "===> Testing with python$$i (python$$PYMAJOR)" ; \
- rm -rf .testrepository ; \
- testr-python$$PYMAJOR init ; \
- TEMP_REZ=`mktemp -t` && \
- PYTHONPATH=$(CURDIR) PYTHON=python$$i testr-python$$PYMAJOR run --subunit | tee $$TEMP_REZ | subunit2pyunit ; \
- cat $$TEMP_REZ | subunit-filter -s --no-passthrough | subunit-stats ; \
- rm -f $$TEMP_REZ ; \
- testr-python$$PYMAJOR slowest ; \
- done
+ @echo "===> Running tests"
+ set -e ; set -x ; for i in 2.7 ; do \
+ PYMAJOR=`echo $$i | cut -d'.' -f1` ; \
+ echo "===> Testing with python$$i (python$$PYMAJOR)" ; \
+ rm -rf .testrepository ; \
+ testr-python$$PYMAJOR init ; \
+ TEMP_REZ=`mktemp -t` ; \
+ PYTHONPATH=$(CURDIR) PYTHON=python$$i testr-python$$PYMAJOR run --subunit | tee $$TEMP_REZ | subunit2pyunit ; \
+ cat $$TEMP_REZ | subunit-filter -s --no-passthrough | subunit-stats ; \
+ rm -f $$TEMP_REZ ; \
+ testr-python$$PYMAJOR slowest ; \
+ done
endif
override_dh_clean:
diff -Nru python-oslo.utils-0.1.1/oslo/utils/strutils.py python-oslo.utils-0.2.0/oslo/utils/strutils.py
--- python-oslo.utils-0.1.1/oslo/utils/strutils.py 2014-07-28 19:20:33.000000000 +0200
+++ python-oslo.utils-0.2.0/oslo/utils/strutils.py 2014-08-15 19:53:57.000000000 +0200
@@ -50,6 +50,39 @@
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(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
+# to the list of _SANITIZE_KEYS and we can generate regular expressions
+# for XML and JSON automatically.
+_SANITIZE_PATTERNS_2 = []
+_SANITIZE_PATTERNS_1 = []
+
+# 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>).*?(</%(key)s>)',
+ r'([\"\']%(key)s[\"\']\s*:\s*[\"\']).*?([\"\'])',
+ r'([\'"].*?%(key)s[\'"]\s*:\s*u?[\'"]).*?([\'"])',
+ r'([\'"].*?%(key)s[\'"]\s*,\s*\'--?[A-z]+\'\s*,\s*u?'
+ '[\'"]).*?([\'"])',
+ r'(%(key)s\s*--?[A-z]+\s*)\S+(\s*)']
+
+for key in _SANITIZE_KEYS:
+ for pattern in _FORMAT_PATTERNS_2:
+ reg_ex = re.compile(pattern % {'key': key}, re.DOTALL)
+ _SANITIZE_PATTERNS_2.append(reg_ex)
+
+ for pattern in _FORMAT_PATTERNS_1:
+ reg_ex = re.compile(pattern % {'key': key}, re.DOTALL)
+ _SANITIZE_PATTERNS_1.append(reg_ex)
+
+
def int_from_bool_as_string(subject):
"""Interpret a string as a boolean and return either 1 or 0.
@@ -166,3 +199,42 @@
"ascii", "ignore").decode("ascii")
value = SLUGIFY_STRIP_RE.sub("", value).strip().lower()
return SLUGIFY_HYPHENATE_RE.sub("-", value)
+
+
+def mask_password(message, secret="***"):
+ """Replace password with 'secret' in message.
+
+ :param message: The string which includes security information.
+ :param secret: value with which to replace passwords.
+ :returns: The unicode value of message with the password fields masked.
+
+ For example:
+
+ >>> mask_password("'adminPass' : 'aaaaa'")
+ "'adminPass' : '***'"
+ >>> mask_password("'admin_pass' : 'aaaaa'")
+ "'admin_pass' : '***'"
+ >>> mask_password('"password" : "aaaaa"')
+ '"password" : "***"'
+ >>> mask_password("'original_password' : 'aaaaa'")
+ "'original_password' : '***'"
+ >>> mask_password("u'original_password' : u'aaaaa'")
+ "u'original_password' : u'***'"
+ """
+ message = six.text_type(message)
+
+ # NOTE(ldbragst): Check to see if anything in message contains any key
+ # specified in _SANITIZE_KEYS, if not then just return the message since
+ # we don't have to mask any passwords.
+ if not any(key in message for key in _SANITIZE_KEYS):
+ return message
+
+ substitute = r'\g<1>' + secret + r'\g<2>'
+ for pattern in _SANITIZE_PATTERNS_2:
+ message = re.sub(pattern, substitute, message)
+
+ substitute = r'\g<1>' + secret
+ for pattern in _SANITIZE_PATTERNS_1:
+ message = re.sub(pattern, substitute, message)
+
+ return message
diff -Nru python-oslo.utils-0.1.1/oslo.utils/locale/oslo.utils-log-critical.pot python-oslo.utils-0.2.0/oslo.utils/locale/oslo.utils-log-critical.pot
--- python-oslo.utils-0.1.1/oslo.utils/locale/oslo.utils-log-critical.pot 1970-01-01 01:00:00.000000000 +0100
+++ python-oslo.utils-0.2.0/oslo.utils/locale/oslo.utils-log-critical.pot 2014-08-15 19:53:57.000000000 +0200
@@ -0,0 +1,19 @@
+# Translations template for oslo.utils.
+# Copyright (C) 2014 ORGANIZATION
+# This file is distributed under the same license as the oslo.utils project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: oslo.utils 0.1.1\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 06:10+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
diff -Nru python-oslo.utils-0.1.1/oslo.utils/locale/oslo.utils-log-error.pot python-oslo.utils-0.2.0/oslo.utils/locale/oslo.utils-log-error.pot
--- python-oslo.utils-0.1.1/oslo.utils/locale/oslo.utils-log-error.pot 1970-01-01 01:00:00.000000000 +0100
+++ python-oslo.utils-0.2.0/oslo.utils/locale/oslo.utils-log-error.pot 2014-08-15 19:53:57.000000000 +0200
@@ -0,0 +1,29 @@
+# Translations template for oslo.utils.
+# Copyright (C) 2014 ORGANIZATION
+# This file is distributed under the same license as the oslo.utils project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: oslo.utils 0.1.1\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 06:10+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: oslo/utils/excutils.py:76
+#, python-format
+msgid "Original exception being dropped: %s"
+msgstr ""
+
+#: oslo/utils/excutils.py:105
+#, python-format
+msgid "Unexpected exception occurred %d time(s)... retrying."
+msgstr ""
+
diff -Nru python-oslo.utils-0.1.1/oslo.utils/locale/oslo.utils-log-info.pot python-oslo.utils-0.2.0/oslo.utils/locale/oslo.utils-log-info.pot
--- python-oslo.utils-0.1.1/oslo.utils/locale/oslo.utils-log-info.pot 1970-01-01 01:00:00.000000000 +0100
+++ python-oslo.utils-0.2.0/oslo.utils/locale/oslo.utils-log-info.pot 2014-08-15 19:53:57.000000000 +0200
@@ -0,0 +1,19 @@
+# Translations template for oslo.utils.
+# Copyright (C) 2014 ORGANIZATION
+# This file is distributed under the same license as the oslo.utils project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: oslo.utils 0.1.1\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 06:10+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
diff -Nru python-oslo.utils-0.1.1/oslo.utils/locale/oslo.utils-log-warning.pot python-oslo.utils-0.2.0/oslo.utils/locale/oslo.utils-log-warning.pot
--- python-oslo.utils-0.1.1/oslo.utils/locale/oslo.utils-log-warning.pot 1970-01-01 01:00:00.000000000 +0100
+++ python-oslo.utils-0.2.0/oslo.utils/locale/oslo.utils-log-warning.pot 2014-08-15 19:53:57.000000000 +0200
@@ -0,0 +1,31 @@
+# Translations template for oslo.utils.
+# Copyright (C) 2014 ORGANIZATION
+# This file is distributed under the same license as the oslo.utils project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: oslo.utils 0.1.1\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2014-08-11 06:10+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 1.3\n"
+
+#: oslo/utils/netutils.py:151
+msgid "tcp_keepidle not available on your system"
+msgstr ""
+
+#: oslo/utils/netutils.py:158
+msgid "tcp_keepintvl not available on your system"
+msgstr ""
+
+#: oslo/utils/netutils.py:165
+msgid "tcp_keepcnt not available on your system"
+msgstr ""
+
diff -Nru python-oslo.utils-0.1.1/oslo.utils/locale/oslo.utils.pot python-oslo.utils-0.2.0/oslo.utils/locale/oslo.utils.pot
--- python-oslo.utils-0.1.1/oslo.utils/locale/oslo.utils.pot 2014-07-28 19:20:33.000000000 +0200
+++ python-oslo.utils-0.2.0/oslo.utils/locale/oslo.utils.pot 2014-08-15 19:53:57.000000000 +0200
@@ -6,9 +6,9 @@
#, fuzzy
msgid ""
msgstr ""
-"Project-Id-Version: oslo.utils 5621114\n"
+"Project-Id-Version: oslo.utils 0.1.1\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2014-07-11 13:25+0200\n"
+"POT-Creation-Date: 2014-08-11 06:10+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,48 +17,18 @@
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 1.3\n"
-#: oslo/utils/strutils.py:92 oslo/utils/openstack/common/strutils.py:92
+#: oslo/utils/strutils.py:92
#, python-format
msgid "Unrecognized value '%(val)s', acceptable values are: %(acceptable)s"
msgstr ""
-#: oslo/utils/strutils.py:197 oslo/utils/openstack/common/strutils.py:197
+#: oslo/utils/strutils.py:126
#, python-format
msgid "Invalid unit system: \"%s\""
msgstr ""
-#: oslo/utils/strutils.py:206 oslo/utils/openstack/common/strutils.py:206
+#: oslo/utils/strutils.py:135
#, python-format
msgid "Invalid string format: %s"
msgstr ""
-#: oslo/utils/openstack/common/gettextutils.py:320
-msgid "Message objects do not support addition."
-msgstr ""
-
-#: oslo/utils/openstack/common/gettextutils.py:330
-msgid ""
-"Message objects do not support str() because they may contain non-ascii "
-"characters. Please use unicode() or translate() instead."
-msgstr ""
-
-#: oslo/utils/openstack/common/log.py:327
-#, python-format
-msgid "Deprecated: %s"
-msgstr ""
-
-#: oslo/utils/openstack/common/log.py:436
-#, python-format
-msgid "Error loading logging config %(log_config)s: %(err_msg)s"
-msgstr ""
-
-#: oslo/utils/openstack/common/log.py:487
-#, python-format
-msgid "syslog facility must be one of: %s"
-msgstr ""
-
-#: oslo/utils/openstack/common/log.py:725
-#, python-format
-msgid "Fatal call to deprecated config: %(msg)s"
-msgstr ""
-
diff -Nru python-oslo.utils-0.1.1/tests/test_strutils.py python-oslo.utils-0.2.0/tests/test_strutils.py
--- python-oslo.utils-0.1.1/tests/test_strutils.py 2014-07-28 19:20:33.000000000 +0200
+++ python-oslo.utils-0.2.0/tests/test_strutils.py 2014-08-15 19:53:57.000000000 +0200
@@ -259,3 +259,290 @@
self.assertAlmostEqual(actual, expected)
StringToBytesTest.generate_scenarios()
+
+
+class MaskPasswordTestCase(test_base.BaseTestCase):
+
+ def test_json(self):
+ # Test 'adminPass' w/o spaces
+ payload = """{'adminPass':'mypassword'}"""
+ expected = """{'adminPass':'***'}"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'adminPass' with spaces
+ payload = """{ 'adminPass' : 'mypassword' }"""
+ expected = """{ 'adminPass' : '***' }"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'admin_pass' w/o spaces
+ payload = """{'admin_pass':'mypassword'}"""
+ expected = """{'admin_pass':'***'}"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'admin_pass' with spaces
+ payload = """{ 'admin_pass' : 'mypassword' }"""
+ expected = """{ 'admin_pass' : '***' }"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'admin_password' w/o spaces
+ payload = """{'admin_password':'mypassword'}"""
+ expected = """{'admin_password':'***'}"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'admin_password' with spaces
+ payload = """{ 'admin_password' : 'mypassword' }"""
+ expected = """{ 'admin_password' : '***' }"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'password' w/o spaces
+ payload = """{'password':'mypassword'}"""
+ expected = """{'password':'***'}"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'password' with spaces
+ payload = """{ 'password' : 'mypassword' }"""
+ expected = """{ 'password' : '***' }"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+
+ def test_xml(self):
+ # Test 'adminPass' w/o spaces
+ payload = """<adminPass>mypassword</adminPass>"""
+ expected = """<adminPass>***</adminPass>"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'adminPass' with spaces
+ payload = """<adminPass>
+ mypassword
+ </adminPass>"""
+ expected = """<adminPass>***</adminPass>"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'admin_pass' w/o spaces
+ payload = """<admin_pass>mypassword</admin_pass>"""
+ expected = """<admin_pass>***</admin_pass>"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'admin_pass' with spaces
+ payload = """<admin_pass>
+ mypassword
+ </admin_pass>"""
+ expected = """<admin_pass>***</admin_pass>"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'admin_password' w/o spaces
+ payload = """<admin_password>mypassword</admin_password>"""
+ expected = """<admin_password>***</admin_password>"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'admin_password' with spaces
+ payload = """<admin_password>
+ mypassword
+ </admin_password>"""
+ expected = """<admin_password>***</admin_password>"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'password' w/o spaces
+ payload = """<password>mypassword</password>"""
+ expected = """<password>***</password>"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'password' with spaces
+ payload = """<password>
+ mypassword
+ </password>"""
+ expected = """<password>***</password>"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+
+ def test_xml_attribute(self):
+ # Test 'adminPass' w/o spaces
+ payload = """adminPass='mypassword'"""
+ expected = """adminPass='***'"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'adminPass' with spaces
+ payload = """adminPass = 'mypassword'"""
+ expected = """adminPass = '***'"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'adminPass' with double quotes
+ payload = """adminPass = "mypassword\""""
+ expected = """adminPass = "***\""""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'admin_pass' w/o spaces
+ payload = """admin_pass='mypassword'"""
+ expected = """admin_pass='***'"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'admin_pass' with spaces
+ payload = """admin_pass = 'mypassword'"""
+ expected = """admin_pass = '***'"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'admin_pass' with double quotes
+ payload = """admin_pass = "mypassword\""""
+ expected = """admin_pass = "***\""""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'admin_password' w/o spaces
+ payload = """admin_password='mypassword'"""
+ expected = """admin_password='***'"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'admin_password' with spaces
+ payload = """admin_password = 'mypassword'"""
+ expected = """admin_password = '***'"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'admin_password' with double quotes
+ payload = """admin_password = "mypassword\""""
+ expected = """admin_password = "***\""""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'password' w/o spaces
+ payload = """password='mypassword'"""
+ expected = """password='***'"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'password' with spaces
+ payload = """password = 'mypassword'"""
+ expected = """password = '***'"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ # Test 'password' with double quotes
+ payload = """password = "mypassword\""""
+ expected = """password = "***\""""
+ self.assertEqual(expected, strutils.mask_password(payload))
+
+ def test_json_message(self):
+ payload = """body: {"changePassword": {"adminPass": "1234567"}}"""
+ expected = """body: {"changePassword": {"adminPass": "***"}}"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ payload = """body: {"rescue": {"admin_pass": "1234567"}}"""
+ expected = """body: {"rescue": {"admin_pass": "***"}}"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ payload = """body: {"rescue": {"admin_password": "1234567"}}"""
+ expected = """body: {"rescue": {"admin_password": "***"}}"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ payload = """body: {"rescue": {"password": "1234567"}}"""
+ expected = """body: {"rescue": {"password": "***"}}"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+
+ def test_xml_message(self):
+ payload = """<?xml version="1.0" encoding="UTF-8"?>
+<rebuild
+ xmlns="http://docs.openstack.org/compute/api/v1.1"
+ name="foobar"
+ imageRef="http://openstack.example.com/v1.1/32278/images/70a599e0-31e7"
+ accessIPv4="1.2.3.4"
+ accessIPv6="fe80::100"
+ adminPass="seekr3t">
+ <metadata>
+ <meta key="My Server Name">Apache1</meta>
+ </metadata>
+</rebuild>"""
+ expected = """<?xml version="1.0" encoding="UTF-8"?>
+<rebuild
+ xmlns="http://docs.openstack.org/compute/api/v1.1"
+ name="foobar"
+ imageRef="http://openstack.example.com/v1.1/32278/images/70a599e0-31e7"
+ accessIPv4="1.2.3.4"
+ accessIPv6="fe80::100"
+ adminPass="***">
+ <metadata>
+ <meta key="My Server Name">Apache1</meta>
+ </metadata>
+</rebuild>"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ payload = """<?xml version="1.0" encoding="UTF-8"?>
+<rescue xmlns="http://docs.openstack.org/compute/api/v1.1"
+ admin_pass="MySecretPass"/>"""
+ expected = """<?xml version="1.0" encoding="UTF-8"?>
+<rescue xmlns="http://docs.openstack.org/compute/api/v1.1"
+ admin_pass="***"/>"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ payload = """<?xml version="1.0" encoding="UTF-8"?>
+<rescue xmlns="http://docs.openstack.org/compute/api/v1.1"
+ admin_password="MySecretPass"/>"""
+ expected = """<?xml version="1.0" encoding="UTF-8"?>
+<rescue xmlns="http://docs.openstack.org/compute/api/v1.1"
+ admin_password="***"/>"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+ payload = """<?xml version="1.0" encoding="UTF-8"?>
+<rescue xmlns="http://docs.openstack.org/compute/api/v1.1"
+ password="MySecretPass"/>"""
+ expected = """<?xml version="1.0" encoding="UTF-8"?>
+<rescue xmlns="http://docs.openstack.org/compute/api/v1.1"
+ password="***"/>"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+
+ def test_mask_password(self):
+ payload = "test = 'password' : 'aaaaaa'"
+ expected = "test = 'password' : '111'"
+ self.assertEqual(expected,
+ strutils.mask_password(payload, secret='111'))
+
+ payload = 'mysqld --password "aaaaaa"'
+ expected = 'mysqld --password "****"'
+ self.assertEqual(expected,
+ strutils.mask_password(payload, secret='****'))
+
+ payload = 'mysqld --password aaaaaa'
+ expected = 'mysqld --password ???'
+ self.assertEqual(expected,
+ strutils.mask_password(payload, secret='???'))
+
+ payload = 'mysqld --password = "aaaaaa"'
+ expected = 'mysqld --password = "****"'
+ self.assertEqual(expected,
+ strutils.mask_password(payload, secret='****'))
+
+ payload = "mysqld --password = 'aaaaaa'"
+ expected = "mysqld --password = '****'"
+ self.assertEqual(expected,
+ strutils.mask_password(payload, secret='****'))
+
+ payload = "mysqld --password = aaaaaa"
+ expected = "mysqld --password = ****"
+ self.assertEqual(expected,
+ strutils.mask_password(payload, secret='****'))
+
+ payload = "test = password = aaaaaa"
+ expected = "test = password = 111"
+ self.assertEqual(expected,
+ strutils.mask_password(payload, secret='111'))
+
+ payload = "test = password= aaaaaa"
+ expected = "test = password= 111"
+ self.assertEqual(expected,
+ strutils.mask_password(payload, secret='111'))
+
+ payload = "test = password =aaaaaa"
+ expected = "test = password =111"
+ self.assertEqual(expected,
+ strutils.mask_password(payload, secret='111'))
+
+ payload = "test = password=aaaaaa"
+ expected = "test = password=111"
+ self.assertEqual(expected,
+ strutils.mask_password(payload, secret='111'))
+
+ payload = 'test = "original_password" : "aaaaaaaaa"'
+ expected = 'test = "original_password" : "***"'
+ self.assertEqual(expected, strutils.mask_password(payload))
+
+ payload = 'test = "param1" : "value"'
+ expected = 'test = "param1" : "value"'
+ self.assertEqual(expected, strutils.mask_password(payload))
+
+ payload = """{'adminPass':'mypassword'}"""
+ payload = six.text_type(payload)
+ expected = """{'adminPass':'***'}"""
+ self.assertEqual(expected, strutils.mask_password(payload))
+
+ payload = ("test = 'node.session.auth.password','-v','mypassword',"
+ "'nomask'")
+ expected = ("test = 'node.session.auth.password','-v','***',"
+ "'nomask'")
+ self.assertEqual(expected, strutils.mask_password(payload))
+
+ payload = ("test = 'node.session.auth.password', '--password', "
+ "'mypassword', 'nomask'")
+ expected = ("test = 'node.session.auth.password', '--password', "
+ "'***', 'nomask'")
+ self.assertEqual(expected, strutils.mask_password(payload))
+
+ payload = ("test = 'node.session.auth.password', '--password', "
+ "'mypassword'")
+ expected = ("test = 'node.session.auth.password', '--password', "
+ "'***'")
+ self.assertEqual(expected, strutils.mask_password(payload))
+
+ payload = "test = node.session.auth.password -v mypassword nomask"
+ expected = "test = node.session.auth.password -v *** nomask"
+ self.assertEqual(expected, strutils.mask_password(payload))
+
+ payload = ("test = node.session.auth.password --password mypassword "
+ "nomask")
+ expected = ("test = node.session.auth.password --password *** "
+ "nomask")
+ self.assertEqual(expected, strutils.mask_password(payload))
+
+ payload = ("test = node.session.auth.password --password mypassword")
+ expected = ("test = node.session.auth.password --password ***")
+ self.assertEqual(expected, strutils.mask_password(payload))
--- End Message ---