Skip to content

Commit

Permalink
Merge pull request ansible#3810 from vismay-golwala/restrict_copy_jt
Browse files Browse the repository at this point in the history
Raise meaningful error when permission denied to copy JT

Reviewed-by: https://github.com/softwarefactory-project-zuul[bot]
  • Loading branch information
2 parents 6908558 + 0154d80 commit c7fe840
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 16 deletions.
7 changes: 5 additions & 2 deletions awx/api/generics.py
Original file line number Diff line number Diff line change
Expand Up @@ -959,8 +959,11 @@ def get(self, request, *args, **kwargs):
create_kwargs = self._build_create_dict(obj)
for key in create_kwargs:
create_kwargs[key] = getattr(create_kwargs[key], 'pk', None) or create_kwargs[key]
can_copy = request.user.can_access(self.model, 'add', create_kwargs) and \
request.user.can_access(self.model, 'copy_related', obj)
try:
can_copy = request.user.can_access(self.model, 'add', create_kwargs) and \
request.user.can_access(self.model, 'copy_related', obj)
except PermissionDenied:
return Response({'can_copy': False})
return Response({'can_copy': can_copy})

def post(self, request, *args, **kwargs):
Expand Down
5 changes: 4 additions & 1 deletion awx/main/access.py
Original file line number Diff line number Diff line change
Expand Up @@ -1507,7 +1507,10 @@ def can_copy_related(self, obj):

# obj.credentials.all() is accessible ONLY when object is saved (has valid id)
credential_manager = getattr(obj, 'credentials', None) if getattr(obj, 'id', False) else Credential.objects.none()
return reduce(lambda prev, cred: prev and self.user in cred.use_role, credential_manager.all(), True)
user_can_copy = reduce(lambda prev, cred: prev and self.user in cred.use_role, credential_manager.all(), True)
if not user_can_copy:
raise PermissionDenied(_('Insufficient access to Job Template credentials.'))
return user_can_copy

def can_start(self, obj, validate_license=True):
# Check license.
Expand Down
45 changes: 32 additions & 13 deletions awx/main/tests/functional/test_copy.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,44 @@ def test_job_template_copy(post, get, project, inventory, machine_credential, va
reverse('api:job_template_copy', kwargs={'pk': job_template_with_survey_passwords.pk}),
admin, expect=200
).data['can_copy'] is True
post(
assert post(
reverse('api:job_template_copy', kwargs={'pk': job_template_with_survey_passwords.pk}),
{'name': 'new jt name'}, alice, expect=403
)
).data['detail'] == 'Insufficient access to Job Template credentials.'
jt_copy_pk = post(
reverse('api:job_template_copy', kwargs={'pk': job_template_with_survey_passwords.pk}),
{'name': 'new jt name'}, admin, expect=201
).data['id']
jt_copy = type(job_template_with_survey_passwords).objects.get(pk=jt_copy_pk)
assert jt_copy.created_by == admin
assert jt_copy.name == 'new jt name'
assert jt_copy.project == project
assert jt_copy.inventory == inventory
assert jt_copy.playbook == job_template_with_survey_passwords.playbook
assert jt_copy.credentials.count() == 3
assert credential in jt_copy.credentials.all()
assert vault_credential in jt_copy.credentials.all()
assert machine_credential in jt_copy.credentials.all()
assert job_template_with_survey_passwords.survey_spec == jt_copy.survey_spec

# give credential access to user 'alice'
for c in (credential, machine_credential, vault_credential):
c.use_role.members.add(alice)
c.save()
assert get(
reverse('api:job_template_copy', kwargs={'pk': job_template_with_survey_passwords.pk}),
alice, expect=200
).data['can_copy'] is True
jt_copy_pk_alice = post(
reverse('api:job_template_copy', kwargs={'pk': job_template_with_survey_passwords.pk}),
{'name': 'new jt name'}, alice, expect=201
).data['id']

jt_copy_admin = type(job_template_with_survey_passwords).objects.get(pk=jt_copy_pk)
jt_copy_alice = type(job_template_with_survey_passwords).objects.get(pk=jt_copy_pk_alice)

assert jt_copy_admin.created_by == admin
assert jt_copy_alice.created_by == alice

for jt_copy in (jt_copy_admin, jt_copy_alice):
assert jt_copy.name == 'new jt name'
assert jt_copy.project == project
assert jt_copy.inventory == inventory
assert jt_copy.playbook == job_template_with_survey_passwords.playbook
assert jt_copy.credentials.count() == 3
assert credential in jt_copy.credentials.all()
assert vault_credential in jt_copy.credentials.all()
assert machine_credential in jt_copy.credentials.all()
assert job_template_with_survey_passwords.survey_spec == jt_copy.survey_spec


@pytest.mark.django_db
Expand Down

0 comments on commit c7fe840

Please sign in to comment.