From cef7f5a16597119d55958eea2b3dd82d7b27f6e0 Mon Sep 17 00:00:00 2001 From: Wayne Witzel III Date: Thu, 18 Aug 2016 09:55:20 -0400 Subject: [PATCH 1/2] prevent non-superusers from adding orphan users --- awx/api/permissions.py | 9 ++++++++- awx/api/views.py | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/awx/api/permissions.py b/awx/api/permissions.py index 6e1320e2d8..285441421d 100644 --- a/awx/api/permissions.py +++ b/awx/api/permissions.py @@ -19,7 +19,7 @@ from awx.main.utils import get_object_or_400 logger = logging.getLogger('awx.api.permissions') __all__ = ['ModelAccessPermission', 'JobTemplateCallbackPermission', - 'TaskPermission', 'ProjectUpdatePermission'] + 'TaskPermission', 'ProjectUpdatePermission', 'UserPermission'] class ModelAccessPermission(permissions.BasePermission): ''' @@ -202,3 +202,10 @@ class ProjectUpdatePermission(ModelAccessPermission): def check_post_permissions(self, request, view, obj=None): project = get_object_or_400(view.model, pk=view.kwargs['pk']) return check_user_access(request.user, view.model, 'start', project) + + +class UserPermission(ModelAccessPermission): + def check_post_permissions(self, request, view, obj=None): + if request.user.is_superuser: + return True + raise PermissionDenied() diff --git a/awx/api/views.py b/awx/api/views.py index 0b20304892..a58b706856 100644 --- a/awx/api/views.py +++ b/awx/api/views.py @@ -1152,6 +1152,7 @@ class UserList(ListCreateAPIView): model = User serializer_class = UserSerializer + permission_classes = (UserPermission,) def post(self, request, *args, **kwargs): ret = super(UserList, self).post( request, *args, **kwargs) From 706e98c392a723c485123e931755dd59338ddc40 Mon Sep 17 00:00:00 2001 From: Wayne Witzel III Date: Fri, 19 Aug 2016 18:54:56 -0400 Subject: [PATCH 2/2] fixing old tests for new user creation permissions --- awx/main/tests/old/users.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/awx/main/tests/old/users.py b/awx/main/tests/old/users.py index de364ff161..6fc7726512 100644 --- a/awx/main/tests/old/users.py +++ b/awx/main/tests/old/users.py @@ -192,8 +192,12 @@ class UsersTest(BaseTest): self.post(url, expect=403, data=new_user, auth=self.get_other_credentials()) self.post(url, expect=201, data=new_user, auth=self.get_super_credentials()) self.post(url, expect=400, data=new_user, auth=self.get_super_credentials()) - self.post(url, expect=201, data=new_user2, auth=self.get_normal_credentials()) - self.post(url, expect=400, data=new_user2, auth=self.get_normal_credentials()) + # org admin cannot create orphaned users + self.post(url, expect=403, data=new_user2, auth=self.get_normal_credentials()) + # org admin can create org users + org_url = reverse('api:organization_users_list', args=(self.organizations[0].pk,)) + self.post(org_url, expect=201, data=new_user2, auth=self.get_normal_credentials()) + self.post(org_url, expect=400, data=new_user2, auth=self.get_normal_credentials()) # Normal user cannot add users after his org is marked inactive. self.organizations[0].delete() new_user3 = dict(username='blippy3') @@ -367,23 +371,20 @@ class UsersTest(BaseTest): url = reverse('api:user_list') data = dict(username='username', password='password') data2 = dict(username='username2', password='password2') - data = self.post(url, expect=201, data=data, auth=self.get_normal_credentials()) + # but a regular user cannot create users + self.post(url, expect=403, data=data2, auth=self.get_other_credentials()) + # org admins cannot create orphaned users + self.post(url, expect=403, data=data2, auth=self.get_normal_credentials()) + + # a super user can create new users + self.post(url, expect=201, data=data, auth=self.get_super_credentials()) # verify that the login works... self.get(url, expect=200, auth=('username', 'password')) - # but a regular user cannot - data = self.post(url, expect=403, data=data2, auth=self.get_other_credentials()) - - # a super user can also create new users - data = self.post(url, expect=201, data=data2, auth=self.get_super_credentials()) - - # verify that the login works - self.get(url, expect=200, auth=('username2', 'password2')) - # verify that if you post a user with a pk, you do not alter that user's password info mod = dict(id=self.super_django_user.pk, username='change', password='change') - data = self.post(url, expect=201, data=mod, auth=self.get_super_credentials()) + self.post(url, expect=201, data=mod, auth=self.get_super_credentials()) orig = User.objects.get(pk=self.super_django_user.pk) self.assertTrue(orig.username != 'change')