diff options
author | Jenkins <jenkins@review.openstack.org> | 2012-09-13 21:20:06 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2012-09-13 21:20:06 +0000 |
commit | 84f41c2e43f366f8aa9a4d2201604535966d74d7 (patch) | |
tree | d275abc42752b3ce8aac58ef804f766816b7988f | |
parent | af8b031e7ae5c0d1cf498cd86e691dd3e9a71de1 (diff) | |
parent | 4e1a0867f9e9f42dd7c2abe3a10ca8a8f7dddce3 (diff) | |
download | keystone-84f41c2e43f366f8aa9a4d2201604535966d74d7.tar.gz |
Merge "Limit token revocation to tenant (bug 1050025)"folsom-rc1
-rw-r--r-- | keystone/identity/core.py | 8 | ||||
-rw-r--r-- | keystone/token/backends/kvs.py | 15 | ||||
-rw-r--r-- | keystone/token/backends/memcache.py | 12 | ||||
-rw-r--r-- | keystone/token/backends/sql.py | 8 | ||||
-rw-r--r-- | keystone/token/core.py | 16 | ||||
-rw-r--r-- | tests/test_backend.py | 22 |
6 files changed, 60 insertions, 21 deletions
diff --git a/keystone/identity/core.py b/keystone/identity/core.py index 012843ba4..e0297432f 100644 --- a/keystone/identity/core.py +++ b/keystone/identity/core.py @@ -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) diff --git a/keystone/token/backends/kvs.py b/keystone/token/backends/kvs.py index 98d7936ec..392e48524 100644 --- a/keystone/token/backends/kvs.py +++ b/keystone/token/backends/kvs.py @@ -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 diff --git a/keystone/token/backends/memcache.py b/keystone/token/backends/memcache.py index 437431bcf..fc57cf4d2 100644 --- a/keystone/token/backends/memcache.py +++ b/keystone/token/backends/memcache.py @@ -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 diff --git a/keystone/token/backends/sql.py b/keystone/token/backends/sql.py index 15a0060cd..02e894766 100644 --- a/keystone/token/backends/sql.py +++ b/keystone/token/backends/sql.py @@ -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'], diff --git a/keystone/token/core.py b/keystone/token/core.py index d3c1b67a0..e10a4ddfd 100644 --- a/keystone/token/core.py +++ b/keystone/token/core.py @@ -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() diff --git a/tests/test_backend.py b/tests/test_backend.py index 696da451f..f4ac2156c 100644 --- a/tests/test_backend.py +++ b/tests/test_backend.py @@ -646,10 +646,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 @@ -674,6 +676,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, |