From 12bda9fc3ac975c251232d41e92dd70c7a4e6e7c Mon Sep 17 00:00:00 2001 From: Colleen Murphy Date: Tue, 17 Sep 2019 14:19:56 -0700 Subject: [PATCH] Fix validation of role assignment subtree list Without this patch, if a project ID is not passed as query argument, a target of {} is passed to the enforcer and causes a type error to be raised ("'NoneType' object is not callable") which then is emitted as a validation error to the user rather than as a server error. This patch fixes the issue by correctly passing in None as the default target, which is what the enforcer expects, which then allows the validation to continue and return a more helpful error message about the required query parameter. Change-Id: If7f0fa4dd072b0f00172161da4f7b91f8c1e1f10 --- keystone/api/role_assignments.py | 6 +++--- keystone/tests/unit/test_v3_assignment.py | 14 +++++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/keystone/api/role_assignments.py b/keystone/api/role_assignments.py index d1cfd90c48..fe81cca0fd 100644 --- a/keystone/api/role_assignments.py +++ b/keystone/api/role_assignments.py @@ -80,12 +80,12 @@ class RoleAssignmentsResource(ks_flask.ResourceBase): 'group.id', 'role.id', 'scope.domain.id', 'scope.project.id', 'scope.OS-INHERIT:inherited_to', 'user.id' ] - target = {} + target = None if 'scope.project.id' in flask.request.args: project_id = flask.request.args['scope.project.id'] if project_id: - target['project'] = PROVIDERS.resource_api.get_project( - project_id) + target = {'project': PROVIDERS.resource_api.get_project( + project_id)} ENFORCER.enforce_call(action='identity:list_role_assignments_for_tree', filters=filters, target_attr=target) if not flask.request.args.get('scope.project.id'): diff --git a/keystone/tests/unit/test_v3_assignment.py b/keystone/tests/unit/test_v3_assignment.py index 3bc15af6ed..a81d855ceb 100644 --- a/keystone/tests/unit/test_v3_assignment.py +++ b/keystone/tests/unit/test_v3_assignment.py @@ -2596,11 +2596,15 @@ class AssignmentInheritanceTestCase(test_v3.RestfulTestCase, def test_project_id_specified_if_include_subtree_specified(self): """When using include_subtree, you must specify a project ID.""" - self.get('/role_assignments?include_subtree=True', - expected_status=http_client.BAD_REQUEST) - self.get('/role_assignments?scope.project.id&' - 'include_subtree=True', - expected_status=http_client.BAD_REQUEST) + r = self.get('/role_assignments?include_subtree=True', + expected_status=http_client.BAD_REQUEST) + error_msg = ("scope.project.id must be specified if include_subtree " + "is also specified") + self.assertEqual(error_msg, r.result['error']['message']) + r = self.get('/role_assignments?scope.project.id&' + 'include_subtree=True', + expected_status=http_client.BAD_REQUEST) + self.assertEqual(error_msg, r.result['error']['message']) def test_get_role_assignments_for_project_tree(self): """Get role_assignment?scope.project.id=X&include_subtree``.