summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEoghan Glynn <eglynn@redhat.com>2012-03-22 16:54:26 +0000
committerEoghan Glynn <eglynn@redhat.com>2012-03-22 17:36:55 +0000
commita24376c0a87bc8631f61edab8cd463a5c26aa494 (patch)
treeb30a47faedd2c648aced001ae8a2a7d84babb89d
parent13ed88186bb5c6a1900c3bb742d06743fd21ac58 (diff)
Avoid leaking secrets into config logging.
Implements bp cfg-password-options Allow options to be declared secret so that their value is obfuscated before logging. Change-Id: Ie2168d218b029d9c12fa5b48342cd5b17b2cc77a
-rw-r--r--openstack/common/cfg.py27
-rw-r--r--tests/unit/test_cfg.py12
2 files changed, 32 insertions, 7 deletions
diff --git a/openstack/common/cfg.py b/openstack/common/cfg.py
index 1005b2f..7b729c3 100644
--- a/openstack/common/cfg.py
+++ b/openstack/common/cfg.py
@@ -207,6 +207,16 @@ as the leftover arguments, but will instead return::
['cmd', '--debug', '/tmp/mything']
i.e. argument parsing is stopped at the first non-option argument.
+
+Options may be declared as secret so that their values are not leaked into
+log files:
+
+ opts = [
+ cfg.StrOpt('s3_store_access_key', secret=True),
+ cfg.StrOpt('s3_store_secret_key', secret=True),
+ ...
+ ]
+
"""
import collections
@@ -399,8 +409,8 @@ class Opt(object):
an string explaining how the options value is used
"""
- def __init__(self, name, dest=None, short=None,
- default=None, metavar=None, help=None):
+ def __init__(self, name, dest=None, short=None, default=None,
+ metavar=None, help=None, secret=False):
"""Construct an Opt object.
The only required parameter is the option's name. However, it is
@@ -412,6 +422,7 @@ class Opt(object):
:param default: the default value of the option
:param metavar: the option argument to show in --help
:param help: an explanation of how the option is used
+ :param secret: true iff the value should be obfuscated in log output
"""
self.name = name
if dest is None:
@@ -422,6 +433,7 @@ class Opt(object):
self.default = default
self.metavar = metavar
self.help = help
+ self.secret = secret
def _get_from_config_parser(self, cparser, section):
"""Retrieves the option value from a ConfigParser object.
@@ -948,15 +960,22 @@ class ConfigOpts(collections.Mapping):
logger.log(lvl, "config files: %s", self.config_file)
logger.log(lvl, "=" * 80)
+ def _sanitize(opt, value):
+ """Obfuscate values of options declared secret"""
+ return value if not opt.secret else '*' * len(str(value))
+
for opt_name in sorted(self._opts):
- logger.log(lvl, "%-30s = %s", opt_name, getattr(self, opt_name))
+ opt = self._get_opt_info(opt_name)['opt']
+ logger.log(lvl, "%-30s = %s", opt_name,
+ _sanitize(opt, getattr(self, opt_name)))
for group_name in self._groups:
group_attr = self.GroupAttr(self, self._get_group(group_name))
for opt_name in sorted(self._groups[group_name]._opts):
+ opt = self._get_opt_info(opt_name, group_name)['opt']
logger.log(lvl, "%-30s = %s",
"%s.%s" % (group_name, opt_name),
- getattr(group_attr, opt_name))
+ _sanitize(opt, getattr(group_attr, opt_name)))
logger.log(lvl, "*" * 80)
diff --git a/tests/unit/test_cfg.py b/tests/unit/test_cfg.py
index dc7b94e..9e1e0e8 100644
--- a/tests/unit/test_cfg.py
+++ b/tests/unit/test_cfg.py
@@ -936,10 +936,13 @@ class OptDumpingTestCase(BaseTestCase):
def test_log_opt_values(self):
self.conf.register_cli_opt(StrOpt('foo'))
+ self.conf.register_cli_opt(StrOpt('passwd', secret=True))
self.conf.register_group(OptGroup('blaa'))
self.conf.register_cli_opt(StrOpt('bar'), 'blaa')
+ self.conf.register_cli_opt(StrOpt('key', secret=True), 'blaa')
- self.conf(['--foo', 'this', '--blaa-bar', 'that'])
+ self.conf(['--foo', 'this', '--blaa-bar', 'that',
+ '--blaa-key', 'admin', '--passwd', 'hush'])
logger = self.FakeLogger(self, 666)
@@ -948,12 +951,15 @@ class OptDumpingTestCase(BaseTestCase):
self.assertEquals(logger.logged, [
"*" * 80,
"Configuration options gathered from:",
- "command line args: ['--foo', 'this', '--blaa-bar', 'that']",
+ "command line args: ['--foo', 'this', '--blaa-bar', 'that', "\
+ "'--blaa-key', 'admin', '--passwd', 'hush']",
"config files: []",
"=" * 80,
"config_file = []",
"foo = this",
- "blaa.bar = that",
+ "passwd = ****",
+ "blaa.bar = that",
+ "blaa.key = *****",
"*" * 80,
])