diff options
| author | Eoghan Glynn <eglynn@redhat.com> | 2012-03-22 16:54:26 +0000 |
|---|---|---|
| committer | Eoghan Glynn <eglynn@redhat.com> | 2012-03-22 17:36:55 +0000 |
| commit | a24376c0a87bc8631f61edab8cd463a5c26aa494 (patch) | |
| tree | b30a47faedd2c648aced001ae8a2a7d84babb89d | |
| parent | 13ed88186bb5c6a1900c3bb742d06743fd21ac58 (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.py | 27 | ||||
| -rw-r--r-- | tests/unit/test_cfg.py | 12 |
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, ]) |
