Create an Auth Plugin to pass to users
We pass the service catalog and token data through to consumers via headers, with the auth plugin work we can create clients that are authenticated with the incoming token and service catalog. DocImpact: A new environment option is passed out of auth_token middleware called `token_auth` which is an authentication plugin that can be used with a session in a service. Implements: blueprint create-auth-plugin Change-Id: I549a421fc73f00126f6ac5f4b5911de2e32de825
This commit is contained in:
parent
e3a3dff00f
commit
d26c81df44
@ -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),
|
||||
}
|
||||
|
@ -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
|
||||
@ -453,6 +459,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."""
|
||||
|
||||
@ -559,8 +597,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._app(env, start_response)
|
||||
|
||||
@ -696,7 +736,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
|
||||
@ -706,7 +746,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:
|
||||
|
@ -29,6 +29,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
|
||||
@ -1256,6 +1257,25 @@ class CommonAuthTokenMiddlewareTest(object):
|
||||
# again.
|
||||
self.assertThat(2, 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):
|
||||
|
Loading…
Reference in New Issue
Block a user