Merge "Base use webob"

This commit is contained in:
Jenkins 2015-06-04 21:06:28 +00:00 committed by Gerrit Code Review
commit 6f10b9c8e1
4 changed files with 31 additions and 98 deletions
keystonemiddleware

@ -212,6 +212,7 @@ from keystoneclient import session
from oslo_config import cfg
from oslo_serialization import jsonutils
import six
import webob.dec
from keystonemiddleware.auth_token import _auth
from keystonemiddleware.auth_token import _base
@ -221,7 +222,6 @@ from keystonemiddleware.auth_token import _identity
from keystonemiddleware.auth_token import _revocations
from keystonemiddleware.auth_token import _signing_dir
from keystonemiddleware.auth_token import _user_plugin
from keystonemiddleware.auth_token import _utils
from keystonemiddleware.i18n import _, _LC, _LE, _LI, _LW
@ -527,19 +527,8 @@ class AuthProtocol(object):
else:
return CONF[group][name]
def _call_app(self, env, start_response):
# NOTE(jamielennox): We wrap the given start response so that if an
# application with a 'delay_auth_decision' setting fails, or otherwise
# raises Unauthorized that we include the Authentication URL headers.
def _fake_start_response(status, response_headers, exc_info=None):
if status.startswith('401'):
response_headers.extend(self._reject_auth_headers)
return start_response(status, response_headers, exc_info)
return self._app(env, _fake_start_response)
def __call__(self, env, start_response):
@webob.dec.wsgify
def __call__(self, request):
"""Handle incoming request.
Authenticate send downstream on success. Reject request if
@ -556,8 +545,8 @@ class AuthProtocol(object):
env.get('HTTP_X_SERVICE_ROLES')))
return msg
self._token_cache.initialize(env)
self._remove_auth_headers(env)
self._token_cache.initialize(request.environ)
self._remove_auth_headers(request.environ)
try:
user_auth_ref = None
@ -565,58 +554,61 @@ class AuthProtocol(object):
try:
self._LOG.debug('Authenticating user token')
user_token_info = self._get_user_token_from_header(env)
user_token_info = self._get_user_token_from_header(
request.environ)
user_auth_ref, user_token_info = self._validate_token(
user_token_info, env)
env['keystone.token_info'] = user_token_info
user_token_info, request.environ)
request.environ['keystone.token_info'] = user_token_info
user_headers = self._build_user_headers(user_auth_ref)
self._add_headers(env, user_headers)
self._add_headers(request.environ, user_headers)
except exc.InvalidToken:
if self._delay_auth_decision:
self._LOG.info(
_LI('Invalid user token - deferring reject '
'downstream'))
self._add_headers(env, {'X-Identity-Status': 'Invalid'})
self._add_headers(request.environ,
{'X-Identity-Status': 'Invalid'})
else:
self._LOG.info(
_LI('Invalid user token - rejecting request'))
return self._reject_request(env, start_response)
self._reject_request()
try:
self._LOG.debug('Authenticating service token')
serv_token = self._get_service_token_from_header(env)
serv_token = self._get_service_token_from_header(
request.environ)
if serv_token is not None:
serv_auth_ref, serv_token_info = self._validate_token(
serv_token, env)
serv_token, request.environ)
serv_headers = self._build_service_headers(serv_auth_ref)
self._add_headers(env, serv_headers)
self._add_headers(request.environ, serv_headers)
except exc.InvalidToken:
if self._delay_auth_decision:
self._LOG.info(
_LI('Invalid service token - deferring reject '
'downstream'))
self._add_headers(env,
self._add_headers(request.environ,
{'X-Service-Identity-Status': 'Invalid'})
else:
self._LOG.info(
_LI('Invalid service token - rejecting request'))
return self._reject_request(env, start_response)
self._reject_request()
env['keystone.token_auth'] = _user_plugin.UserAuthPlugin(
user_auth_ref, serv_auth_ref)
p = _user_plugin.UserAuthPlugin(user_auth_ref, serv_auth_ref)
request.environ['keystone.token_auth'] = p
except exc.ServiceError as e:
self._LOG.critical(_LC('Unable to obtain admin token: %s'), e)
return self._do_503_error(env, start_response)
raise webob.exc.HTTPServiceUnavailable()
self._LOG.debug("Received request from %s", _fmt_msg(env))
self._LOG.debug("Received request from %s", _fmt_msg(request.environ))
return self._call_app(env, start_response)
response = request.get_response(self._app)
def _do_503_error(self, env, start_response):
resp = _utils.MiniResp('Service unavailable', env)
start_response('503 Service Unavailable', resp.headers)
return resp.body
if response.status_int == 401:
response.headers.extend(self._reject_auth_headers)
return response
def _init_auth_headers(self):
"""Initialize auth header list.
@ -683,7 +675,7 @@ class AuthProtocol(object):
header_val = 'Keystone uri=\'%s\'' % self._auth_uri
return [('WWW-Authenticate', header_val)]
def _reject_request(self, env, start_response):
def _reject_request(self):
"""Redirect client to auth server.
:param env: wsgi request environment
@ -691,10 +683,8 @@ class AuthProtocol(object):
:returns: HTTPUnauthorized http response
"""
resp = _utils.MiniResp('Authentication required',
env, self._reject_auth_headers)
start_response('401 Unauthorized', resp.headers)
return resp.body
raise webob.exc.HTTPUnauthorized(body='Authentication required',
headers=self._reject_auth_headers)
def _token_hashes(self, token):
"""Generate a list of hashes that the current token may be cached as.

@ -1,25 +0,0 @@
# 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.
class MiniResp(object):
def __init__(self, error_message, env, headers=[]):
# The HEAD method is unique: it must never return a body, even if
# it reports an error (RFC-2616 clause 9.4). We relieve callers
# from varying the error responses depending on the method.
if env['REQUEST_METHOD'] == 'HEAD':
self.body = ['']
else:
self.body = [error_message.encode()]
self.headers = list(headers)
self.headers.append(('Content-type', 'text/plain'))

@ -985,7 +985,6 @@ class CommonAuthTokenMiddlewareTest(object):
self.assertEqual(401, resp.status_int)
self.assertEqual("Keystone uri='https://keystone.example.com:1234'",
resp.headers['WWW-Authenticate'])
self.assertEqual('', resp.body)
def test_request_blank_token(self):
resp = self.call_middleware(headers={'X-Auth-Token': ''})

@ -1,31 +0,0 @@
# 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.
import testtools
from keystonemiddleware.auth_token import _utils
class TokenEncodingTest(testtools.TestCase):
def test_messages_encoded_as_bytes(self):
"""Test that string are passed around as bytes for PY3."""
msg = "This is an error"
class FakeResp(_utils.MiniResp):
def __init__(self, error, env):
super(FakeResp, self).__init__(error, env)
fake_resp = FakeResp(msg, dict(REQUEST_METHOD='GET'))
# On Py2 .encode() don't do much but that's better than to
# have a ifdef with six.PY3
self.assertEqual(msg.encode(), fake_resp.body[0])