diff --git a/awx/main/access.py b/awx/main/access.py index 421e0e73ab..c70e6331c9 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -871,6 +871,11 @@ class ProjectAccess(BaseAccess): @check_superuser def can_change(self, obj, data): + org_pk = get_pk_from_dict(data, 'organization') + if obj and org_pk and obj.organization and obj.organization.pk != org_pk: + org = get_object_or_400(Organization, pk=org_pk) + if self.user not in org.admin_role: + return False return self.user in obj.admin_role def can_delete(self, obj): @@ -2045,11 +2050,16 @@ class CustomInventoryScriptAccess(BaseAccess): @check_superuser def can_admin(self, obj, data=None): + org_pk = get_pk_from_dict(data, 'organization') + if obj and org_pk and obj.organization and obj.organization.pk != org_pk: + org = get_object_or_400(Organization, pk=org_pk) + if self.user not in org.admin_role: + return False return self.user in obj.admin_role @check_superuser def can_change(self, obj, data): - return self.can_admin(obj) + return self.can_admin(obj, data=data) @check_superuser def can_delete(self, obj): diff --git a/awx/main/tests/functional/test_rbac_inventory.py b/awx/main/tests/functional/test_rbac_inventory.py index 287919ad31..68e183c68b 100644 --- a/awx/main/tests/functional/test_rbac_inventory.py +++ b/awx/main/tests/functional/test_rbac_inventory.py @@ -9,7 +9,8 @@ from awx.main.models import ( from awx.main.access import ( InventoryAccess, HostAccess, - InventoryUpdateAccess + InventoryUpdateAccess, + CustomInventoryScriptAccess ) from django.apps import apps @@ -29,6 +30,15 @@ def test_custom_inv_script_access(organization, user): organization.admin_role.members.add(ou) assert ou in custom_inv.admin_role +@pytest.mark.django_db +def test_modify_inv_script_foreign_org_admin(org_admin, organization, organization_factory, project): + custom_inv = CustomInventoryScript.objects.create(name='test', script='test', description='test', + organization=organization) + + other_org = organization_factory('not-my-org').organization + access = CustomInventoryScriptAccess(org_admin) + assert not access.can_change(custom_inv, {'organization': other_org.pk, 'name': 'new-project'}) + @pytest.mark.django_db def test_inventory_admin_user(inventory, permissions, user): u = user('admin', False) diff --git a/awx/main/tests/functional/test_rbac_project.py b/awx/main/tests/functional/test_rbac_project.py index ba88226b2e..2b342df198 100644 --- a/awx/main/tests/functional/test_rbac_project.py +++ b/awx/main/tests/functional/test_rbac_project.py @@ -217,3 +217,10 @@ def test_create_project_foreign_org_admin(org_admin, organization, organization_ other_org = organization_factory('not-my-org').organization access = ProjectAccess(org_admin) assert not access.can_add({'organization': other_org.pk, 'name': 'new-project'}) + +@pytest.mark.django_db +def test_modify_project_foreign_org_admin(org_admin, organization, organization_factory, project): + """Org admins can only modify projects in their own org.""" + other_org = organization_factory('not-my-org').organization + access = ProjectAccess(org_admin) + assert not access.can_change(project, {'organization': other_org.pk, 'name': 'new-project'})