summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Cacqueray <tristan.cacqueray@enovance.com>2014-09-14 19:18:06 +0000
committerTristan Cacqueray <tristan.cacqueray@enovance.com>2014-09-22 17:00:09 +0000
commit9672744f090d462cac5eb757ceaacd7122362708 (patch)
treea5182a6f6074180594336b673b107db32c7ce879
parente24bd6ba1b35af80a4a386c8b46ae2d5e1a2d514 (diff)
downloadtrove-9672744f090d462cac5eb757ceaacd7122362708.tar.gz
Sync latest process and str utils from oslo
This sync required changes to fix these issues: * Make execute method clean password in exception * Make sure mask_password works properly ------------------------------------------------ The sync pulls in the following changes (newest to oldest): 6a60f842 - Mask passwords in exceptions and error messages (SSH) 63c99a0f - Mask passwords in exceptions and error messages 66142c34 - Make strutils.mask_password more secure ----------------------------------------------- Closes-Bug: 1343604 Closes-Bug: 1345233 SecurityImpact Change-Id: I3b49b1d667f6ade9ae3f6765d735440a3e838917
-rw-r--r--trove/openstack/common/processutils.py28
-rw-r--r--trove/openstack/common/strutils.py44
2 files changed, 47 insertions, 25 deletions
diff --git a/trove/openstack/common/processutils.py b/trove/openstack/common/processutils.py
index 7d5c350c..58f6b5e1 100644
--- a/trove/openstack/common/processutils.py
+++ b/trove/openstack/common/processutils.py
@@ -150,12 +150,12 @@ def execute(*cmd, **kwargs):
cmd = shlex.split(root_helper) + list(cmd)
cmd = map(str, cmd)
+ sanitized_cmd = strutils.mask_password(' '.join(cmd))
while attempts > 0:
attempts -= 1
try:
- LOG.log(loglevel, 'Running cmd (subprocess): %s',
- strutils.mask_password(' '.join(cmd)))
+ LOG.log(loglevel, _('Running cmd (subprocess): %s'), sanitized_cmd)
_PIPE = subprocess.PIPE # pylint: disable=E1101
if os.name == 'nt':
@@ -192,16 +192,18 @@ def execute(*cmd, **kwargs):
LOG.log(loglevel, 'Result was %s' % _returncode)
if not ignore_exit_code and _returncode not in check_exit_code:
(stdout, stderr) = result
+ sanitized_stdout = strutils.mask_password(stdout)
+ sanitized_stderr = strutils.mask_password(stderr)
raise ProcessExecutionError(exit_code=_returncode,
- stdout=stdout,
- stderr=stderr,
- cmd=' '.join(cmd))
+ stdout=sanitized_stdout,
+ stderr=sanitized_stderr,
+ cmd=sanitized_cmd)
return result
except ProcessExecutionError:
if not attempts:
raise
else:
- LOG.log(loglevel, '%r failed. Retrying.', cmd)
+ LOG.log(loglevel, _('%r failed. Retrying.'), sanitized_cmd)
if delay_on_retry:
greenthread.sleep(random.randint(20, 200) / 100.0)
finally:
@@ -240,7 +242,8 @@ def trycmd(*args, **kwargs):
def ssh_execute(ssh, cmd, process_input=None,
addl_env=None, check_exit_code=True):
- LOG.debug('Running cmd (SSH): %s', cmd)
+ sanitized_cmd = strutils.mask_password(cmd)
+ LOG.debug('Running cmd (SSH): %s', sanitized_cmd)
if addl_env:
raise InvalidArgumentError(_('Environment not supported over SSH'))
@@ -254,7 +257,10 @@ def ssh_execute(ssh, cmd, process_input=None,
# NOTE(justinsb): This seems suspicious...
# ...other SSH clients have buffering issues with this approach
stdout = stdout_stream.read()
+ sanitized_stdout = strutils.mask_password(stdout)
stderr = stderr_stream.read()
+ sanitized_stderr = strutils.mask_password(stderr)
+
stdin_stream.close()
exit_status = channel.recv_exit_status()
@@ -264,11 +270,11 @@ def ssh_execute(ssh, cmd, process_input=None,
LOG.debug('Result was %s' % exit_status)
if check_exit_code and exit_status != 0:
raise ProcessExecutionError(exit_code=exit_status,
- stdout=stdout,
- stderr=stderr,
- cmd=cmd)
+ stdout=sanitized_stdout,
+ stderr=sanitized_stderr,
+ cmd=sanitized_cmd)
- return (stdout, stderr)
+ return (sanitized_stdout, sanitized_stderr)
def get_worker_count():
diff --git a/trove/openstack/common/strutils.py b/trove/openstack/common/strutils.py
index dff59481..583ac836 100644
--- a/trove/openstack/common/strutils.py
+++ b/trove/openstack/common/strutils.py
@@ -50,26 +50,37 @@ SLUGIFY_STRIP_RE = re.compile(r"[^\w\s-]")
SLUGIFY_HYPHENATE_RE = re.compile(r"[-\s]+")
-# NOTE(flaper87): The following 3 globals are used by `mask_password`
+# 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 = []
-_FORMAT_PATTERNS = [r'(%(key)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*)']
+_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:
+ for pattern in _FORMAT_PATTERNS_2:
reg_ex = re.compile(pattern % {'key': key}, re.DOTALL)
- _SANITIZE_PATTERNS.append(reg_ex)
+ _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):
@@ -289,7 +300,12 @@ def mask_password(message, secret="***"):
if not any(key in message for key in _SANITIZE_KEYS):
return message
- secret = r'\g<1>' + secret + r'\g<2>'
- for pattern in _SANITIZE_PATTERNS:
- message = re.sub(pattern, secret, 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