diff --git a/awx/main/access.py b/awx/main/access.py index b8a80c12d9..cabb7e5592 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -2173,7 +2173,7 @@ class WorkflowJobAccess(BaseAccess): def filtered_queryset(self): return WorkflowJob.objects.filter( Q(unified_job_template__in=UnifiedJobTemplate.accessible_pk_qs(self.user, 'read_role')) - | Q(organization__in=Organization.objects.filter(Q(admin_role__members=self.user)), is_bulk_job=True) + | Q(organization__in=Organization.accessible_pk_qs(self.user, 'auditor_role')) ) def can_read(self, obj): @@ -2571,12 +2571,11 @@ class UnifiedJobAccess(BaseAccess): def filtered_queryset(self): inv_pk_qs = Inventory._accessible_pk_qs(Inventory, self.user, 'read_role') - org_auditor_qs = Organization.objects.filter(Q(admin_role__members=self.user) | Q(auditor_role__members=self.user)) qs = self.model.objects.filter( Q(unified_job_template_id__in=UnifiedJobTemplate.accessible_pk_qs(self.user, 'read_role')) | Q(inventoryupdate__inventory_source__inventory__id__in=inv_pk_qs) | Q(adhoccommand__inventory__id__in=inv_pk_qs) - | Q(organization__in=org_auditor_qs) + | Q(organization__in=Organization.accessible_pk_qs(self.user, 'auditor_role')) ) return qs diff --git a/awx/main/tests/functional/dab_rbac/test_translation_layer.py b/awx/main/tests/functional/dab_rbac/test_translation_layer.py index 22957e1d4c..5d1e519a39 100644 --- a/awx/main/tests/functional/dab_rbac/test_translation_layer.py +++ b/awx/main/tests/functional/dab_rbac/test_translation_layer.py @@ -106,6 +106,17 @@ def test_compat_role_naming(setup_managed_roles, job_template, rando, alice): assert rd.created_by is None +@pytest.mark.django_db +def test_organization_admin_has_audit(setup_managed_roles): + """This formalizes a behavior change from old to new RBAC system + + Previously, the auditor_role did not list admin_role as a parent + this made various queries hard to deal with, requiring adding 2 conditions + The new system should explicitly list the auditor permission in org admin role""" + rd = RoleDefinition.objects.get(name='Organization Admin') + assert 'audit_organization' in rd.permissions.values_list('codename', flat=True) + + @pytest.mark.django_db def test_organization_level_permissions(organization, inventory, setup_managed_roles): u1 = User.objects.create(username='alice') diff --git a/awx/main/tests/functional/test_rbac_workflow.py b/awx/main/tests/functional/test_rbac_workflow.py index 4814e3212c..c94f4f4df8 100644 --- a/awx/main/tests/functional/test_rbac_workflow.py +++ b/awx/main/tests/functional/test_rbac_workflow.py @@ -1,6 +1,7 @@ import pytest from awx.main.access import ( + UnifiedJobAccess, WorkflowJobTemplateAccess, WorkflowJobTemplateNodeAccess, WorkflowJobAccess, @@ -245,6 +246,30 @@ class TestWorkflowJobAccess: inventory.use_role.members.add(rando) assert WorkflowJobAccess(rando).can_start(workflow_job) + @pytest.mark.parametrize('org_role', ['admin_role', 'auditor_role']) + def test_workflow_job_org_audit_access(self, workflow_job_template, rando, org_role): + assert workflow_job_template.organization # sanity + workflow_job = workflow_job_template.create_unified_job() + assert workflow_job.organization # sanity + + assert not UnifiedJobAccess(rando).can_read(workflow_job) + assert not WorkflowJobAccess(rando).can_read(workflow_job) + assert workflow_job not in WorkflowJobAccess(rando).filtered_queryset() + + org = workflow_job.organization + role = getattr(org, org_role) + role.members.add(rando) + + assert UnifiedJobAccess(rando).can_read(workflow_job) + assert WorkflowJobAccess(rando).can_read(workflow_job) + assert workflow_job in WorkflowJobAccess(rando).filtered_queryset() + + # Organization-level permissions should persist after deleting the WFJT + workflow_job_template.delete() + assert UnifiedJobAccess(rando).can_read(workflow_job) + assert WorkflowJobAccess(rando).can_read(workflow_job) + assert workflow_job in WorkflowJobAccess(rando).filtered_queryset() + @pytest.mark.django_db class TestWFJTCopyAccess: