From c4c1770475b4b0cbd57bc56677eeca1326973f76 Mon Sep 17 00:00:00 2001 From: Hongbin Lu Date: Tue, 21 Nov 2017 20:05:21 +0000 Subject: [PATCH] placement: skip authentication on root URI The placement API GET / is for version discovery. Skip authentication on this URL. The change to test_deploy is required to make it request a URL that requires authentication. It had been using /. Change-Id: I5ed1f7a607620c43671e90eaf8a1f6285f1d15e4 Closes-Bug: #1733630 --- nova/api/openstack/placement/auth.py | 34 ++++++++++++++++++- nova/api/openstack/placement/deploy.py | 3 +- .../placement/gabbits/confirm-auth.yaml | 16 +++++++-- .../api/openstack/placement/test_deploy.py | 2 +- 4 files changed, 48 insertions(+), 7 deletions(-) diff --git a/nova/api/openstack/placement/auth.py b/nova/api/openstack/placement/auth.py index 13fae4af9b3d..0a072b5fb6d5 100644 --- a/nova/api/openstack/placement/auth.py +++ b/nova/api/openstack/placement/auth.py @@ -11,6 +11,7 @@ # under the License. +from keystonemiddleware import auth_token from oslo_context import context from oslo_db.sqlalchemy import enginefacade from oslo_log import log as logging @@ -37,6 +38,9 @@ class NoAuthMiddleware(Middleware): @webob.dec.wsgify def __call__(self, req): + if req.environ['PATH_INFO'] == '/': + return self.application + if 'X-Auth-Token' not in req.headers: return webob.exc.HTTPUnauthorized() @@ -68,9 +72,37 @@ class PlacementKeystoneContext(Middleware): ctx = RequestContext.from_environ( req.environ, request_id=req_id) - if ctx.user_id is None: + if ctx.user_id is None and req.environ['PATH_INFO'] != '/': LOG.debug("Neither X_USER_ID nor X_USER found in request") return webob.exc.HTTPUnauthorized() req.environ['placement.context'] = ctx return self.application + + +class PlacementAuthProtocol(auth_token.AuthProtocol): + """A wrapper on Keystone auth_token middleware. + + Does not perform verification of authentication tokens + for root in the API. + + """ + def __init__(self, app, conf): + self._placement_app = app + super(PlacementAuthProtocol, self).__init__(app, conf) + + def __call__(self, environ, start_response): + if environ['PATH_INFO'] == '/': + return self._placement_app(environ, start_response) + + return super(PlacementAuthProtocol, self).__call__( + environ, start_response) + + +def filter_factory(global_conf, **local_conf): + conf = global_conf.copy() + conf.update(local_conf) + + def auth_filter(app): + return PlacementAuthProtocol(app, conf) + return auth_filter diff --git a/nova/api/openstack/placement/deploy.py b/nova/api/openstack/placement/deploy.py index 821aeb61f8ed..fe440cf1f5fb 100644 --- a/nova/api/openstack/placement/deploy.py +++ b/nova/api/openstack/placement/deploy.py @@ -11,7 +11,6 @@ # under the License. """Deployment handling for Placmenent API.""" -from keystonemiddleware import auth_token import oslo_middleware from oslo_middleware import cors @@ -41,7 +40,7 @@ def deploy(conf, project_name): # Do not use 'oslo_config_project' param here as the conf # location may have been overridden earlier in the deployment # process with OS_PLACEMENT_CONFIG_DIR in wsgi.py. - auth_middleware = auth_token.filter_factory( + auth_middleware = auth.filter_factory( {}, oslo_config_config=conf) # Pass in our CORS config, if any, manually as that's a) diff --git a/nova/tests/functional/api/openstack/placement/gabbits/confirm-auth.yaml b/nova/tests/functional/api/openstack/placement/gabbits/confirm-auth.yaml index 68742e5d9b61..d4e17f6ef391 100644 --- a/nova/tests/functional/api/openstack/placement/gabbits/confirm-auth.yaml +++ b/nova/tests/functional/api/openstack/placement/gabbits/confirm-auth.yaml @@ -11,12 +11,22 @@ defaults: accept: application/json tests: - - name: no token gets 401 + - name: no token gets 200 at root GET: / - status: 401 + status: 200 - - name: with token 200 + - name: with token 200 at root GET: / request_headers: x-auth-token: admin:admin status: 200 + + - name: no token gets 401 + GET: /resource_providers + status: 401 + + - name: with token 200 + GET: /resource_providers + request_headers: + x-auth-token: admin:admin + status: 200 diff --git a/nova/tests/unit/api/openstack/placement/test_deploy.py b/nova/tests/unit/api/openstack/placement/test_deploy.py index 938b8b1fd0b4..7413d07fcd7e 100644 --- a/nova/tests/unit/api/openstack/placement/test_deploy.py +++ b/nova/tests/unit/api/openstack/placement/test_deploy.py @@ -35,7 +35,7 @@ class DeployTest(test.NoDBTestCase): # ensure that the auth_token middleware is chosen self.flags(auth_strategy='keystone', group='api') app = deploy.deploy(CONF, 'nova') - req = webob.Request.blank('/', method="GET") + req = webob.Request.blank('/resource_providers', method="GET") response = req.get_response(app)