]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Always validate auth_uri with allowed_auth_uris
authorSteve Baker <sbaker@redhat.com>
Mon, 19 Aug 2013 02:35:06 +0000 (14:35 +1200)
committerSteve Baker <sbaker@redhat.com>
Wed, 21 Aug 2013 23:10:21 +0000 (11:10 +1200)
The original intention was to allow heat to orchestrate
on any requested cloud when allowed_auth_uris is configured
with an empty list.

This change makes all requests be validated against
allowed_auth_uris for the following reasons:
- there is a potential security issue with requests
  being authorised by a fake keystone, allowing an exploit in
  heat to be executed without any valid authentication factors
  first being presented.
- ec2token middleware will also need to be made multi-cloud aware
  however as a compatible API it is not possible to specify the desired
  auth_uri with each request. Instead ec2token will need a list of
  configured endpoints so that it can try each one until a request
  is authenticated.

Change-Id: I3d6b7edf381a66b87b6e1fae07bc5dbe9db024bc

etc/heat/heat.conf.sample
heat/common/auth_password.py
heat/common/config.py
heat/tests/test_auth_password.py

index 8a31cd2074b863d67b088fd53a807b723966e5d8..b4e6872f17b6d3c2f8fce7d95d3cf68a8d4df611 100644 (file)
 # Allow orchestration of multiple clouds (boolean value)
 #multi_cloud=false
 
-# Allowed targets for auth_uri when multi_cloud is enabled.
-# If empty, all targets will be allowed. (list value)
+# Allowed keystone endpoints for auth_uri when multi_cloud is
+# enabled. At least one endpoint needs to be specified. (list
+# value)
 #allowed_auth_uris=
 
 
index 9164710d38eee7db34ede26f64c0bb6e746a40a2..1ccdb2b9f5a41c00deca8168f9f85cb6f7264720 100644 (file)
@@ -117,8 +117,9 @@ class KeystonePasswordAuthProtocol(object):
                                     'X-Auth-Url'))
             return resp(env, start_response)
         allowed = cfg.CONF.auth_password.allowed_auth_uris
-        if allowed and not auth_url in allowed:
-            resp = HTTPUnauthorized(_('Header X-Auth-Url "%s" not allowed')
+        if auth_url not in allowed:
+            resp = HTTPUnauthorized(_('Header X-Auth-Url "%s" not an allowed '
+                                      'endpoint')
                                     % auth_url)
             return resp(env, start_response)
         return None
index 8feeacb30d1e6a2be0a6b74285a5307f696545e9..918ae4d2f8e33933c159c89ecc70e2d9bee850eb 100644 (file)
@@ -117,8 +117,9 @@ auth_password_opts = [
                 help=_('Allow orchestration of multiple clouds')),
     cfg.ListOpt('allowed_auth_uris',
                 default=[],
-                help=_('Allowed targets for auth_uri when multi_cloud is '
-                       'enabled.  If empty, all targets will be allowed.'))]
+                help=_('Allowed keystone endpoints for auth_uri when '
+                       'multi_cloud is enabled. At least one endpoint needs '
+                       'to be specified.'))]
 
 cfg.CONF.register_opts(db_opts)
 cfg.CONF.register_opts(engine_opts)
index 4aa156409a4dd27d3a59abb4ba97d30af5f33e09..aba9b2b518b66ada96d54a7b03ae59d750d6cf99 100644 (file)
@@ -124,7 +124,8 @@ class KeystonePasswordAuthProtocolTest(HeatTestCase):
         self.middleware(req.environ, self._start_fake_response)
         self.assertEqual(self.response_status, 401)
 
-    def _test_multi_cloud(self, allowed_auth_uris=[]):
+    def test_multi_cloud(self):
+        allowed_auth_uris = ['http://multicloud.test.com:5000/v2.0']
         cfg.CONF.set_override('multi_cloud', True, group='auth_password')
         auth_url = 'http://multicloud.test.com:5000/v2.0'
         cfg.CONF.set_override('allowed_auth_uris',
@@ -147,11 +148,18 @@ class KeystonePasswordAuthProtocolTest(HeatTestCase):
         self.middleware(req.environ, self._start_fake_response)
         self.m.VerifyAll()
 
-    def test_multi_cloud(self):
-        self._test_multi_cloud(['http://multicloud.test.com:5000/v2.0'])
-
     def test_multi_cloud_empty_allowed_uris(self):
-        self._test_multi_cloud()
+        cfg.CONF.set_override('multi_cloud', True, group='auth_password')
+        auth_url = 'http://multicloud.test.com:5000/v2.0'
+        cfg.CONF.set_override('allowed_auth_uris',
+                              [],
+                              group='auth_password')
+        req = webob.Request.blank('/tenant_id1/')
+        req.headers['X_AUTH_USER'] = 'user_name1'
+        req.headers['X_AUTH_KEY'] = 'goodpassword'
+        req.headers['X_AUTH_URL'] = auth_url
+        self.middleware(req.environ, self._start_fake_response)
+        self.assertEqual(self.response_status, 401)
 
     def test_multi_cloud_target_not_allowed(self):
         cfg.CONF.set_override('multi_cloud', True, group='auth_password')