From 98dd79775ba7b46e21693b60901b1148f94346c7 Mon Sep 17 00:00:00 2001 From: AlanCoding Date: Mon, 11 Apr 2016 10:05:04 -0400 Subject: [PATCH 1/4] series of tests to verify user executing permissions --- .../api/test_job_start_permissions.py | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 awx/main/tests/functional/api/test_job_start_permissions.py diff --git a/awx/main/tests/functional/api/test_job_start_permissions.py b/awx/main/tests/functional/api/test_job_start_permissions.py new file mode 100644 index 0000000000..4f91addd95 --- /dev/null +++ b/awx/main/tests/functional/api/test_job_start_permissions.py @@ -0,0 +1,47 @@ +import pytest + +from awx.main.models.inventory import Inventory +from awx.main.models.credential import Credential +from awx.main.models.jobs import JobTemplate + +@pytest.fixture +def machine_credential(): + return Credential.objects.create(name='machine-cred', kind='ssh', username='test_user', password='pas4word') + +@pytest.mark.django_db +@pytest.mark.job_permissions +def test_admin_executing_permissions(deploy_jobtemplate, inventory, machine_credential, user): + + admin_user = user('admin-user', True) + + assert admin_user.can_access(Inventory, 'read', inventory) + assert admin_user.can_access(Inventory, 'execute', inventory) # for ad_hoc + assert admin_user.can_access(JobTemplate, 'start', deploy_jobtemplate) + assert admin_user.can_access(Credential, 'read', machine_credential) + +@pytest.mark.django_db +@pytest.mark.job_permissions +def test_job_template_start_access(deploy_jobtemplate, user): + + common_user = user('test-user', False) + deploy_jobtemplate.executor_role.members.add(common_user) + + assert common_user.can_access(JobTemplate, 'start', deploy_jobtemplate) + +@pytest.mark.django_db +@pytest.mark.job_permissions +def test_credential_use_access(machine_credential, user): + + common_user = user('test-user', False) + machine_credential.usage_role.members.add(common_user) + + assert common_user.can_access(Credential, 'read', machine_credential) + +@pytest.mark.django_db +@pytest.mark.job_permissions +def test_inventory_use_access(inventory, user): + + common_user = user('test-user', False) + inventory.executor_role.members.add(common_user) + + assert common_user.can_access(Inventory, 'start', inventory) From e5b9766c8fb374a28e1e608923c26400238c0297 Mon Sep 17 00:00:00 2001 From: Wayne Witzel III Date: Tue, 12 Apr 2016 13:28:03 -0400 Subject: [PATCH 2/4] Update Job start / access permissions --- awx/main/access.py | 17 +++++++++++++++++ awx/main/migrations/0008_v300_rbac_changes.py | 5 +++++ awx/main/models/inventory.py | 5 +++++ ...rt_permissions.py => test_rbac_job_start.py} | 12 ++++++------ 4 files changed, 33 insertions(+), 6 deletions(-) rename awx/main/tests/functional/{api/test_job_start_permissions.py => test_rbac_job_start.py} (75%) diff --git a/awx/main/access.py b/awx/main/access.py index 8cf71f9f88..09bea1beb4 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -312,8 +312,15 @@ class InventoryAccess(BaseAccess): return qs.select_related('created_by', 'modified_by', 'organization').all() def can_read(self, obj): + if self.user.is_superuser: + return True return obj.accessible_by(self.user, {'read': True}) + def can_use(self, obj): + if self.user.is_superuser: + return True + return obj.accessible_by(self.user, {'use': True}) + def can_add(self, data): # If no data is specified, just checking for generic add permission? if not data: @@ -551,6 +558,11 @@ class CredentialAccess(BaseAccess): # Access enforced in our view where we have context enough to make a decision return True + def can_use(self, obj): + if self.user.is_superuser: + return True + return obj.accessible_by(self.user, {'use': True}) + def can_change(self, obj, data): if self.user.is_superuser: return True @@ -770,6 +782,11 @@ class JobTemplateAccess(BaseAccess): return False if obj.project is None: return False + + # Given explicit execute access to this JobTemplate + if obj.accessible_by(self.user, {'execute':True}): + return True + # If the user has admin access to the project they can start a job if obj.project.accessible_by(self.user, ALL_PERMISSIONS): return True diff --git a/awx/main/migrations/0008_v300_rbac_changes.py b/awx/main/migrations/0008_v300_rbac_changes.py index 30d058cfd3..bbdd9fa540 100644 --- a/awx/main/migrations/0008_v300_rbac_changes.py +++ b/awx/main/migrations/0008_v300_rbac_changes.py @@ -141,6 +141,11 @@ class Migration(migrations.Migration): name='updater_role', field=awx.main.fields.ImplicitRoleField(related_name='+', to='main.Role', null=b'True'), ), + migrations.AddField( + model_name='inventory', + name='usage_role', + field=awx.main.fields.ImplicitRoleField(related_name='+', to='main.Role', null=b'True'), + ), migrations.AddField( model_name='custominventoryscript', name='admin_role', diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index e8398e4544..2af823885d 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -113,6 +113,11 @@ class Inventory(CommonModel, ResourceMixin): role_description='May update the inventory', permissions = {'read': True, 'update': True} ) + usage_role = ImplicitRoleField( + role_name='Inventory User', + role_description='May use this inventory, but not read sensitive portions or modify it', + permissions = {'use': True} + ) executor_role = ImplicitRoleField( role_name='Inventory Executor', role_description='May execute jobs against this inventory', diff --git a/awx/main/tests/functional/api/test_job_start_permissions.py b/awx/main/tests/functional/test_rbac_job_start.py similarity index 75% rename from awx/main/tests/functional/api/test_job_start_permissions.py rename to awx/main/tests/functional/test_rbac_job_start.py index 4f91addd95..67e661431d 100644 --- a/awx/main/tests/functional/api/test_job_start_permissions.py +++ b/awx/main/tests/functional/test_rbac_job_start.py @@ -14,10 +14,10 @@ def test_admin_executing_permissions(deploy_jobtemplate, inventory, machine_cred admin_user = user('admin-user', True) - assert admin_user.can_access(Inventory, 'read', inventory) - assert admin_user.can_access(Inventory, 'execute', inventory) # for ad_hoc + assert admin_user.can_access(Inventory, 'use', inventory) + assert admin_user.can_access(Inventory, 'run_ad_hoc_commands', inventory) # for ad_hoc assert admin_user.can_access(JobTemplate, 'start', deploy_jobtemplate) - assert admin_user.can_access(Credential, 'read', machine_credential) + assert admin_user.can_access(Credential, 'use', machine_credential) @pytest.mark.django_db @pytest.mark.job_permissions @@ -35,13 +35,13 @@ def test_credential_use_access(machine_credential, user): common_user = user('test-user', False) machine_credential.usage_role.members.add(common_user) - assert common_user.can_access(Credential, 'read', machine_credential) + assert common_user.can_access(Credential, 'use', machine_credential) @pytest.mark.django_db @pytest.mark.job_permissions def test_inventory_use_access(inventory, user): common_user = user('test-user', False) - inventory.executor_role.members.add(common_user) + inventory.usage_role.members.add(common_user) - assert common_user.can_access(Inventory, 'start', inventory) + assert common_user.can_access(Inventory, 'use', inventory) From e3ebbab17d3e690845b60a97e793443ee38422c2 Mon Sep 17 00:00:00 2001 From: jlmitch5 Date: Tue, 12 Apr 2016 15:58:17 -0400 Subject: [PATCH 3/4] fix list label of status --- awx/ui/client/src/lists/Jobs.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/awx/ui/client/src/lists/Jobs.js b/awx/ui/client/src/lists/Jobs.js index 0441d1da23..c751629baa 100644 --- a/awx/ui/client/src/lists/Jobs.js +++ b/awx/ui/client/src/lists/Jobs.js @@ -29,7 +29,8 @@ export default awTipPlacement: "top", }, status: { - label: 'Status', + label: '', + searchLabel: 'Status', columnClass: 'col-lg-1 col-md-2 col-sm-2 col-xs-2', awToolTip: "{{ job.status_tip }}", awTipPlacement: "top", From ad89491a07d32c13659ba58eb09363bc3921fe64 Mon Sep 17 00:00:00 2001 From: Akita Noek Date: Tue, 12 Apr 2016 16:31:11 -0400 Subject: [PATCH 4/4] Fixed bad merge --- awx/main/migrations/0008_v300_rbac_changes.py | 1 - 1 file changed, 1 deletion(-) diff --git a/awx/main/migrations/0008_v300_rbac_changes.py b/awx/main/migrations/0008_v300_rbac_changes.py index e6c9e40582..8848bbabd7 100644 --- a/awx/main/migrations/0008_v300_rbac_changes.py +++ b/awx/main/migrations/0008_v300_rbac_changes.py @@ -170,7 +170,6 @@ class Migration(migrations.Migration): migrations.AddField( model_name='inventory', name='usage_role', - field=awx.main.fields.ImplicitRoleField(related_name='+', to='main.Role', null=b'True'), field=awx.main.fields.ImplicitRoleField(related_name='+', role_description=b'May use this inventory, but not read sensitive portions or modify it', parent_role=None, to='main.Role', role_name=b'Inventory User', null=b'True', permissions={b'use': True}), ), migrations.AddField(