From b7b92cb9956d0d0d2ef90233f16d810366ca53ba Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Wed, 22 Oct 2014 15:05:05 -0500 Subject: [PATCH] Only allow superusers to create other superusers. --- awx/api/views.py | 35 +++++++++++++++++++++++++++++++---- awx/main/tests/projects.py | 5 ++++- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/awx/api/views.py b/awx/api/views.py index 66c8c22b8a..499a590518 100644 --- a/awx/api/views.py +++ b/awx/api/views.py @@ -428,6 +428,33 @@ class DashboardInventoryGraphView(APIView): return Response(dashboard_data) + +class UserCreateAPIMixin(object): + """A mixin subclass that ensures that only a superuser is able to create + another superuser. + """ + def post(self, request, pk=None): + self._superuser_sanity_check(request) + return super(UserCreateAPIMixin, self).post(request, pk=pk) + + # def put(self, request, pk=None): + # self._superuser_sanity_check(request) + # return super(UserCreateAPIMixin, self).put(request, pk=pk) + + # def patch(self, request, pk=None): + # self._superuser_sanity_check(request) + # return super(UserCreateAPIMixin, self).patch(request, pk=pk) + + def _superuser_sanity_check(self, request): + """Ensure that if a non-superuser tries to create a superuser, + that the request is rejected. + """ + if not request.user.is_superuser: + if request.DATA.get('is_superuser', False): + raise PermissionDenied('Only superusers may create ' + 'other superusers.') + + class ScheduleList(ListAPIView): view_name = "Schedules" @@ -489,14 +516,14 @@ class OrganizationInventoriesList(SubListAPIView): parent_model = Organization relationship = 'inventories' -class OrganizationUsersList(SubListCreateAPIView): +class OrganizationUsersList(UserCreateAPIMixin, SubListCreateAPIView): model = User serializer_class = UserSerializer parent_model = Organization relationship = 'users' -class OrganizationAdminsList(SubListCreateAPIView): +class OrganizationAdminsList(UserCreateAPIMixin, SubListCreateAPIView): model = User serializer_class = UserSerializer @@ -536,7 +563,7 @@ class TeamDetail(RetrieveUpdateDestroyAPIView): model = Team serializer_class = TeamSerializer -class TeamUsersList(SubListCreateAPIView): +class TeamUsersList(UserCreateAPIMixin, SubListCreateAPIView): model = User serializer_class = UserSerializer @@ -731,7 +758,7 @@ class ProjectUpdateCancel(GenericAPIView): else: return self.http_method_not_allowed(request, *args, **kwargs) -class UserList(ListCreateAPIView): +class UserList(UserCreateAPIMixin, ListCreateAPIView): model = User serializer_class = UserSerializer diff --git a/awx/main/tests/projects.py b/awx/main/tests/projects.py index 4ba27c4056..9483ebd2e8 100644 --- a/awx/main/tests/projects.py +++ b/awx/main/tests/projects.py @@ -415,7 +415,10 @@ class ProjectsTest(BaseTransactionTest): all_users = self.get(reverse('api:user_list'), expect=200, auth=self.get_normal_credentials()) for x in all_users['results']: self.post(team_users, data=x, expect=403, auth=self.get_nobody_credentials()) - self.post(team_users, data=x, expect=204, auth=self.get_normal_credentials()) + self.post(team_users, data=dict(x, is_superuser=False), + expect=204, auth=self.get_normal_credentials()) + self.post(team_users, data=dict(x, is_superuser=True), + expect=403, auth=self.get_normal_credentials()) self.assertEqual(Team.objects.get(pk=team.pk).users.count(), 4)