Merge "Create an Auth Plugin to pass to users"

This commit is contained in:
Jenkins 2014-09-15 03:44:33 +00:00 committed by Gerrit Code Review
commit 766840fc00
3 changed files with 65 additions and 5 deletions

View File

@ -231,6 +231,7 @@ latex_documents = [
# If false, no module index is generated.
#latex_use_modindex = True
keystoneclient = 'http://docs.openstack.org/developer/python-keystoneclient/'
# Example configuration for intersphinx: refer to the Python standard library.
#intersphinx_mapping = {'python': ('http://docs.python.org/', None)}
intersphinx_mapping = {'keystoneclient': (keystoneclient, None),
}

View File

@ -143,6 +143,11 @@ keystone.token_info
Keystone token validation call, as well as basic information about
the tenant and user.
keystone.token_auth
A keystoneclient auth plugin that may be used with a
:py:class:`keystoneclient.session.Session`. This plugin will load the
authentication data provided to auth_token middleware.
"""
import contextlib
@ -154,6 +159,7 @@ import tempfile
import time
from keystoneclient import access
from keystoneclient.auth.identity import base as base_identity
from keystoneclient.auth.identity import v2
from keystoneclient.auth import token_endpoint
from keystoneclient.common import cms
@ -479,6 +485,38 @@ class _MiniResp(object):
self.headers.append(('Content-type', 'text/plain'))
class _UserAuthPlugin(base_identity.BaseIdentityPlugin):
"""The incoming authentication credentials.
A plugin that represents the incoming user credentials. This can be
consumed by applications.
This object is not expected to be constructed directly by users. It is
created and passed by auth_token middleware and then can be used as the
authentication plugin when communicating via a session.
"""
def __init__(self, user_token, auth_ref):
# FIXME(jamielennox): set reauthenticate=False here when keystoneclient
# 0.11 is released to prevent trying to refetch authentication.
super(_UserAuthPlugin, self).__init__()
self._user_token = user_token
self._stored_auth_ref = auth_ref
def get_token(self, session, **kwargs):
# NOTE(jamielennox): This is needed partially because the AccessInfo
# factory is so bad that we don't always get the correct token data.
# Override and always return the token that was provided in the req.
return self._user_token
def get_auth_ref(self, session, **kwargs):
# NOTE(jamielennox): We can't go out and fetch this auth_ref, we've
# got it already so always return it. In the event it tries to
# re-authenticate it will get the same old auth_ref which is not
# perfect, but the best we can do for now.
return self._stored_auth_ref
class AuthProtocol(object):
"""Auth Middleware that handles authenticating client calls."""
@ -600,8 +638,10 @@ class AuthProtocol(object):
self._remove_auth_headers(env)
user_token = self._get_user_token_from_header(env)
token_info = self._validate_user_token(user_token, env)
auth_ref = access.AccessInfo.factory(body=token_info)
env['keystone.token_info'] = token_info
user_headers = self._build_user_headers(token_info)
env['keystone.token_auth'] = _UserAuthPlugin(user_token, auth_ref)
user_headers = self._build_user_headers(auth_ref, token_info)
self._add_headers(env, user_headers)
return self._call_app(env, start_response)
@ -755,7 +795,7 @@ class AuthProtocol(object):
self._LOG.warn('Authorization failed for token')
raise InvalidUserToken('Token authorization failed')
def _build_user_headers(self, token_info):
def _build_user_headers(self, auth_ref, token_info):
"""Convert token object into headers.
Build headers that represent authenticated user - see main
@ -765,7 +805,6 @@ class AuthProtocol(object):
:raise InvalidUserToken when unable to parse token object
"""
auth_ref = access.AccessInfo.factory(body=token_info)
roles = ','.join(auth_ref.role_names)
if _token_is_v2(token_info) and not auth_ref.project_id:

View File

@ -30,6 +30,7 @@ from keystoneclient import access
from keystoneclient.common import cms
from keystoneclient import exceptions
from keystoneclient import fixture
from keystoneclient import session
import mock
import testresources
import testtools
@ -1296,6 +1297,25 @@ class CommonAuthTokenMiddlewareTest(object):
# Assert that the token wasn't cached again.
self.assertThat(1, matchers.Equals(cache.set.call_count))
def test_auth_plugin(self):
httpretty.register_uri(httpretty.GET,
self.examples.SERVICE_URL,
body=VERSION_LIST_v3,
status_code=300)
req = webob.Request.blank('/')
req.headers['X-Auth-Token'] = self.token_dict['uuid_token_default']
body = self.middleware(req.environ, self.start_fake_response)
self.assertEqual(200, self.response_status)
self.assertEqual([FakeApp.SUCCESS], body)
token_auth = req.environ['keystone.token_auth']
endpoint_filter = {'service_type': self.examples.SERVICE_TYPE,
'version': 3}
url = token_auth.get_endpoint(session.Session(), **endpoint_filter)
self.assertEqual('%s/v3' % BASE_URI, url)
class V2CertDownloadMiddlewareTest(BaseAuthTokenMiddlewareTest,
testresources.ResourcedTestCase):