128 lines
4.9 KiB
Python
128 lines
4.9 KiB
Python
# Copyright 2012 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.
|
|
|
|
from oslo_log import log
|
|
from oslo_log import versionutils
|
|
from oslo_serialization import jsonutils
|
|
|
|
from keystone.common import authorization
|
|
from keystone.common import wsgi
|
|
from keystone import exception
|
|
|
|
|
|
LOG = log.getLogger(__name__)
|
|
|
|
|
|
class TokenAuthMiddleware(wsgi.Middleware):
|
|
def process_request(self, request):
|
|
context = request.environ.setdefault(wsgi.CONTEXT_ENV, {})
|
|
|
|
token = request.headers.get(authorization.AUTH_TOKEN_HEADER)
|
|
context['token_id'] = token
|
|
|
|
subject_token = request.headers.get(authorization.SUBJECT_TOKEN_HEADER)
|
|
if subject_token:
|
|
context['subject_token_id'] = subject_token
|
|
|
|
|
|
class AdminTokenAuthMiddleware(wsgi.Middleware):
|
|
# NOTE(notmorgan): DEPRECATED FOR REMOVAL does nothing but warn to remove
|
|
# from pipeline
|
|
|
|
@versionutils.deprecated(
|
|
as_of=versionutils.deprecated.PIKE,
|
|
what='AdminTokenAuthMiddleware in the paste-ini pipeline.',
|
|
remove_in=+1)
|
|
def __init__(self, application):
|
|
super(AdminTokenAuthMiddleware, self).__init__(application)
|
|
# NOTE(notmorgan): This is deprecated and emits a significant error
|
|
# message to make sure deployers update their deployments so in the
|
|
# future release upgrade the deployment does not break.
|
|
LOG.error('The admin_token_auth middleware functionality has been '
|
|
'merged into the main auth middleware '
|
|
'(keystone.middleware.auth.AuthContextMiddleware). '
|
|
'`admin_token_auth` must be removed from the '
|
|
'[pipeline:api_v3], [pipeline:admin_api], and '
|
|
'[pipeline:public_api] sections of your paste ini '
|
|
'file. The [filter:admin_token_auth] block will also '
|
|
'need to be removed from your paste ini file. Failure '
|
|
'to remove these elements from your paste ini file will '
|
|
'result in keystone to no longer start/run when the '
|
|
'`admin_token_auth` is removed in the Queens release.')
|
|
|
|
|
|
class JsonBodyMiddleware(wsgi.Middleware):
|
|
"""Middleware to allow method arguments to be passed as serialized JSON.
|
|
|
|
Accepting arguments as JSON is useful for accepting data that may be more
|
|
complex than simple primitives.
|
|
|
|
Filters out the parameters `self`, `context` and anything beginning with
|
|
an underscore.
|
|
|
|
"""
|
|
|
|
def process_request(self, request):
|
|
# Abort early if we don't have any work to do
|
|
params_json = request.body
|
|
if not params_json:
|
|
return
|
|
|
|
# Reject unrecognized content types. Empty string indicates
|
|
# the client did not explicitly set the header
|
|
if request.content_type not in ('application/json', ''):
|
|
e = exception.ValidationError(attribute='application/json',
|
|
target='Content-Type header')
|
|
return wsgi.render_exception(e, request=request)
|
|
|
|
params_parsed = {}
|
|
try:
|
|
params_parsed = jsonutils.loads(params_json)
|
|
except ValueError:
|
|
e = exception.ValidationError(attribute='valid JSON',
|
|
target='request body')
|
|
return wsgi.render_exception(e, request=request)
|
|
finally:
|
|
if not params_parsed:
|
|
params_parsed = {}
|
|
|
|
if not isinstance(params_parsed, dict):
|
|
e = exception.ValidationError(attribute='valid JSON object',
|
|
target='request body')
|
|
return wsgi.render_exception(e, request=request)
|
|
|
|
params = {}
|
|
for k, v in params_parsed.items():
|
|
if k in ('self', 'context'):
|
|
continue
|
|
if k.startswith('_'):
|
|
continue
|
|
params[k] = v
|
|
|
|
request.environ[wsgi.PARAMS_ENV] = params
|
|
|
|
|
|
class NormalizingFilter(wsgi.Middleware):
|
|
"""Middleware filter to handle URL normalization."""
|
|
|
|
def process_request(self, request):
|
|
"""Normalize URLs."""
|
|
# Removes a trailing slash from the given path, if any.
|
|
if (len(request.environ['PATH_INFO']) > 1 and
|
|
request.environ['PATH_INFO'][-1] == '/'):
|
|
request.environ['PATH_INFO'] = request.environ['PATH_INFO'][:-1]
|
|
# Rewrites path to root if no path is given.
|
|
elif not request.environ['PATH_INFO']:
|
|
request.environ['PATH_INFO'] = '/'
|