Skip to content

Commit 6fe9bf3

Browse files
gerrod3mdellweg
authored andcommitted
Add RBAC for TaskGroups
fixes: pulp#5497
1 parent 672a623 commit 6fe9bf3

File tree

5 files changed

+88
-2
lines changed

5 files changed

+88
-2
lines changed

CHANGES/5497.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added RBAC for `TaskGroups` API.

pulpcore/app/tasks/test.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import backoff
2+
from pulpcore.app.models import TaskGroup
3+
from pulpcore.tasking.tasks import dispatch
24

35

46
def dummy_task():
@@ -18,3 +20,13 @@ def gooey_task(interval):
1820
from time import sleep
1921

2022
sleep(interval)
23+
24+
25+
def dummy_group_task(inbetween=3, intervals=None):
26+
"""A group task that dispatches 'interval' sleep tasks every 'inbetween' seconds.'"""
27+
intervals = intervals or range(5)
28+
task_group = TaskGroup.current()
29+
for interval in intervals:
30+
dispatch(sleep, args=(interval,), task_group=task_group)
31+
sleep(inbetween)
32+
task_group.finish()

pulpcore/app/viewsets/task.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,27 @@ class TaskGroupViewSet(NamedModelViewSet, mixins.RetrieveModelMixin, mixins.List
249249
serializer_class = TaskGroupSerializer
250250
ordering = "-pulp_created"
251251

252+
DEFAULT_ACCESS_POLICY = {
253+
"statements": [
254+
{"action": ["list", "retrieve"], "principal": "authenticated", "effect": "allow"},
255+
],
256+
"queryset_scoping": {"function": "scope_queryset"},
257+
}
258+
259+
def scope_queryset(self, qs):
260+
"""Filter based on having view permission on the parent task of the group."""
261+
if not self.request.user.is_superuser:
262+
task_viewset = TaskViewSet()
263+
setattr(task_viewset, "request", self.request)
264+
setattr(task_viewset, "action", "group") # Set this to avoid extra prefetch queries
265+
tasks = (
266+
task_viewset.get_queryset()
267+
.filter(parent_task__isnull=True, task_group__isnull=False)
268+
.values_list("pk", flat=True)
269+
)
270+
qs = qs.filter(tasks__in=tasks)
271+
return qs
272+
252273

253274
class WorkerFilter(BaseFilterSet):
254275
online = filters.BooleanFilter(method="filter_online")

pulpcore/pytest_plugin.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,19 +1015,21 @@ def _wget_recursive_download_on_host(url, destination):
10151015

10161016
@pytest.fixture(scope="session")
10171017
def dispatch_task(pulpcore_bindings):
1018-
def _dispatch_task(*args, **kwargs):
1018+
def _dispatch_task(*args, task_group_id=None, **kwargs):
10191019
cid = pulpcore_bindings.client.default_headers.get("Correlation-ID") or str(uuid.uuid4())
10201020
username = pulpcore_bindings.client.configuration.username
10211021
commands = (
10221022
"from django_guid import set_guid; "
10231023
"from pulpcore.tasking.tasks import dispatch; "
1024+
"from pulpcore.app.models import TaskGroup; "
10241025
"from pulpcore.app.util import get_url, set_current_user; "
10251026
"from django.contrib.auth import get_user_model; "
10261027
"User = get_user_model(); "
10271028
f"user = User.objects.filter(username='{username}').first(); "
10281029
"set_current_user(user); "
10291030
f"set_guid({cid!r}); "
1030-
f"task = dispatch(*{args!r}, **{kwargs!r}); "
1031+
f"tg = {task_group_id!r} and TaskGroup.objects.filter(pk={task_group_id!r}).first(); "
1032+
f"task = dispatch(*{args!r}, task_group=tg, **{kwargs!r}); "
10311033
"print(get_url(task))"
10321034
)
10331035

@@ -1040,6 +1042,25 @@ def _dispatch_task(*args, **kwargs):
10401042
return _dispatch_task
10411043

10421044

1045+
@pytest.fixture(scope="session")
1046+
def dispatch_task_group(dispatch_task):
1047+
def _dispatch_task_group(task_name, *args, **kwargs):
1048+
commands = (
1049+
"from pulpcore.app.models import TaskGroup; "
1050+
"from pulpcore.app.util import get_url; "
1051+
"task_group = TaskGroup.objects.create(); "
1052+
"print(task_group.pk, get_url(task_group))"
1053+
)
1054+
process = subprocess.run(["pulpcore-manager", "shell", "-c", commands], capture_output=True)
1055+
assert process.returncode == 0
1056+
tgroup_id, tgroup_href = process.stdout.decode().strip().split()
1057+
1058+
dispatch_task(task_name, *args, task_group_id=tgroup_id, **kwargs)
1059+
return tgroup_href
1060+
1061+
return _dispatch_task_group
1062+
1063+
10431064
# GPG related fixtures
10441065

10451066

pulpcore/tests/functional/api/test_tasking.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,3 +367,34 @@ def test_emmiting_unblocked_task_telemetry(
367367
pulpcore_bindings.TasksApi.tasks_cancel(task_href, {"state": "canceled"})
368368
for task_href in resident_task_hrefs
369369
]
370+
371+
372+
@pytest.fixture
373+
def task_group(dispatch_task_group, monitor_task_group):
374+
"""Fixture containing a finished Task Group."""
375+
kwargs = {"inbetween": 0, "intervals": [0]}
376+
tgroup_href = dispatch_task_group("pulpcore.app.tasks.test.dummy_group_task", kwargs=kwargs)
377+
return monitor_task_group(tgroup_href)
378+
379+
380+
@pytest.mark.parallel
381+
def test_scope_task_groups(pulpcore_bindings, task_group, gen_user):
382+
"""Test that task groups can be queryset scoped by permission on Tasks."""
383+
for task in task_group.tasks:
384+
if task.name == "pulpcore.app.tasks.test.dummy_group_task":
385+
break
386+
387+
response = pulpcore_bindings.TaskGroupsApi.list()
388+
assert response.count > 0
389+
390+
with gen_user():
391+
response = pulpcore_bindings.TaskGroupsApi.list()
392+
assert response.count == 0
393+
394+
with gen_user(model_roles=["core.task_viewer"]):
395+
response = pulpcore_bindings.TaskGroupsApi.list()
396+
assert response.count > 0
397+
398+
with gen_user(object_roles=[("core.task_owner", task.pulp_href)]):
399+
response = pulpcore_bindings.TaskGroupsApi.list()
400+
assert response.count == 1

0 commit comments

Comments
 (0)