From 63556be0e3b995a2a232a0b180c932a97736350e Mon Sep 17 00:00:00 2001 From: Boris Bobrov Date: Wed, 14 Feb 2024 16:11:41 +0100 Subject: [PATCH] Fix operation order in role deletion Deletion of a role leads to deletion of role assignments and entries in the application credentials. However, deletion of the entries in application credentials depends on the existence of the assignment, so the order of deletion is important. Delete the entries from application credentials first and then clean up role assignment. Closes-Bug: 2053137 Change-Id: Ibba9063c729961cd4155f8b55dbabd4789d7a438 --- keystone/assignment/core.py | 2 +- .../unit/test_v3_application_credential.py | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/keystone/assignment/core.py b/keystone/assignment/core.py index b8039b3c79..f986b20cd2 100644 --- a/keystone/assignment/core.py +++ b/keystone/assignment/core.py @@ -1339,10 +1339,10 @@ class RoleManager(manager.Manager): ro_opt.check_immutable_delete(resource_ref=role, resource_type='role', resource_id=role_id) - PROVIDERS.assignment_api.delete_role_assignments(role_id) PROVIDERS.assignment_api._send_app_cred_notification_for_role_removal( role_id ) + PROVIDERS.assignment_api.delete_role_assignments(role_id) self.driver.delete_role(role_id) notifications.Audit.deleted(self._ROLE, role_id, initiator) self.get_role.invalidate(self, role_id) diff --git a/keystone/tests/unit/test_v3_application_credential.py b/keystone/tests/unit/test_v3_application_credential.py index b60307c05a..2a51ce5da6 100644 --- a/keystone/tests/unit/test_v3_application_credential.py +++ b/keystone/tests/unit/test_v3_application_credential.py @@ -380,6 +380,31 @@ class ApplicationCredentialTestCase(test_v3.RestfulTestCase): self.assertNotIn('secret', ac) self.assertNotIn('secret_hash', ac) + def test_list_application_credentials_with_deleted_role(self): + second_role = unit.new_role_ref(name='test_new_role') + PROVIDERS.role_api.create_role(second_role['id'], second_role) + PROVIDERS.assignment_api.add_role_to_user_and_project( + self.user_id, self.project_id, second_role['id']) + with self.test_client() as c: + token = self.get_scoped_token() + resp = c.get('/v3/users/%s/application_credentials' % self.user_id, + expected_status_code=http.client.OK, + headers={'X-Auth-Token': token}) + self.assertEqual([], resp.json['application_credentials']) + roles = [{'id': second_role['id']}] + app_cred_body = self._app_cred_body(roles=roles) + c.post('/v3/users/%s/application_credentials' % self.user_id, + json=app_cred_body, + expected_status_code=http.client.CREATED, + headers={'X-Auth-Token': token}) + resp = c.get('/v3/users/%s/application_credentials' % self.user_id, + expected_status_code=http.client.OK, + headers={'X-Auth-Token': token}) + PROVIDERS.role_api.delete_role(second_role['id']) + resp = c.get('/v3/users/%s/application_credentials' % self.user_id, + expected_status_code=http.client.OK, + headers={'X-Auth-Token': token}) + def test_list_application_credentials_by_name(self): with self.test_client() as c: roles = [{'id': self.role_id}]