52fe8c0285
This rips NoAuthMiddleware completely out of functional tests by: - Removing our override of [api]auth_strategy in ConfFixture, allowing it to default to ``keystone``. This causes the fake wsgi setup to go through the same pipeline as real API requests; so making that work entails... - Mocking out the keystonecontext piece of the paste pipeline to create the context previously mashed (somewhat inappropriately) into NoAuthMiddleware. In the future we may want to mock this more shallowly or find a way to make the req more realistic so it needn't be mocked at all, but for now this is close to what the noauth2 pipeline used to do. - Stubbing out the keystonemiddleware piece of the paste pipeline. In the future we should try to use keystonemiddleware's AuthTokenFixture so our tests can occur in a more realistic environment, but for now this is just mimicking what the noauth2 pipeline used to do; except for... - Removing the authentication portion of the TestOpenStackClient. This used to make an actual request(), which landed in NoAuthMiddleware, which was hacking together some headers (based, it appears, on a protocol which is many years out of date and no longer approximates what keystone does, which should be the point if it's going to exist at all). So now we just hack up the necessary headers inline. - Doing the addition of project_id in request URIs in OSAPIFixture. This is another thing that NoAuthMiddleware was doing inappropriately (IRL the project_id will either be part of the request from the start, or it won't). It was also only doing it part of the time; as a result, a couple of tests requesting version documents, which were previously not expecting the project ID to be present, needed to be modified to expect it. This better reflects reality. Change-Id: I459a605b4a9390f0e36356ca1fe432948159acd4
124 lines
4.1 KiB
Python
124 lines
4.1 KiB
Python
# Copyright (c) 2011 OpenStack Foundation
|
|
#
|
|
# 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.
|
|
"""
|
|
Common Auth Middleware.
|
|
|
|
"""
|
|
|
|
from oslo_log import log as logging
|
|
from oslo_log import versionutils
|
|
from oslo_serialization import jsonutils
|
|
import webob.dec
|
|
import webob.exc
|
|
|
|
from nova.api import wsgi
|
|
import nova.conf
|
|
from nova import context
|
|
from nova.i18n import _
|
|
|
|
|
|
CONF = nova.conf.CONF
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
def _load_pipeline(loader, pipeline):
|
|
filters = [loader.get_filter(n) for n in pipeline[:-1]]
|
|
app = loader.get_app(pipeline[-1])
|
|
filters.reverse()
|
|
for filter in filters:
|
|
app = filter(app)
|
|
return app
|
|
|
|
|
|
def pipeline_factory(loader, global_conf, **local_conf):
|
|
"""A paste pipeline replica that keys off of auth_strategy."""
|
|
versionutils.report_deprecated_feature(
|
|
LOG,
|
|
"The legacy V2 API code tree has been removed in Newton. "
|
|
"Please remove legacy v2 API entry from api-paste.ini, and use "
|
|
"V2.1 API or V2.1 API compat mode instead"
|
|
)
|
|
|
|
|
|
def pipeline_factory_v21(loader, global_conf, **local_conf):
|
|
"""A paste pipeline replica that keys off of auth_strategy."""
|
|
auth_strategy = CONF.api.auth_strategy
|
|
if auth_strategy == 'noauth2':
|
|
versionutils.report_deprecated_feature(
|
|
LOG,
|
|
"'[api]auth_strategy=noauth2' is deprecated as of the 21.0.0 "
|
|
"Ussuri release and will be removed in a future release. Please "
|
|
"remove any 'noauth2' entries from api-paste.ini; only the "
|
|
"'keystone' pipeline is supported."
|
|
)
|
|
return _load_pipeline(loader, local_conf[auth_strategy].split())
|
|
|
|
|
|
class InjectContext(wsgi.Middleware):
|
|
"""Add a 'nova.context' to WSGI environ."""
|
|
|
|
def __init__(self, context, *args, **kwargs):
|
|
self.context = context
|
|
super(InjectContext, self).__init__(*args, **kwargs)
|
|
|
|
@webob.dec.wsgify(RequestClass=wsgi.Request)
|
|
def __call__(self, req):
|
|
req.environ['nova.context'] = self.context
|
|
return self.application
|
|
|
|
|
|
class NovaKeystoneContext(wsgi.Middleware):
|
|
"""Make a request context from keystone headers."""
|
|
|
|
@staticmethod
|
|
def _create_context(env, **kwargs):
|
|
"""Create a context from a request environ.
|
|
|
|
This exists to make test stubbing easier.
|
|
"""
|
|
return context.RequestContext.from_environ(env, **kwargs)
|
|
|
|
@webob.dec.wsgify(RequestClass=wsgi.Request)
|
|
def __call__(self, req):
|
|
# Build a context, including the auth_token...
|
|
remote_address = req.remote_addr
|
|
if CONF.api.use_forwarded_for:
|
|
remote_address = req.headers.get('X-Forwarded-For', remote_address)
|
|
|
|
service_catalog = None
|
|
if req.headers.get('X_SERVICE_CATALOG') is not None:
|
|
try:
|
|
catalog_header = req.headers.get('X_SERVICE_CATALOG')
|
|
service_catalog = jsonutils.loads(catalog_header)
|
|
except ValueError:
|
|
raise webob.exc.HTTPInternalServerError(
|
|
_('Invalid service catalog json.'))
|
|
|
|
# NOTE(jamielennox): This is a full auth plugin set by auth_token
|
|
# middleware in newer versions.
|
|
user_auth_plugin = req.environ.get('keystone.token_auth')
|
|
|
|
ctx = self._create_context(
|
|
req.environ,
|
|
user_auth_plugin=user_auth_plugin,
|
|
remote_address=remote_address,
|
|
service_catalog=service_catalog)
|
|
|
|
if ctx.user_id is None:
|
|
LOG.debug("Neither X_USER_ID nor X_USER found in request")
|
|
return webob.exc.HTTPUnauthorized()
|
|
|
|
req.environ['nova.context'] = ctx
|
|
return self.application
|