Expose bind data via AccessInfo

The bind information is a standard part of the token data and can be
access from auth_token middleware so it should be exposed as part of the
AccessInfo object.

Change-Id: I45fc6eeed43f335aa1d771bdf1a11257432cb85c
This commit is contained in:
Jamie Lennox 2015-10-15 17:03:23 +11:00
parent b2484fdbf6
commit 4fd8531fd5
6 changed files with 79 additions and 1 deletions

View File

@ -369,6 +369,22 @@ class AccessInfo(object):
"""
raise NotImplementedError()
@property
def bind(self):
"""Information about external mechanisms the token is bound to.
If a token is bound to an external authentication mechanism it can only
be used in conjunction with that mechanism. For example if bound to a
kerberos principal it may only be accepted if there is also kerberos
authentication performed on the request.
:returns: A dictionary or None. The key will be the bind type the value
is a dictionary that is specific to the format of the bind
type. Returns None if there is no bind information in the
token.
"""
raise NotImplementedError()
class AccessInfoV2(AccessInfo):
"""An object for encapsulating a raw v2 auth token from identity
@ -386,7 +402,7 @@ class AccessInfoV2(AccessInfo):
set_token = super(AccessInfoV2, self).auth_token
return set_token or self._data['access']['token']['id']
@_missingproperty
@property
def _token(self):
return self._data['access']['token']
@ -544,6 +560,10 @@ class AccessInfoV2(AccessInfo):
def service_providers(self):
return None
@_missingproperty
def bind(self):
return self._token['bind']
class AccessInfoV3(AccessInfo):
"""An object for encapsulating a raw v3 auth token from identity
@ -708,3 +728,7 @@ class AccessInfoV3(AccessInfo):
service_providers.ServiceProviders.from_token(self._data))
return self._service_providers
@_missingproperty
def bind(self):
return self._data['token']['bind']

View File

@ -242,3 +242,6 @@ class Token(dict):
def set_trust(self, id=None, trustee_user_id=None):
self.trust_id = id or uuid.uuid4().hex
self.trustee_user_id = trustee_user_id or uuid.uuid4().hex
def set_bind(self, name, data):
self._token.setdefault('bind', {})[name] = data

View File

@ -405,6 +405,9 @@ class Token(dict):
_service_providers.append(sp)
return sp
def set_bind(self, name, data):
self.root.setdefault('bind', {})[name] = data
class V3FederationToken(Token):
"""A V3 Keystone Federation token that can be used for testing.

View File

@ -55,6 +55,7 @@ class AccessV2Test(utils.TestCase):
self.assertEqual(token.audit_id, auth_ref.audit_id)
self.assertIsNone(auth_ref.audit_chain_id)
self.assertIsNone(token.audit_chain_id)
self.assertIsNone(auth_ref.bind)
def test_will_expire_soon(self):
token = fixture.V2Token()
@ -199,3 +200,13 @@ class AccessV2Test(utils.TestCase):
self.assertEqual(user_id, auth_ref.trustee_user_id)
self.assertEqual(trust_id, token['access']['trust']['id'])
def test_binding(self):
token = fixture.V2Token()
principal = uuid.uuid4().hex
token.set_bind('kerberos', principal)
auth_ref = access.create(body=token)
self.assertIsInstance(auth_ref, access.AccessInfoV2)
self.assertEqual({'kerberos': principal}, auth_ref.bind)

View File

@ -62,6 +62,7 @@ class AccessV3Test(utils.TestCase):
self.assertEqual(auth_ref.audit_id, token.audit_id)
self.assertIsNone(auth_ref.audit_chain_id)
self.assertIsNone(token.audit_chain_id)
self.assertIsNone(auth_ref.bind)
def test_will_expire_soon(self):
expires = timeutils.utcnow() + datetime.timedelta(minutes=5)
@ -184,3 +185,13 @@ class AccessV3Test(utils.TestCase):
token.set_project_scope()
auth_ref = access.create(body=token)
self.assertFalse(auth_ref.is_federated)
def test_binding(self):
token = fixture.V3Token()
principal = uuid.uuid4().hex
token.set_bind('kerberos', principal)
auth_ref = access.create(body=token)
self.assertIsInstance(auth_ref, access.AccessInfoV3)
self.assertEqual({'kerberos': principal}, auth_ref.bind)

View File

@ -109,6 +109,19 @@ class V2TokenTests(utils.TestCase):
self.assertEqual(region, service['region'])
self.assertEqual(endpoint_id, service['id'])
def test_token_bind(self):
name1 = uuid.uuid4().hex
data1 = uuid.uuid4().hex
name2 = uuid.uuid4().hex
data2 = {uuid.uuid4().hex: uuid.uuid4().hex}
token = fixture.V2Token()
token.set_bind(name1, data1)
token.set_bind(name2, data2)
self.assertEqual({name1: data1, name2: data2},
token['access']['token']['bind'])
class V3TokenTests(utils.TestCase):
@ -271,3 +284,16 @@ class V3TokenTests(utils.TestCase):
self.assertEqual(ref_service_providers, token.service_providers)
self.assertEqual(ref_service_providers,
token['token']['service_providers'])
def test_token_bind(self):
name1 = uuid.uuid4().hex
data1 = uuid.uuid4().hex
name2 = uuid.uuid4().hex
data2 = {uuid.uuid4().hex: uuid.uuid4().hex}
token = fixture.V3Token()
token.set_bind(name1, data1)
token.set_bind(name2, data2)
self.assertEqual({name1: data1, name2: data2},
token['token']['bind'])