From b0be97f0dd82ba21448a049ea1306118dd53c38d Mon Sep 17 00:00:00 2001 From: David Stanek Date: Fri, 15 Aug 2014 11:57:07 -0500 Subject: [PATCH] Adds a whitelist for endpoint catalog substitution Change-Id: If02327d70d0143d805969fe927898f08eb84c4c2 Closes-Bug: #1354208 --- keystone/catalog/core.py | 4 ++++ keystone/common/config.py | 12 +++++++++++- keystone/common/utils.py | 12 ++++++++++++ keystone/tests/unit/catalog/test_core.py | 23 ++++++++++++++++++++--- 4 files changed, 47 insertions(+), 4 deletions(-) diff --git a/keystone/catalog/core.py b/keystone/catalog/core.py index 924f6eb..332e128 100644 --- a/keystone/catalog/core.py +++ b/keystone/catalog/core.py @@ -22,6 +22,7 @@ import six from keystone.common import dependency from keystone.common import driver_hints from keystone.common import manager +from keystone.common import utils from keystone import config from keystone import exception from keystone.openstack.common.gettextutils import _ @@ -34,6 +35,9 @@ LOG = log.getLogger(__name__) def format_url(url, data): """Safely string formats a user-defined URL with the given data.""" + data = utils.WhiteListedFormatter( + CONF.catalog.endpoint_substitution_whitelist, + data) try: result = url.replace('$(', '%(') % data except AttributeError: diff --git a/keystone/common/config.py b/keystone/common/config.py index 85c49f8..1552092 100644 --- a/keystone/common/config.py +++ b/keystone/common/config.py @@ -640,7 +640,17 @@ FILE_OPTIONS = { help='Keystone catalog backend driver.'), cfg.IntOpt('list_limit', default=None, help='Maximum number of entities that will be returned ' - 'in a catalog collection.')], + 'in a catalog collection.'), + cfg.ListOpt('endpoint_substitution_whitelist', + default=['tenant_id', 'user_id', 'public_bind_host', + 'admin_bind_host', 'compute_host', 'compute_port', + 'admin_port', 'public_port', 'public_endpoint', + 'admin_endpoint'], + help='List of possible substitutions for use in ' + 'formatting endpoints. Use caution when modifying ' + 'this list. It will give users with permission to ' + 'create endpoints the ability to see those values ' + 'in your configuration file.')], 'kvs': [ cfg.ListOpt('backends', default=[], help='Extra dogpile.cache backend modules to register ' diff --git a/keystone/common/utils.py b/keystone/common/utils.py index c720d21..0f0de7d 100644 --- a/keystone/common/utils.py +++ b/keystone/common/utils.py @@ -525,3 +525,15 @@ def make_dirs(path, mode=None, user=None, group=None, log=None): raise EnvironmentError("makedirs('%s'): %s" % (path, exc.strerror)) set_permissions(path, mode, user, group, log) + + +class WhiteListedFormatter(object): + + def __init__(self, whitelist, data): + self._whitelist = set(whitelist or []) + self._data = data + + def __getitem__(self, name): + if name not in self._whitelist: + raise KeyError + return self._data[name] diff --git a/keystone/tests/unit/catalog/test_core.py b/keystone/tests/unit/catalog/test_core.py index 7b142ed..618899f 100644 --- a/keystone/tests/unit/catalog/test_core.py +++ b/keystone/tests/unit/catalog/test_core.py @@ -10,13 +10,21 @@ # License for the specific language governing permissions and limitations # under the License. -import testtools - from keystone.catalog import core +from keystone import config from keystone import exception +from keystone import tests + + +CONF = config.CONF + +class FormatUrlTests(tests.TestCase): -class FormatUrlTests(testtools.TestCase): + def setUp(self): + super(FormatUrlTests, self).setUp() + whitelist = ['host', 'port', 'part1', 'part2'] + CONF.catalog.endpoint_substitution_whitelist = whitelist def test_successful_formatting(self): url_template = 'http://%(host)s:%(port)d/%(part1)s/%(part2)s' @@ -53,3 +61,12 @@ class FormatUrlTests(testtools.TestCase): _test(None) _test(object()) + + def test_substitution_with_key_not_whitelisted(self): + url_template = 'http://%(host)s:%(port)d/%(part1)s/%(part2)s/%(part3)s' + values = {'host': 'server', 'port': 9090, + 'part1': 'A', 'part2': 'B', 'part3': 'C'} + self.assertRaises(exception.MalformedEndpoint, + core.format_url, + url_template, + values) -- 1.8.3.2