summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--keystone/common/controller.py4
-rw-r--r--keystone/identity/controllers.py16
-rw-r--r--keystone/tests/_ldap_livetest.py11
-rw-r--r--keystone/tests/test_backend_ldap.py4
-rw-r--r--keystone/tests/test_keystoneclient.py46
-rw-r--r--keystone/tests/test_v3_auth.py61
6 files changed, 138 insertions, 4 deletions
diff --git a/keystone/common/controller.py b/keystone/common/controller.py
index 15857c45..1bf65cda 100644
--- a/keystone/common/controller.py
+++ b/keystone/common/controller.py
@@ -168,6 +168,10 @@ class V2Controller(wsgi.Application):
self._delete_tokens_for_trust(trust['trustee_user_id'],
trust['id'])
+ def _delete_tokens_for_project(self, project_id):
+ for user_ref in self.identity_api.get_project_users(project_id):
+ self._delete_tokens_for_user(user_ref['id'], project_id=project_id)
+
def _require_attribute(self, ref, attr):
"""Ensures the reference contains the specified attribute."""
if ref.get(attr) is None or ref.get(attr) == '':
diff --git a/keystone/identity/controllers.py b/keystone/identity/controllers.py
index cf8c83c7..67f3beac 100644
--- a/keystone/identity/controllers.py
+++ b/keystone/identity/controllers.py
@@ -108,12 +108,20 @@ class Tenant(controller.V2Controller):
# be specifying that
clean_tenant = tenant.copy()
clean_tenant.pop('domain_id', None)
+
+ # If the project has been disabled (or enabled=False) we are
+ # deleting the tokens for that project.
+ if not tenant.get('enabled', True):
+ self._delete_tokens_for_project(tenant_id)
+
tenant_ref = self.identity_api.update_project(
tenant_id, clean_tenant)
return {'tenant': tenant_ref}
def delete_project(self, context, tenant_id):
self.assert_admin(context)
+ # Delete all tokens belonging to the users for that project
+ self._delete_tokens_for_project(tenant_id)
self.identity_api.delete_project(tenant_id)
def get_project_users(self, context, tenant_id, **kw):
@@ -571,6 +579,10 @@ class ProjectV3(controller.V3Controller):
def update_project(self, context, project_id, project):
self._require_matching_id(project_id, project)
+ # The project was disabled so we delete the tokens
+ if not project.get('enabled', True):
+ self._delete_tokens_for_project(project_id)
+
ref = self.identity_api.update_project(project_id, project)
return ProjectV3.wrap_member(context, ref)
@@ -579,6 +591,10 @@ class ProjectV3(controller.V3Controller):
for cred in self.credential_api.list_credentials():
if cred['project_id'] == project_id:
self.credential_api.delete_credential(cred['id'])
+
+ # Delete all tokens belonging to the users for that project
+ self._delete_tokens_for_project(project_id)
+
# Finally delete the project itself - the backend is
# responsible for deleting any role assignments related
# to this project
diff --git a/keystone/tests/_ldap_livetest.py b/keystone/tests/_ldap_livetest.py
index 59da4e66..4562ccb6 100644
--- a/keystone/tests/_ldap_livetest.py
+++ b/keystone/tests/_ldap_livetest.py
@@ -87,9 +87,6 @@ class LiveLDAPIdentity(test_backend_ldap.LDAPIdentity):
def tearDown(self):
test.TestCase.tearDown(self)
- def test_user_enable_attribute_mask(self):
- self.skipTest('Test is for Active Directory Only')
-
def test_ldap_dereferencing(self):
alt_users_ldif = {'objectclass': ['top', 'organizationalUnit'],
'ou': 'alt_users'}
@@ -158,3 +155,11 @@ class LiveLDAPIdentity(test_backend_ldap.LDAPIdentity):
alias_dereferencing=deref)
self.assertEqual(ldap.DEREF_SEARCHING,
ldap_wrapper.conn.get_option(ldap.OPT_DEREF))
+
+ def test_user_enable_attribute_mask(self):
+ CONF.ldap.user_enabled_emulation = False
+ CONF.ldap.user_enabled_attribute = 'employeeType'
+ super(LiveLDAPIdentity, self).test_user_enable_attribute_mask()
+
+ def test_create_unicode_user_name(self):
+ self.skipTest('Addressed by bug #1172106')
diff --git a/keystone/tests/test_backend_ldap.py b/keystone/tests/test_backend_ldap.py
index 9c1c98d5..6f9cfef9 100644
--- a/keystone/tests/test_backend_ldap.py
+++ b/keystone/tests/test_backend_ldap.py
@@ -454,10 +454,12 @@ class LDAPIdentity(test.TestCase, BaseLDAPIdentity):
self.assertNotIn('name', role_ref)
def test_user_enable_attribute_mask(self):
- CONF.ldap.user_enabled_attribute = 'enabled'
CONF.ldap.user_enabled_mask = 2
CONF.ldap.user_enabled_default = 512
self.clear_database()
+ self.load_backends()
+ self.load_fixtures(default_fixtures)
+
user = {'id': 'fake1', 'name': 'fake1', 'enabled': True}
self.identity_api.create_user('fake1', user)
user_ref = self.identity_api.get_user('fake1')
diff --git a/keystone/tests/test_keystoneclient.py b/keystone/tests/test_keystoneclient.py
index 7e59885d..0c323ddd 100644
--- a/keystone/tests/test_keystoneclient.py
+++ b/keystone/tests/test_keystoneclient.py
@@ -378,6 +378,46 @@ class KeystoneClientTests(object):
client.tokens.authenticate,
token=token_id)
+ def test_disable_tenant_invalidates_token(self):
+ from keystoneclient import exceptions as client_exceptions
+
+ admin_client = self.get_client(admin=True)
+ foo_client = self.get_client(self.user_foo)
+ tenant_bar = admin_client.tenants.get(self.tenant_bar['id'])
+
+ # Disable the tenant.
+ tenant_bar.update(enabled=False)
+
+ # Test that the token has been removed.
+ self.assertRaises(client_exceptions.Unauthorized,
+ foo_client.tokens.authenticate,
+ token=foo_client.auth_token)
+
+ # Test that the user access has been disabled.
+ self.assertRaises(client_exceptions.Unauthorized,
+ self.get_client,
+ self.user_foo)
+
+ def test_delete_tenant_invalidates_token(self):
+ from keystoneclient import exceptions as client_exceptions
+
+ admin_client = self.get_client(admin=True)
+ foo_client = self.get_client(self.user_foo)
+ tenant_bar = admin_client.tenants.get(self.tenant_bar['id'])
+
+ # Delete the tenant.
+ tenant_bar.delete()
+
+ # Test that the token has been removed.
+ self.assertRaises(client_exceptions.Unauthorized,
+ foo_client.tokens.authenticate,
+ token=foo_client.auth_token)
+
+ # Test that the user access has been disabled.
+ self.assertRaises(client_exceptions.Unauthorized,
+ self.get_client,
+ self.user_foo)
+
def test_disable_user_invalidates_token(self):
from keystoneclient import exceptions as client_exceptions
@@ -1165,6 +1205,12 @@ class KcEssex3TestCase(CompatTestCase, KeystoneClientTests):
def test_policy_crud(self):
self.skipTest('N/A due to lack of endpoint CRUD')
+ def test_disable_tenant_invalidates_token(self):
+ self.skipTest('N/A')
+
+ def test_delete_tenant_invalidates_token(self):
+ self.skipTest('N/A')
+
class Kc11TestCase(CompatTestCase, KeystoneClientTests):
def get_checkout(self):
diff --git a/keystone/tests/test_v3_auth.py b/keystone/tests/test_v3_auth.py
index 43f87d98..1f4425ce 100644
--- a/keystone/tests/test_v3_auth.py
+++ b/keystone/tests/test_v3_auth.py
@@ -545,6 +545,67 @@ class TestTokenRevoking(test_v3.RestfulTestCase):
headers={'X-Subject-Token': token},
expected_status=204)
+ def test_disabling_project_revokes_token(self):
+ resp = self.post(
+ '/auth/tokens',
+ body=self.build_authentication_request(
+ user_id=self.user3['id'],
+ password=self.user3['password'],
+ project_id=self.projectA['id']))
+ token = resp.headers.get('X-Subject-Token')
+
+ # confirm token is valid
+ self.head('/auth/tokens',
+ headers={'X-Subject-Token': token},
+ expected_status=204)
+
+ # disable the project, which should invalidate the token
+ self.patch(
+ '/projects/%(project_id)s' % {'project_id': self.projectA['id']},
+ body={'project': {'enabled': False}})
+
+ # user should no longer have access to the project
+ self.head('/auth/tokens',
+ headers={'X-Subject-Token': token},
+ expected_status=401)
+ resp = self.post(
+ '/auth/tokens',
+ body=self.build_authentication_request(
+ user_id=self.user3['id'],
+ password=self.user3['password'],
+ project_id=self.projectA['id']),
+ expected_status=401)
+
+ def test_deleting_project_revokes_token(self):
+ resp = self.post(
+ '/auth/tokens',
+ body=self.build_authentication_request(
+ user_id=self.user3['id'],
+ password=self.user3['password'],
+ project_id=self.projectA['id']))
+ token = resp.headers.get('X-Subject-Token')
+
+ # confirm token is valid
+ self.head('/auth/tokens',
+ headers={'X-Subject-Token': token},
+ expected_status=204)
+
+ # delete the project, which should invalidate the token
+ self.delete(
+ '/projects/%(project_id)s' % {'project_id': self.projectA['id']})
+
+ # user should no longer have access to the project
+ self.head('/auth/tokens',
+ headers={'X-Subject-Token': token},
+ expected_status=401)
+ resp = self.post(
+ '/auth/tokens',
+ body=self.build_authentication_request(
+ user_id=self.user3['id'],
+ password=self.user3['password'],
+ project_id=self.projectA['id']),
+ expected_status=401)
+
def test_deleting_group_grant_revokes_tokens(self):
"""Test deleting a group grant revokes tokens.