mirror of
https://github.com/ZwareBear/awx.git
synced 2026-05-02 04:41:49 -05:00
Set JT.organization with value from its project
Remove validation requiring JT.organization
Undo some of the additional org definitions in tests
Revert some tests no longer needed for feature
exclude workflow approvals from unified organization field
revert awxkit changes for providing organization
Roll back additional JT creation permission requirement
Fix up more issues by persisting organization field when project is removed
Restrict project org editing, logging, and testing
Grant removed inventory org admin permissions in migration
Add special validate_unique for job templates
this deals with enforcing name-organization uniqueness
Add back in special message where config is unknown
when receiving 403 on job relaunch
Fix logical and performance bugs with data migration
within JT.inventory.organization make-permission-explicit migration
remove nested loops so we do .iterator() on JT queryset
in reverse migration, carefully remove execute role on JT
held by org admins of inventory organization,
as well as the execute_role holders
Use current state of Role model in logic, with 1 notable exception
that is used to filter on ancestors
the ancestor and descentent relationship in the migration model
is not reliable
output of this is saved as an integer list to avoid future
compatibility errors
make the parents rebuilding logic skip over irrelevant models
this is the largest performance gain for small resource numbers
168 lines
7.2 KiB
Python
168 lines
7.2 KiB
Python
import pytest
|
|
|
|
from rest_framework.exceptions import PermissionDenied
|
|
|
|
from awx.main.models.inventory import Inventory
|
|
from awx.main.models.credential import Credential
|
|
from awx.main.models.jobs import JobTemplate, Job
|
|
from awx.main.access import (
|
|
UnifiedJobAccess,
|
|
WorkflowJobAccess, WorkflowJobNodeAccess,
|
|
JobAccess
|
|
)
|
|
|
|
|
|
@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, '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, 'use', machine_credential)
|
|
|
|
|
|
@pytest.mark.django_db
|
|
@pytest.mark.job_permissions
|
|
def test_admin_executing_permissions_with_limits(deploy_jobtemplate, inventory, user):
|
|
admin_user = user('admin-user', True)
|
|
|
|
inventory.organization.max_hosts = 1
|
|
inventory.organization.save()
|
|
inventory.hosts.create(name="Existing host 1")
|
|
inventory.hosts.create(name="Existing host 2")
|
|
|
|
assert admin_user.can_access(JobTemplate, 'start', deploy_jobtemplate)
|
|
|
|
|
|
@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.execute_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.use_role.members.add(common_user)
|
|
|
|
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.use_role.members.add(common_user)
|
|
|
|
assert common_user.can_access(Inventory, 'use', inventory)
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_slice_job(slice_job_factory, rando):
|
|
workflow_job = slice_job_factory(2, jt_kwargs={'created_by': rando}, spawn=True)
|
|
workflow_job.job_template.execute_role.members.add(rando)
|
|
|
|
# Abilities of user with execute_role for slice workflow job container
|
|
assert WorkflowJobAccess(rando).can_start(workflow_job) # relaunch allowed
|
|
for access_cls in (UnifiedJobAccess, WorkflowJobAccess):
|
|
access = access_cls(rando)
|
|
assert access.can_read(workflow_job)
|
|
assert workflow_job in access.get_queryset()
|
|
|
|
# Abilities of user with execute_role for all the slice of the job
|
|
for node in workflow_job.workflow_nodes.all():
|
|
access = WorkflowJobNodeAccess(rando)
|
|
assert access.can_read(node)
|
|
assert node in access.get_queryset()
|
|
job = node.job
|
|
assert JobAccess(rando).can_start(job) # relaunch allowed
|
|
for access_cls in (UnifiedJobAccess, JobAccess):
|
|
access = access_cls(rando)
|
|
assert access.can_read(job)
|
|
assert job in access.get_queryset()
|
|
|
|
|
|
@pytest.mark.django_db
|
|
class TestJobRelaunchAccess:
|
|
@pytest.fixture
|
|
def job_no_prompts(self, machine_credential, inventory, organization):
|
|
jt = JobTemplate.objects.create(name='test-job_template', inventory=inventory, organization=organization)
|
|
jt.credentials.add(machine_credential)
|
|
return jt.create_unified_job()
|
|
|
|
@pytest.fixture
|
|
def job_with_prompts(self, machine_credential, inventory, organization, credentialtype_ssh):
|
|
jt = JobTemplate.objects.create(
|
|
name='test-job-template-prompts', inventory=inventory,
|
|
ask_tags_on_launch=True, ask_variables_on_launch=True, ask_skip_tags_on_launch=True,
|
|
ask_limit_on_launch=True, ask_job_type_on_launch=True, ask_verbosity_on_launch=True,
|
|
ask_inventory_on_launch=True, ask_credential_on_launch=True)
|
|
jt.credentials.add(machine_credential)
|
|
new_cred = Credential.objects.create(
|
|
name='new-cred',
|
|
credential_type=credentialtype_ssh,
|
|
inputs={
|
|
'username': 'test_user',
|
|
'password': 'pas4word'
|
|
}
|
|
)
|
|
new_cred.save()
|
|
new_inv = Inventory.objects.create(name='new-inv', organization=organization)
|
|
return jt.create_unified_job(credentials=[new_cred], inventory=new_inv)
|
|
|
|
def test_normal_relaunch_via_job_template(self, job_no_prompts, rando):
|
|
"Has JT execute_role, job unchanged relative to JT"
|
|
job_no_prompts.job_template.execute_role.members.add(rando)
|
|
assert rando.can_access(Job, 'start', job_no_prompts)
|
|
|
|
def test_orphan_relaunch_via_organization(self, job_no_prompts, rando, organization):
|
|
"JT for job has been deleted, relevant organization roles will allow management"
|
|
assert job_no_prompts.organization == organization
|
|
organization.execute_role.members.add(rando)
|
|
job_no_prompts.job_template.delete()
|
|
job_no_prompts.job_template = None # Django should do this for us, but it does not
|
|
assert rando.can_access(Job, 'start', job_no_prompts)
|
|
|
|
def test_no_relaunch_without_prompted_fields_access(self, job_with_prompts, rando):
|
|
"Has JT execute_role but no use_role on inventory & credential - deny relaunch"
|
|
job_with_prompts.job_template.execute_role.members.add(rando)
|
|
with pytest.raises(PermissionDenied) as exc:
|
|
rando.can_access(Job, 'start', job_with_prompts)
|
|
assert 'Job was launched with prompted fields you do not have access to' in str(exc)
|
|
|
|
def test_can_relaunch_with_prompted_fields_access(self, job_with_prompts, rando):
|
|
"Has use_role on the prompted inventory & credential - allow relaunch"
|
|
job_with_prompts.job_template.execute_role.members.add(rando)
|
|
for cred in job_with_prompts.credentials.all():
|
|
cred.use_role.members.add(rando)
|
|
job_with_prompts.inventory.use_role.members.add(rando)
|
|
job_with_prompts.created_by = rando
|
|
assert rando.can_access(Job, 'start', job_with_prompts)
|
|
|
|
def test_no_relaunch_after_limit_change(self, inventory, machine_credential, rando):
|
|
"State of the job contradicts the JT state - deny relaunch based on JT execute"
|
|
jt = JobTemplate.objects.create(name='test-job_template', inventory=inventory, ask_limit_on_launch=True)
|
|
jt.credentials.add(machine_credential)
|
|
job_with_prompts = jt.create_unified_job(limit='webservers')
|
|
jt.ask_limit_on_launch = False
|
|
jt.save()
|
|
jt.execute_role.members.add(rando)
|
|
with pytest.raises(PermissionDenied):
|
|
rando.can_access(Job, 'start', job_with_prompts)
|
|
|
|
def test_can_relaunch_if_limit_was_prompt(self, job_with_prompts, rando):
|
|
"Job state differs from JT, but only on prompted fields - allow relaunch"
|
|
job_with_prompts.job_template.execute_role.members.add(rando)
|
|
job_with_prompts.limit = 'webservers'
|
|
job_with_prompts.save()
|
|
job_with_prompts.inventory.use_role.members.add(rando)
|
|
for cred in job_with_prompts.credentials.all():
|
|
cred.use_role.members.add(rando)
|
|
assert rando.can_access(Job, 'start', job_with_prompts)
|