Merge pull request #2447 from YunfanZhang42/fix_credential_leak

Forbid users from using unauthorized credentials in projects and inventories.
This commit is contained in:
Yunfan Zhang 2018-07-09 15:06:39 -04:00 committed by GitHub
commit 307e5204fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 8 deletions

View File

@ -740,12 +740,13 @@ class InventoryAccess(BaseAccess):
# If no data is specified, just checking for generic add permission?
if not data:
return Organization.accessible_objects(self.user, 'inventory_admin_role').exists()
return self.check_related('organization', Organization, data, role_field='inventory_admin_role')
return (self.check_related('organization', Organization, data, role_field='inventory_admin_role') and
self.check_related('insights_credential', Credential, data, role_field='use_role'))
@check_superuser
def can_change(self, obj, data):
return self.can_admin(obj, data)
return (self.can_admin(obj, data) and
self.check_related('insights_credential', Credential, data, obj=obj, role_field='use_role'))
@check_superuser
def can_admin(self, obj, data):
@ -1198,14 +1199,15 @@ class ProjectAccess(BaseAccess):
@check_superuser
def can_add(self, data):
if not data: # So the browseable API will work
return Organization.accessible_objects(self.user, 'project_admin_role').exists()
return self.check_related('organization', Organization, data, role_field='project_admin_role', mandatory=True)
return Organization.accessible_objects(self.user, 'admin_role').exists()
return (self.check_related('organization', Organization, data, mandatory=True) and
self.check_related('credential', Credential, data, role_field='use_role'))
@check_superuser
def can_change(self, obj, data):
if not self.check_related('organization', Organization, data, obj=obj, role_field='project_admin_role'):
return False
return self.user in obj.admin_role
return (self.check_related('organization', Organization, data, obj=obj, role_field='project_admin_role') and
self.user in obj.admin_role and
self.check_related('credential', Credential, data, obj=obj, role_field='use_role'))
@check_superuser
def can_start(self, obj, validate_license=True):

View File

@ -450,6 +450,17 @@ class TestInsightsCredential:
{'insights_credential': insights_credential.id}, admin_user,
expect=200)
def test_insights_credential_protection(self, post, patch, insights_inventory, alice, insights_credential):
insights_inventory.organization.admin_role.members.add(alice)
insights_inventory.admin_role.members.add(alice)
post(reverse('api:inventory_list'), {
"name": "test",
"organization": insights_inventory.organization.id,
"insights_credential": insights_credential.id
}, alice, expect=403)
patch(insights_inventory.get_absolute_url(),
{'insights_credential': insights_credential.id}, alice, expect=403)
def test_non_insights_credential(self, patch, insights_inventory, admin_user, scm_credential):
patch(insights_inventory.get_absolute_url(),
{'insights_credential': scm_credential.id}, admin_user,

View File

@ -52,6 +52,7 @@ def test_project_copy(post, get, project, organization, scm_credential, alice):
reverse('api:project_copy', kwargs={'pk': project.pk}), alice, expect=200
).data['can_copy'] is False
project.organization.admin_role.members.add(alice)
scm_credential.use_role.members.add(alice)
assert get(
reverse('api:project_copy', kwargs={'pk': project.pk}), alice, expect=200
).data['can_copy'] is True

View File

@ -209,6 +209,25 @@ def test_create_project(post, organization, org_admin, org_member, admin, rando,
assert Project.objects.filter(name='Project', organization=organization).exists()
@pytest.mark.django_db
def test_project_credential_protection(post, put, project, organization, scm_credential, org_admin):
project.save()
project.admin_role.members.add(org_admin)
put(
reverse('api:project_detail', kwargs={'pk':project.id}), {
'name': 'should not change',
'credential': scm_credential.id
}, org_admin, expect=403
)
post(
reverse('api:project_list'), {
'name': 'should not create',
'organization':organization.id,
'credential': scm_credential.id
}, org_admin, expect=403
)
@pytest.mark.django_db()
def test_create_project_null_organization(post, organization, admin):
post(reverse('api:project_list'), { 'name': 't', 'organization': None}, admin, expect=201)