19645558 problem in SERVICE/KEYSTONE
authorDrew Fisher <drew.fisher@oracle.com>
Fri, 19 Sep 2014 13:47:29 -0600
changeset 2102 eaee380e5cad
parent 2101 4016cd530eeb
child 2103 92b50cf5c69e
19645558 problem in SERVICE/KEYSTONE
components/openstack/keystone/patches/08-CVE-2014-3621.patch
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/openstack/keystone/patches/08-CVE-2014-3621.patch	Fri Sep 19 13:47:29 2014 -0600
@@ -0,0 +1,184 @@
+This upstream patch addresses CVE-2014-3621 and is tracked under
+Launchpad bug 1354208.  It is addressed in Icehouse 2014.1.3 and
+Havana 2013.2.4
+
+From 52714633c9a4dae5e60279217090859aa6dbcb4f Mon Sep 17 00:00:00 2001
+From: David Stanek <[email protected]>
+Date: Fri, 15 Aug 2014 13:30:33 -0500
+Subject: [PATCH] Adds a whitelist for endpoint catalog substitution
+
+Change-Id: If02327d70d0143d805969fe927898f08eb84c4c2
+Closes-Bug: #1354208
+---
+ etc/keystone.conf.sample                 |    7 ++++
+ keystone/catalog/core.py                 |    4 ++
+ keystone/common/config.py                |   14 ++++++-
+ keystone/common/utils.py                 |   12 ++++++
+ keystone/tests/unit/catalog/test_core.py |   62 ++++++++++++++++++++++++++++++
+ 5 files changed, 97 insertions(+), 2 deletions(-)
+ create mode 100644 keystone/tests/unit/__init__.py
+ create mode 100644 keystone/tests/unit/catalog/__init__.py
+ create mode 100644 keystone/tests/unit/catalog/test_core.py
+
+diff --git a/etc/keystone.conf.sample b/etc/keystone.conf.sample
+index d7e1c44..c24f8ff 100644
+--- a/etc/keystone.conf.sample
++++ b/etc/keystone.conf.sample
+@@ -190,6 +190,13 @@
+ 
+ # template_file = default_catalog.templates
+ 
++# (Deprecated) 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. This
++# option will be removed in Juno. (list value)
++#endpoint_substitution_whitelist=tenant_id,user_id,public_bind_host,admin_bind_hostompute_hostompute_port,admin_port,public_port,public_endpoint,admin_endpoint
++
+ [endpoint_filter]
+ # extension for creating associations between project and endpoints in order to
+ # provide a tailored catalog for project-scoped token requests.
+diff --git a/keystone/catalog/core.py b/keystone/catalog/core.py
+index 7cc49d5..ebd56ed 100644
+--- a/keystone/catalog/core.py
++++ b/keystone/catalog/core.py
+@@ -19,6 +19,7 @@
+ 
+ from keystone.common import dependency
+ from keystone.common import manager
++from keystone.common import utils
+ from keystone import config
+ from keystone import exception
+ from keystone.openstack.common import log as logging
+@@ -30,6 +31,9 @@ LOG = logging.getLogger(__name__)
+ 
+ def format_url(url, data):
+     """Safely string formats a user-defined URL with the given data."""
++    data = utils.WhiteListedItemFilter(
++        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 f1a7b74..7199c43 100644
+--- a/keystone/common/config.py
++++ b/keystone/common/config.py
+@@ -260,8 +260,18 @@ FILE_OPTIONS = {
+         cfg.StrOpt('template_file',
+                    default='default_catalog.templates'),
+         cfg.StrOpt('driver',
+-                   default='keystone.catalog.backends.sql.Catalog')]}
+-
++                   default='keystone.catalog.backends.sql.Catalog'),
++        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='(Deprecated) 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. This option will be '
++                         'removed in Juno.')]}
+ 
+ CONF = cfg.CONF
+ 
+diff --git a/keystone/common/utils.py b/keystone/common/utils.py
+index 402f8a2..3d4a62a 100644
+--- a/keystone/common/utils.py
++++ b/keystone/common/utils.py
+@@ -516,3 +516,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 WhiteListedItemFilter(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/__init__.py b/keystone/tests/unit/__init__.py
+new file mode 100644
+index 0000000..e69de29
+diff --git a/keystone/tests/unit/catalog/__init__.py b/keystone/tests/unit/catalog/__init__.py
+new file mode 100644
+index 0000000..e69de29
+diff --git a/keystone/tests/unit/catalog/test_core.py b/keystone/tests/unit/catalog/test_core.py
+new file mode 100644
+index 0000000..b4372b9
+--- /dev/null
++++ b/keystone/tests/unit/catalog/test_core.py
+@@ -0,0 +1,62 @@
++# Licensed under the Apache License, Version 2.0 (the "License"); you may
++# not use this file except in compliance with the License. You may obtain
++# a copy of the License at
++#
++#      http://www.apache.org/licenses/LICENSE-2.0
++#
++# Unless required by applicable law or agreed to in writing, software
++# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
++# License for the specific language governing permissions and limitations
++# under the License.
++
++from keystone.catalog import core
++from keystone import config
++from keystone import exception
++from keystone import tests
++
++
++CONF = config.CONF
++
++
++class FormatUrlTests(tests.TestCase):
++
++    def setUp(self):
++        super(FormatUrlTests, self).setUp()
++        whitelist = ['host', 'port', 'part1', 'part2']
++        self.opt_in_group('catalog', endpoint_substitution_whitelist=whitelist)
++
++    def test_successful_formatting(self):
++        url_template = 'http://%(host)s:%(port)d/%(part1)s/%(part2)s'
++        values = {'host': 'server', 'port': 9090, 'part1': 'A', 'part2': 'B'}
++        actual_url = core.format_url(url_template, values)
++
++        expected_url = 'http://server:9090/A/B'
++        self.assertEqual(actual_url, expected_url)
++
++    def test_raises_malformed_on_missing_key(self):
++        self.assertRaises(exception.MalformedEndpoint,
++                          core.format_url,
++                          "http://%(foo)s/%(bar)s",
++                          {"foo": "1"})
++
++    def test_raises_malformed_on_wrong_type(self):
++        self.assertRaises(exception.MalformedEndpoint,
++                          core.format_url,
++                          "http://%foo%s",
++                          {"foo": "1"})
++
++    def test_raises_malformed_on_incomplete_format(self):
++        self.assertRaises(exception.MalformedEndpoint,
++                          core.format_url,
++                          "http://%(foo)",
++                          {"foo": "1"})
++
++    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.7.9.5
+