Limit token revocation to tenant (bug 1050025)
Change-Id: I7ebe0192b4900ad9475119a6d582233b37b31fb4
This commit is contained in:
parent
461fd623f6
commit
4e1a0867f9
@ -592,7 +592,7 @@ class RoleController(wsgi.Application):
|
||||
self.identity_api.add_user_to_tenant(context, tenant_id, user_id)
|
||||
self.identity_api.add_role_to_user_and_tenant(
|
||||
context, user_id, tenant_id, role_id)
|
||||
self.token_api.revoke_tokens(context, user_id)
|
||||
self.token_api.revoke_tokens(context, user_id, tenant_id)
|
||||
|
||||
role_ref = self.identity_api.get_role(context, role_id)
|
||||
return {'role': role_ref}
|
||||
@ -618,7 +618,7 @@ class RoleController(wsgi.Application):
|
||||
if not roles:
|
||||
self.identity_api.remove_user_from_tenant(
|
||||
context, tenant_id, user_id)
|
||||
self.token_api.revoke_tokens(context, user_id)
|
||||
self.token_api.revoke_tokens(context, user_id, tenant_id)
|
||||
|
||||
# COMPAT(diablo): CRUD extension
|
||||
def get_role_refs(self, context, user_id):
|
||||
@ -661,7 +661,7 @@ class RoleController(wsgi.Application):
|
||||
self.identity_api.add_user_to_tenant(context, tenant_id, user_id)
|
||||
self.identity_api.add_role_to_user_and_tenant(
|
||||
context, user_id, tenant_id, role_id)
|
||||
self.token_api.revoke_tokens(context, user_id)
|
||||
self.token_api.revoke_tokens(context, user_id, tenant_id)
|
||||
|
||||
role_ref = self.identity_api.get_role(context, role_id)
|
||||
return {'role': role_ref}
|
||||
@ -690,4 +690,4 @@ class RoleController(wsgi.Application):
|
||||
if not roles:
|
||||
self.identity_api.remove_user_from_tenant(
|
||||
context, tenant_id, user_id)
|
||||
self.token_api.revoke_tokens(context, user_id)
|
||||
self.token_api.revoke_tokens(context, user_id, tenant_id)
|
||||
|
@ -50,18 +50,23 @@ class Token(kvs.Base, token.Driver):
|
||||
except exception.NotFound:
|
||||
raise exception.TokenNotFound(token_id=token_id)
|
||||
|
||||
def list_tokens(self, user_id):
|
||||
def list_tokens(self, user_id, tenant_id=None):
|
||||
tokens = []
|
||||
now = timeutils.utcnow()
|
||||
for token, user_ref in self.db.items():
|
||||
for token, ref in self.db.items():
|
||||
if not token.startswith('token-'):
|
||||
continue
|
||||
if 'user' not in user_ref:
|
||||
if 'user' not in ref:
|
||||
continue
|
||||
if user_ref['user'].get('id') != user_id:
|
||||
if ref['user'].get('id') != user_id:
|
||||
continue
|
||||
if user_ref.get('expires') and user_ref.get('expires') < now:
|
||||
if ref.get('expires') and ref.get('expires') < now:
|
||||
continue
|
||||
if tenant_id is not None:
|
||||
if 'tenant' not in ref:
|
||||
continue
|
||||
if ref['tenant'].get('id') != tenant_id:
|
||||
continue
|
||||
tokens.append(token.split('-', 1)[1])
|
||||
return tokens
|
||||
|
||||
|
@ -31,7 +31,6 @@ config.register_str('servers', group='memcache', default='localhost:11211')
|
||||
|
||||
|
||||
class Token(token.Driver):
|
||||
|
||||
revocation_key = 'revocation-list'
|
||||
|
||||
def __init__(self, client=None):
|
||||
@ -95,14 +94,19 @@ class Token(token.Driver):
|
||||
self._add_to_revocation_list(data)
|
||||
return result
|
||||
|
||||
def list_tokens(self, user_id):
|
||||
def list_tokens(self, user_id, tenant_id=None):
|
||||
tokens = []
|
||||
user_record = self.client.get('usertokens-%s' % user_id) or ""
|
||||
token_list = jsonutils.loads('[%s]' % user_record)
|
||||
for token_id in token_list:
|
||||
ptk = self._prefix_token_id(token_id)
|
||||
token = self.client.get(ptk)
|
||||
if token:
|
||||
token_ref = self.client.get(ptk)
|
||||
if token_ref:
|
||||
if tenant_id is not None:
|
||||
if 'tenant' not in token_ref:
|
||||
continue
|
||||
if token_ref['tenant'].get('id') != tenant_id:
|
||||
continue
|
||||
tokens.append(token_id)
|
||||
return tokens
|
||||
|
||||
|
@ -95,7 +95,7 @@ class Token(sql.Base, token.Driver):
|
||||
token_ref.valid = False
|
||||
session.flush()
|
||||
|
||||
def list_tokens(self, user_id):
|
||||
def list_tokens(self, user_id, tenant_id=None):
|
||||
session = self.get_session()
|
||||
tokens = []
|
||||
now = timeutils.utcnow()
|
||||
@ -107,6 +107,11 @@ class Token(sql.Base, token.Driver):
|
||||
continue
|
||||
if token_ref_dict['user'].get('id') != user_id:
|
||||
continue
|
||||
if tenant_id is not None:
|
||||
if 'tenant' not in token_ref_dict:
|
||||
continue
|
||||
if token_ref_dict['tenant'].get('id') != tenant_id:
|
||||
continue
|
||||
tokens.append(token_ref['id'])
|
||||
return tokens
|
||||
|
||||
@ -117,7 +122,6 @@ class Token(sql.Base, token.Driver):
|
||||
for token_ref in session.query(TokenModel)\
|
||||
.filter(TokenModel.expires > now)\
|
||||
.filter_by(valid=False):
|
||||
token_ref_dict = token_ref.to_dict()
|
||||
record = {
|
||||
'id': token_ref['id'],
|
||||
'expires': token_ref['expires'],
|
||||
|
@ -39,8 +39,13 @@ class Manager(manager.Manager):
|
||||
def __init__(self):
|
||||
super(Manager, self).__init__(CONF.token.driver)
|
||||
|
||||
def revoke_tokens(self, context, user_id):
|
||||
for token_id in self.list_tokens(context, user_id):
|
||||
def revoke_tokens(self, context, user_id, tenant_id=None):
|
||||
"""Invalidates all tokens held by a user (optionally for a tenant).
|
||||
|
||||
If a specific tenant ID is not provided, *all* tokens held by user will
|
||||
be revoked.
|
||||
"""
|
||||
for token_id in self.list_tokens(context, user_id, tenant_id):
|
||||
self.delete_token(context, token_id)
|
||||
|
||||
|
||||
@ -110,10 +115,11 @@ class Driver(object):
|
||||
"""
|
||||
raise exception.NotImplemented()
|
||||
|
||||
def revoke_tokens(self, user_id):
|
||||
"""Invalidates all tokens held by a user.
|
||||
def revoke_tokens(self, user_id, tenant_id=None):
|
||||
"""Invalidates all tokens held by a user (optionally for a tenant).
|
||||
|
||||
:raises: keystone.exception.UserNotFound
|
||||
:raises: keystone.exception.UserNotFound,
|
||||
keystone.exception.TenantNotFound
|
||||
"""
|
||||
raise exception.NotImplemented()
|
||||
|
||||
|
@ -661,10 +661,12 @@ class TokenTests(object):
|
||||
self.assertRaises(exception.TokenNotFound,
|
||||
self.token_api.delete_token, token_id)
|
||||
|
||||
def create_token_sample_data(self):
|
||||
def create_token_sample_data(self, tenant_id=None):
|
||||
token_id = uuid.uuid4().hex
|
||||
data = {'id': token_id, 'a': 'b',
|
||||
'user': {'id': 'testuserid'}}
|
||||
if tenant_id is not None:
|
||||
data['tenant'] = {'id': tenant_id, 'name': tenant_id}
|
||||
self.token_api.create_token(token_id, data)
|
||||
return token_id
|
||||
|
||||
@ -689,6 +691,24 @@ class TokenTests(object):
|
||||
self.assertNotIn(token_id2, tokens)
|
||||
self.assertNotIn(token_id1, tokens)
|
||||
|
||||
# tenant-specific tokens
|
||||
tenant1 = uuid.uuid4().hex
|
||||
tenant2 = uuid.uuid4().hex
|
||||
token_id3 = self.create_token_sample_data(tenant_id=tenant1)
|
||||
token_id4 = self.create_token_sample_data(tenant_id=tenant2)
|
||||
tokens = self.token_api.list_tokens('testuserid')
|
||||
self.assertEquals(len(tokens), 2)
|
||||
self.assertNotIn(token_id1, tokens)
|
||||
self.assertNotIn(token_id2, tokens)
|
||||
self.assertIn(token_id3, tokens)
|
||||
self.assertIn(token_id4, tokens)
|
||||
tokens = self.token_api.list_tokens('testuserid', tenant2)
|
||||
self.assertEquals(len(tokens), 1)
|
||||
self.assertNotIn(token_id1, tokens)
|
||||
self.assertNotIn(token_id2, tokens)
|
||||
self.assertNotIn(token_id3, tokens)
|
||||
self.assertIn(token_id4, tokens)
|
||||
|
||||
def test_get_token_404(self):
|
||||
self.assertRaises(exception.TokenNotFound,
|
||||
self.token_api.get_token,
|
||||
|
Loading…
x
Reference in New Issue
Block a user