From ea7a0b2f587de39fafdd60f9aa896ba2505dd822 Mon Sep 17 00:00:00 2001 From: Wayne Witzel III Date: Mon, 2 Apr 2018 14:10:14 -0400 Subject: [PATCH 1/2] Fixes RBAC issue, ensures can admin of sub_obj when needed --- awx/main/access.py | 4 ++++ awx/main/tests/functional/test_rbac_role.py | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/awx/main/access.py b/awx/main/access.py index 6f621cab46..1af54ff1d6 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -2523,6 +2523,10 @@ class RoleAccess(BaseAccess): if not check_user_access(self.user, sub_obj_resource.__class__, 'read', sub_obj_resource): return False + if isinstance(obj.content_object, Organization) and obj.role_field == 'member_role': + if not UserAccess(self.user).can_admin(sub_obj, data): + return False + if isinstance(obj.content_object, ResourceMixin) and \ self.user in obj.content_object.admin_role: return True diff --git a/awx/main/tests/functional/test_rbac_role.py b/awx/main/tests/functional/test_rbac_role.py index 96484f9fee..6a94511f4c 100644 --- a/awx/main/tests/functional/test_rbac_role.py +++ b/awx/main/tests/functional/test_rbac_role.py @@ -50,3 +50,14 @@ def test_visible_roles(admin_user, system_auditor, rando, organization, project) assert rando not in project.admin_role assert access.can_read(project.admin_role) assert project.admin_role in Role.visible_roles(rando) + + +@pytest.mark.django_db +def test_org_user_role_attach(user, organization): + admin = user('admin') + nonmember = user('nonmember') + + organization.admin_role.members.add(admin) + + access = RoleAccess(admin) + assert not access.can_attach(organization.member_role, nonmember, 'members', None) From 067ead35aca0d42f0da127710782365cfe8e5022 Mon Sep 17 00:00:00 2001 From: Wayne Witzel III Date: Mon, 2 Apr 2018 15:37:47 -0400 Subject: [PATCH 2/2] Extend test and fix to include the admin_role --- awx/main/access.py | 8 ++++++-- awx/main/tests/functional/test_rbac_role.py | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/awx/main/access.py b/awx/main/access.py index 1af54ff1d6..bf74f2a491 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -2523,8 +2523,12 @@ class RoleAccess(BaseAccess): if not check_user_access(self.user, sub_obj_resource.__class__, 'read', sub_obj_resource): return False - if isinstance(obj.content_object, Organization) and obj.role_field == 'member_role': - if not UserAccess(self.user).can_admin(sub_obj, data): + # Being a user in the member_role or admin_role of an organization grants + # administrators of that Organization the ability to edit that user. To prevent + # unwanted escalations lets ensure that the Organization administartor has the abilty + # to admin the user being added to the role. + if isinstance(obj.content_object, Organization) and obj.role_field in ['member_role', 'admin_role']: + if not UserAccess(self.user).can_admin(sub_obj, None): return False if isinstance(obj.content_object, ResourceMixin) and \ diff --git a/awx/main/tests/functional/test_rbac_role.py b/awx/main/tests/functional/test_rbac_role.py index 6a94511f4c..438a72182b 100644 --- a/awx/main/tests/functional/test_rbac_role.py +++ b/awx/main/tests/functional/test_rbac_role.py @@ -61,3 +61,4 @@ def test_org_user_role_attach(user, organization): access = RoleAccess(admin) assert not access.can_attach(organization.member_role, nonmember, 'members', None) + assert not access.can_attach(organization.admin_role, nonmember, 'members', None)