def test_system_auditor_JT_attach(system_auditor, job_template, notification_template): job_template.admin_role.members.add(system_auditor) access = JobTemplateAccess(system_auditor) assert not access.can_attach(job_template, notification_template, 'notification_templates_success', {'id': notification_template.id})
def test_jt_add_scan_job_check(job_template_with_ids, user_unit): "Assure that permissions to add scan jobs work correctly" access = JobTemplateAccess(user_unit) project = job_template_with_ids.project inventory = job_template_with_ids.inventory project.use_role = Role() inventory.use_role = Role() organization = Organization(name='test-org') inventory.organization = organization organization.admin_role = Role() def mock_get_object(Class, **kwargs): if Class == Project: return project elif Class == Inventory: return inventory else: raise Exception('Item requested has not been mocked') with mock.patch.object(JobTemplateAccess, 'check_license', return_value=None): with mock.patch('awx.main.models.rbac.Role.__contains__', return_value=True): with mock.patch('awx.main.access.get_object_or_400', mock_get_object): assert access.can_add({ 'project': project.pk, 'inventory': inventory.pk, 'job_type': 'scan' })
def test_job_template_access_superuser(check_license, user, deploy_jobtemplate): # GIVEN a superuser u = user('admin', True) # WHEN access to a job template is checked access = JobTemplateAccess(u) # THEN all access checks should pass assert access.can_read(deploy_jobtemplate) assert access.can_add({})
def test_jt_existing_values_are_nonsensitive(job_template_with_ids, user_unit): """Assure that permission checks are not required if submitted data is identical to what the job template already has.""" data = model_to_dict(job_template_with_ids) access = JobTemplateAccess(user_unit) assert access.changes_are_non_sensitive(job_template_with_ids, data)
def test_job_start_allowed_with_survey_spec(job_template_factory, admin_user): """After user downgrades survey license and disables survey on the JT, check that jobs still launch even if the survey_spec data persists.""" objects = job_template_factory('jt', project='prj', survey='submitter_email') obj = objects.job_template obj.survey_enabled = False obj.save() access = JobTemplateAccess(admin_user) assert access.can_start(job_template_with_survey, {})
def test_job_template_access_admin(role_names, jt_linked, rando): ssh_cred = jt_linked.machine_credential access = JobTemplateAccess(rando) # Appoint this user as admin of the organization #jt_linked.inventory.organization.admin_role.members.add(rando) assert not access.can_read(jt_linked) assert not access.can_delete(jt_linked) for role_name in role_names: role = getattr(jt_linked.inventory.organization, role_name) role.members.add(rando) # Assign organization permission in the same way the create view does organization = jt_linked.inventory.organization ssh_cred.admin_role.parents.add(organization.admin_role) proj_pk = jt_linked.project.pk assert access.can_add( dict(inventory=jt_linked.inventory.pk, project=proj_pk)) assert access.can_add(dict(credential=ssh_cred.pk, project=proj_pk)) for cred in jt_linked.credentials.all(): assert access.can_unattach(jt_linked, cred, 'credentials', {}) assert access.can_read(jt_linked) assert access.can_delete(jt_linked)
def test_job_template_cannot_add_extra_credentials(self, job_template, credential, rando): job_template.admin_role.members.add(rando) credential.read_role.members.add(rando) # without permission to credential, user can not attach it assert not JobTemplateAccess(rando).can_attach( job_template, credential, 'credentials', {})
def test_job_template_can_add_extra_credentials(self, job_template, credential, rando): job_template.admin_role.members.add(rando) credential.use_role.members.add(rando) # user has permission to apply credential assert JobTemplateAccess(rando).can_attach(job_template, credential, 'credentials', {})
def test_job_template_access_use_level(jt_linked, rando): access = JobTemplateAccess(rando) jt_linked.project.use_role.members.add(rando) jt_linked.inventory.use_role.members.add(rando) jt_linked.organization.job_template_admin_role.members.add(rando) proj_pk = jt_linked.project.pk org_pk = jt_linked.organization_id assert access.can_change(jt_linked, { 'job_type': 'check', 'project': proj_pk }) assert access.can_change(jt_linked, { 'job_type': 'check', 'inventory': None }) for cred in jt_linked.credentials.all(): assert access.can_unattach(jt_linked, cred, 'credentials', {}) assert access.can_add( dict(inventory=jt_linked.inventory.pk, project=proj_pk, organization=org_pk)) assert access.can_add(dict(project=proj_pk, organization=org_pk))
def test_change_jt_sensitive_data(job_template_with_ids, mocker, user_unit): """Assure that can_add is called with all ForeignKeys.""" job_template_with_ids.admin_role = Role() data = {'inventory': job_template_with_ids.inventory.id + 1} access = JobTemplateAccess(user_unit) mock_add = mock.MagicMock(return_value=False) with mock.patch('awx.main.models.rbac.Role.__contains__', return_value=True): with mocker.patch('awx.main.access.JobTemplateAccess.can_add', mock_add): with mocker.patch('awx.main.access.JobTemplateAccess.can_read', return_value=True): assert not access.can_change(job_template_with_ids, data) mock_add.assert_called_once_with({ 'inventory': data['inventory'], 'project': job_template_with_ids.project.id })
def test_project_use_access(project, rando): project.use_role.members.add(rando) access = JobTemplateAccess(rando) assert access.can_add(None) assert access.can_add({ 'project': project.id, 'ask_inventory_on_launch': True }) project2 = Project.objects.create( name='second-project', scm_type=project.scm_type, playbook_files=project.playbook_files, organization=project.organization, ) project2.use_role.members.add(rando) jt = JobTemplate.objects.create(project=project, ask_inventory_on_launch=True) jt.admin_role.members.add(rando) assert access.can_change(jt, {'project': project2.pk})
def test_change_jt_sensitive_data(job_template_with_ids, mocker, user_unit): """Assure that can_add is called with all ForeignKeys.""" class RoleReturnsTrue(Role): class Meta: proxy = True def __contains__(self, accessor): return True job_template_with_ids.admin_role = RoleReturnsTrue() job_template_with_ids.organization.job_template_admin_role = RoleReturnsTrue( ) inv2 = Inventory() inv2.use_role = RoleReturnsTrue() data = {'inventory': inv2} access = JobTemplateAccess(user_unit) assert not access.changes_are_non_sensitive(job_template_with_ids, data) job_template_with_ids.inventory.use_role = RoleReturnsTrue() job_template_with_ids.project.use_role = RoleReturnsTrue() assert access.can_change(job_template_with_ids, data)
def test_job_template_access_org_admin(jt_linked, rando): access = JobTemplateAccess(rando) # Appoint this user as admin of the organization jt_linked.inventory.organization.admin_role.members.add(rando) # Assign organization permission in the same way the create view does organization = jt_linked.inventory.organization jt_linked.get_deprecated_credential('ssh').admin_role.parents.add(organization.admin_role) proj_pk = jt_linked.project.pk assert access.can_add(dict(inventory=jt_linked.inventory.pk, project=proj_pk)) assert access.can_add(dict(credential=jt_linked.credential, project=proj_pk)) for cred in jt_linked.credentials.all(): assert access.can_unattach(jt_linked, cred, 'credentials', {}) assert access.can_read(jt_linked) assert access.can_delete(jt_linked)
def test_job_template_access_read_level(jt_linked, rando): access = JobTemplateAccess(rando) jt_linked.project.read_role.members.add(rando) jt_linked.inventory.read_role.members.add(rando) jt_linked.get_deprecated_credential('ssh').read_role.members.add(rando) proj_pk = jt_linked.project.pk assert not access.can_add(dict(inventory=jt_linked.inventory.pk, project=proj_pk)) assert not access.can_add(dict(credential=jt_linked.credential, project=proj_pk)) assert not access.can_add(dict(vault_credential=jt_linked.vault_credential, project=proj_pk)) for cred in jt_linked.credentials.all(): assert not access.can_unattach(jt_linked, cred, 'credentials', {})
def test_jt_org_ownership_change(user, jt_linked): admin1 = user('admin1') org1 = jt_linked.project.organization org1.admin_role.members.add(admin1) a1_access = JobTemplateAccess(admin1) assert a1_access.can_read(jt_linked) admin2 = user('admin2') org2 = Organization.objects.create(name='mrroboto', description='domo') org2.admin_role.members.add(admin2) a2_access = JobTemplateAccess(admin2) assert not a2_access.can_read(jt_linked) jt_linked.project.organization = org2 jt_linked.project.save() jt_linked.inventory.organization = org2 jt_linked.inventory.save() assert a2_access.can_read(jt_linked) assert not a1_access.can_read(jt_linked)
def test_job_template_access_read_level(jt_linked, rando): ssh_cred = jt_linked.machine_credential vault_cred = jt_linked.vault_credentials[0] access = JobTemplateAccess(rando) jt_linked.project.read_role.members.add(rando) jt_linked.inventory.read_role.members.add(rando) ssh_cred.read_role.members.add(rando) proj_pk = jt_linked.project.pk assert not access.can_add(dict(inventory=jt_linked.inventory.pk, project=proj_pk)) assert not access.can_add(dict(credential=ssh_cred.pk, project=proj_pk)) assert not access.can_add(dict(vault_credential=vault_cred.pk, project=proj_pk)) for cred in jt_linked.credentials.all(): assert not access.can_unattach(jt_linked, cred, 'credentials', {})
def test_job_template_access_use_level(jt_linked, rando): access = JobTemplateAccess(rando) jt_linked.project.use_role.members.add(rando) jt_linked.inventory.use_role.members.add(rando) jt_linked.credential.use_role.members.add(rando) jt_linked.vault_credential.use_role.members.add(rando) proj_pk = jt_linked.project.pk assert access.can_add( dict(inventory=jt_linked.inventory.pk, project=proj_pk)) assert access.can_add( dict(credential=jt_linked.credential.pk, project=proj_pk)) assert access.can_add( dict(vault_credential=jt_linked.vault_credential.pk, project=proj_pk)) for cred in jt_linked.extra_credentials.all(): assert not access.can_unattach(jt_linked, cred, 'extra_credentials', {})
def test_associate_label(label, user, job_template): access = JobTemplateAccess(user('joe', False)) job_template.admin_role.members.add(user('joe', False)) label.organization.read_role.members.add(user('joe', False)) assert access.can_attach(job_template, label, 'labels', None)
def test_system_admin_orphan_capabilities(self, job_template, admin_user): job_template.capabilities_cache = {'edit': False} access = JobTemplateAccess(admin_user) capabilities = access.get_user_capabilities(job_template, method_list=['edit']) assert capabilities['edit']
def test_orphan_JT_readable_by_system_auditor(self, job_template, system_auditor): assert system_auditor.is_system_auditor assert job_template.project is None access = JobTemplateAccess(system_auditor) assert access.can_read(job_template)
def test_disable_survey_access_without_license(job_template_with_survey, admin_user): """Assure that user can disable a JT survey after downgrading license.""" access = JobTemplateAccess(admin_user) assert access.can_change(job_template_with_survey, dict(survey_enabled=False))
def test_delete_survey_access_without_license(job_template_with_survey, admin_user): """Assure that access.py allows deleting surveys after downgrading license.""" access = JobTemplateAccess(admin_user) assert access.can_change(job_template_with_survey, dict(survey_spec=None)) assert access.can_change(job_template_with_survey, dict(survey_spec={}))
def test_jt_can_start_ha(job_template_with_ids): with mock.patch.object(Instance.objects, 'active_count', return_value=2): with mock.patch('awx.main.access.BaseAccess.check_license', new=mock_raise_license_forbids): with pytest.raises(LicenseForbids): JobTemplateAccess(user_unit).can_start(job_template_with_ids)
def test_job_template_delete_access_with_survey(job_template_with_survey, admin_user): """The survey_spec view relies on JT `can_delete` to determine permission to delete the survey. This checks that system admins can delete the survey on a JT.""" access = JobTemplateAccess(admin_user) assert access.can_delete(job_template_with_survey)
def test_new_jt_with_vault(self, vault_credential, project, rando): project.admin_role.members.add(rando) assert not JobTemplateAccess(rando).can_add({ 'vault_credential': vault_credential, 'project': project.pk })
def test_job_template_vault_cred_check(self, job_template, vault_credential, rando): job_template.admin_role.members.add(rando) # not allowed to use the vault cred assert not JobTemplateAccess(rando).can_change( job_template, {'vault_credential': vault_credential})
def test_jt_can_add_bad_data(user_unit): "Assure that no server errors are returned if we call JT can_add with bad data" access = JobTemplateAccess(user_unit) assert not access.can_add({'asdf': 'asdf'})
def test_ig_associability(organization, default_instance_group, admin, system_auditor, org_admin, org_member, job_template_factory): admin_access = OrganizationAccess(admin) auditor_access = OrganizationAccess(system_auditor) oadmin_access = OrganizationAccess(org_admin) omember_access = OrganizationAccess(org_member) assert admin_access.can_attach(organization, default_instance_group, 'instance_groups', None) assert not oadmin_access.can_attach(organization, default_instance_group, 'instance_groups', None) assert not auditor_access.can_attach(organization, default_instance_group, 'instance_groups', None) assert not omember_access.can_attach(organization, default_instance_group, 'instance_groups', None) organization.instance_groups.add(default_instance_group) assert admin_access.can_unattach(organization, default_instance_group, 'instance_groups', None) assert not oadmin_access.can_unattach(organization, default_instance_group, 'instance_groups', None) assert not auditor_access.can_unattach( organization, default_instance_group, 'instance_groups', None) assert not omember_access.can_unattach( organization, default_instance_group, 'instance_groups', None) objects = job_template_factory('jt', organization=organization, project='p', inventory='i', credential='c') admin_access = InventoryAccess(admin) auditor_access = InventoryAccess(system_auditor) oadmin_access = InventoryAccess(org_admin) omember_access = InventoryAccess(org_member) assert admin_access.can_attach(objects.inventory, default_instance_group, 'instance_groups', None) assert oadmin_access.can_attach(objects.inventory, default_instance_group, 'instance_groups', None) assert not auditor_access.can_attach( objects.inventory, default_instance_group, 'instance_groups', None) assert not omember_access.can_attach( objects.inventory, default_instance_group, 'instance_groups', None) admin_access = JobTemplateAccess(admin) auditor_access = JobTemplateAccess(system_auditor) oadmin_access = JobTemplateAccess(org_admin) omember_access = JobTemplateAccess(org_member) assert admin_access.can_attach(objects.job_template, default_instance_group, 'instance_groups', None) assert oadmin_access.can_attach(objects.job_template, default_instance_group, 'instance_groups', None) assert not auditor_access.can_attach( objects.job_template, default_instance_group, 'instance_groups', None) assert not omember_access.can_attach( objects.job_template, default_instance_group, 'instance_groups', None)
def test_job_start_blocked_without_survey_license(job_template_with_survey, admin_user): """Check that user can't start a job with surveys without a survey license.""" access = JobTemplateAccess(admin_user) with pytest.raises(LicenseForbids): access.can_start(job_template_with_survey)