summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2014-03-28 00:49:30 +0000
committerGerrit Code Review <review@openstack.org>2014-03-28 00:49:30 +0000
commit2207dcca9014092a15f8e0377ea07c1df910097a (patch)
tree96a6f22e2b83e6945f8311af611f66f925af15ab
parentaac9668a992c730eb7b0b21831d34214399c58f3 (diff)
parentde3de047d1163775cebda55ef04603e0a93777b2 (diff)
downloadironic-2207dcca9014092a15f8e0377ea07c1df910097a.tar.gz
Merge "Process public API list as regular expressions"
-rw-r--r--ironic/api/hooks.py5
-rw-r--r--ironic/api/middleware/auth_token.py25
-rw-r--r--ironic/common/exception.py4
-rw-r--r--ironic/tests/api/test_acl.py13
4 files changed, 38 insertions, 9 deletions
diff --git a/ironic/api/hooks.py b/ironic/api/hooks.py
index 29eec61cc..d706edf8d 100644
--- a/ironic/api/hooks.py
+++ b/ironic/api/hooks.py
@@ -21,7 +21,6 @@ from pecan import hooks
from webob import exc
from ironic.common import context
-from ironic.common import utils
from ironic.conductor import rpcapi
from ironic.db import api as dbapi
from ironic.openstack.common import policy
@@ -75,11 +74,9 @@ class ContextHook(hooks.PecanHook):
auth_token = state.request.headers.get('X-Auth-Token')
creds = {'roles': state.request.headers.get('X-Roles', '').split(',')}
+ is_public_api = state.request.environ.get('is_public_api', False)
is_admin = policy.check('admin', state.request.headers, creds)
- path = utils.safe_rstrip(state.request.path, '/')
- is_public_api = path in self.public_api_routes
-
state.request.context = context.RequestContext(
auth_token=auth_token,
user=user_id,
diff --git a/ironic/api/middleware/auth_token.py b/ironic/api/middleware/auth_token.py
index d9c32b111..9cad079b3 100644
--- a/ironic/api/middleware/auth_token.py
+++ b/ironic/api/middleware/auth_token.py
@@ -12,9 +12,15 @@
# License for the specific language governing permissions and limitations
# under the License.
+import re
+
from keystoneclient.middleware import auth_token
+from ironic.common import exception
from ironic.common import utils
+from ironic.openstack.common import log
+
+LOG = log.getLogger(__name__)
class AuthTokenMiddleware(auth_token.AuthProtocol):
@@ -25,14 +31,29 @@ class AuthTokenMiddleware(auth_token.AuthProtocol):
"""
def __init__(self, app, conf, public_api_routes=[]):
- self.public_api_routes = set(public_api_routes)
+ route_pattern_tpl = '%s(\.json|\.xml)?$'
+
+ try:
+ self.public_api_routes = [re.compile(route_pattern_tpl % route_tpl)
+ for route_tpl in public_api_routes]
+ except re.error as e:
+ msg = _('Cannot compile public API routes: %s') % e
+
+ LOG.error(msg)
+ raise exception.ConfigInvalid(error_msg=msg)
super(AuthTokenMiddleware, self).__init__(app, conf)
def __call__(self, env, start_response):
path = utils.safe_rstrip(env.get('PATH_INFO'), '/')
- if path in self.public_api_routes:
+ # The information whether the API call is being performed against the
+ # public API is required for some other components. Saving it to the
+ # WSGI environment is reasonable thereby.
+ env['is_public_api'] = any(map(lambda pattern: re.match(pattern, path),
+ self.public_api_routes))
+
+ if env['is_public_api']:
return self.app(env, start_response)
return super(AuthTokenMiddleware, self).__call__(env, start_response)
diff --git a/ironic/common/exception.py b/ironic/common/exception.py
index 220fde0b6..0af15ea42 100644
--- a/ironic/common/exception.py
+++ b/ironic/common/exception.py
@@ -353,3 +353,7 @@ class NoFreeConductorWorker(TemporaryFailure):
class VendorPassthruException(IronicException):
pass
+
+
+class ConfigInvalid(IronicException):
+ message = _("Invalid configuration file. %(error_msg)s")
diff --git a/ironic/tests/api/test_acl.py b/ironic/tests/api/test_acl.py
index 57056fc4e..0dfb8a499 100644
--- a/ironic/tests/api/test_acl.py
+++ b/ironic/tests/api/test_acl.py
@@ -83,6 +83,13 @@ class TestACL(base.FunctionalTest):
# expect_errors should be set to True: If expect_errors is set to False
# the response gets converted to JSON and we cannot read the response
# code so easy.
- response = self.get_json('/', expect_errors=True)
-
- self.assertEqual(200, response.status_int)
+ for route in ('/', '/v1'):
+ response = self.get_json(route,
+ path_prefix='', expect_errors=True)
+ self.assertEqual(200, response.status_int)
+
+ def test_public_api_with_path_extensions(self):
+ for route in ('/v1/', '/v1.json', '/v1.xml'):
+ response = self.get_json(route,
+ path_prefix='', expect_errors=True)
+ self.assertEqual(200, response.status_int)