From f60ba4072d7b9d737a02516e4bce5436461cf547 Mon Sep 17 00:00:00 2001 From: Eva Bardou <ebardou@teklia.com> Date: Tue, 12 Jan 2021 14:34:59 +0000 Subject: [PATCH] Check user permissions before he can access TaskUpdate ponos endpoint --- arkindex/project/openapi/patch.yml | 20 +++++++++++++-- arkindex/project/tests/test_ponos_view.py | 30 ++++++++++++++++++++++- arkindex/project/urls.py | 2 ++ arkindex/project/views.py | 14 ++++++++++- 4 files changed, 62 insertions(+), 4 deletions(-) diff --git a/arkindex/project/openapi/patch.yml b/arkindex/project/openapi/patch.yml index f00115c81c..53db57d3d6 100644 --- a/arkindex/project/openapi/patch.yml +++ b/arkindex/project/openapi/patch.yml @@ -368,19 +368,35 @@ paths: aTgNWsA3WFlqjSIEGz+PAVHSNMobBaJm -----END PUBLIC KEY----- /ponos/v1/task/{id}/: + put: + description: Update a task, allowing humans to change the task's state + operationId: UpdateTask + security: [] + tags: + - ponos + patch: + description: Partially update a task, allowing humans to change the task's state + operationId: PartialUpdateTask + security: [] + tags: + - ponos + /ponos/v1/task/{id}/from-agent/: get: description: Retrieve a Ponos task status + operationId: RetrieveTaskFromAgent security: [] tags: - ponos put: - description: Update a task + description: Update a task, from an agent + operationId: UpdateTaskFromAgent security: - agentAuth: [] tags: - ponos patch: - description: Partially update a task + description: Partially update a task, from an agent + operationId: PartialUpdateTaskFromAgent security: - agentAuth: [] tags: diff --git a/arkindex/project/tests/test_ponos_view.py b/arkindex/project/tests/test_ponos_view.py index 326f6ba6e0..1fd6887090 100644 --- a/arkindex/project/tests/test_ponos_view.py +++ b/arkindex/project/tests/test_ponos_view.py @@ -5,8 +5,9 @@ from django.test import TestCase, override_settings from django.urls import reverse from rest_framework import status +from arkindex.dataimport.models import DataImport, DataImportMode from arkindex.users.models import User -from ponos.models import Agent, Farm, Secret, encrypt +from ponos.models import Agent, Farm, Secret, Workflow, encrypt @override_settings(PONOS_PRIVATE_KEY='staging') @@ -78,3 +79,30 @@ class TestPonosView(TestCase): self.client.force_login(User.objects.create()) response = self.client.get(reverse('ponos-agent-details', kwargs={'pk': str(agent.id)})) self.assertEqual(response.status_code, status.HTTP_200_OK) + + def test_update_task(self): + """ + Only admin users or the task creator should have the ability to update a task + """ + creator = User.objects.create(email="creator@user.fr") + workflow = Workflow.objects.create( + recipe="tasks: {test: {image: alpine}}" + ) + workflow.start() + task = workflow.tasks.get() + DataImport.objects.create(mode=DataImportMode.Repository, creator=creator, workflow=workflow) + + response = self.client.patch(reverse('ponos-task-update', kwargs={'pk': str(task.id)}), json={"state": "stopping"}) + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + + self.client.force_login(User.objects.create(email="lambda@user.fr")) + response = self.client.patch(reverse('ponos-task-update', kwargs={'pk': str(task.id)}), json={"state": "stopping"}) + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + + self.client.force_login(User.objects.create(email='admin@admin.fr', is_admin=True)) + response = self.client.patch(reverse('ponos-task-update', kwargs={'pk': str(task.id)}), json={"state": "stopping"}) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + self.client.force_login(creator) + response = self.client.patch(reverse('ponos-task-update', kwargs={'pk': str(task.id)}), json={"state": "stopping"}) + self.assertEqual(response.status_code, status.HTTP_200_OK) diff --git a/arkindex/project/urls.py b/arkindex/project/urls.py index 02f199ae58..b6c81bde83 100644 --- a/arkindex/project/urls.py +++ b/arkindex/project/urls.py @@ -11,6 +11,7 @@ from arkindex.project.views import ( PonosAgentDetails, PonosAgentsState, PonosSecretDetails, + PonosTaskUpdate, ) # Fallback to the dummy frontend view when CDN_ASSETS_URL is not set @@ -23,6 +24,7 @@ urlpatterns = [ path('ponos/v1/secret/<path:name>', PonosSecretDetails.as_view(), name='secret-details'), path('ponos/v1/agents/', PonosAgentsState.as_view(), name='ponos-agents'), path('ponos/v1/agent/<uuid:pk>/', PonosAgentDetails.as_view(), name='ponos-agent-details'), + path('ponos/v1/task/<uuid:pk>/', PonosTaskUpdate.as_view(), name='ponos-task-update'), path('ponos/', include('ponos.urls')), path('admin/', admin.site.urls), path('rq/', include('django_rq.urls')), diff --git a/arkindex/project/views.py b/arkindex/project/views.py index 06fc7f2141..cc7473e347 100644 --- a/arkindex/project/views.py +++ b/arkindex/project/views.py @@ -4,7 +4,7 @@ from rest_framework import permissions from arkindex.project.mixins import CachedViewMixin from arkindex.project.permissions import IsVerified -from ponos.api import AgentDetails, AgentsState, SecretDetails +from ponos.api import AgentDetails, AgentsState, SecretDetails, TaskUpdate class FrontendView(View): @@ -66,3 +66,15 @@ class PonosAgentDetails(AgentDetails): Allow any verified user to see the details of an agent including all its running tasks """ permission_classes = (IsVerified, ) + + +class PonosTaskUpdate(TaskUpdate): + """ + Allow any super admin or the task creator to update a task. + """ + class IsAdminOrCreator(permissions.BasePermission): + + def has_object_permission(self, request, view, obj): + return request.user.is_authenticated and (request.user.is_admin or request.user == obj.workflow.dataimport.creator) + + permission_classes = (IsAdminOrCreator, ) -- GitLab