Skip to content

Commit ad46d6a

Browse files
author
Robin VAN DE MERGHEL
committed
feat: Better policy, to support also jobs
1 parent 97fe8c8 commit ad46d6a

2 files changed

Lines changed: 56 additions & 24 deletions

File tree

diracx-routers/src/diracx/routers/pilots/access_policies.py

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from fastapi import Depends, HTTPException, status
88

99
from diracx.core.properties import SERVICE_ADMINISTRATOR
10+
from diracx.db.sql.job.db import JobDB
1011
from diracx.db.sql.pilots.db import PilotAgentsDB
1112
from diracx.logic.pilots.query import get_pilots_by_stamp
1213
from diracx.routers.access_policies import BaseAccessPolicy
@@ -35,26 +36,50 @@ async def policy(
3536
action: ActionType | None = None,
3637
pilot_db: PilotAgentsDB | None = None,
3738
pilot_stamps: list[str] | None = None,
39+
job_db: JobDB | None = None,
40+
job_ids: list[int] | None = None,
3841
):
3942
assert action, "action is a mandatory parameter"
4043

4144
# Users can query
4245
# NOTE: Add into queries a VO constraint
43-
if action == ActionType.READ_PILOT_FIELDS:
44-
return
46+
# To manage pilots, user have to be an admin
47+
if (
48+
action == ActionType.MANAGE_PILOTS
49+
and SERVICE_ADMINISTRATOR not in user_info.properties
50+
):
51+
raise HTTPException(
52+
status_code=status.HTTP_403_FORBIDDEN,
53+
detail="You don't have the permission to manage pilots.",
54+
)
4555

46-
# If we want to modify pilots, we allow only admins
47-
# TODO: See if we add other types of admins
48-
if SERVICE_ADMINISTRATOR in user_info.properties:
49-
# If we don't provide pilot_db and pilot_stamps, we accept directly
50-
# This is for example when we submit pilots, we use the user VO, so no need to verify
51-
if not (pilot_db and pilot_stamps):
52-
return
56+
#
57+
# Additional checks if job_ids or pilot_stamps are provided
58+
#
5359

54-
# Else, check its VO
55-
assert pilot_db, "PilotDB is needed to determine pilot VO."
56-
assert pilot_stamps, "PilotStamps are needed to determine pilot VO."
60+
# First, if job_ids are provided, we check who is the owner
61+
if job_db and job_ids:
62+
job_owners = await job_db.summary(
63+
["Owner", "VO"],
64+
[{"parameter": "JobID", "operator": "in", "values": job_ids}],
65+
)
66+
67+
expected_owner = {
68+
"Owner": user_info.preferred_username,
69+
"VO": user_info.vo,
70+
"count": len(set(job_ids)),
71+
}
72+
# All the jobs belong to the user doing the query
73+
# and all of them are present
74+
if not job_owners == [expected_owner]:
75+
raise HTTPException(
76+
status_code=status.HTTP_403_FORBIDDEN,
77+
detail="You don't have the rights to modify a pilot.",
78+
)
5779

80+
# This is for example when we submit pilots, we use the user VO, so no need to verify
81+
if pilot_db and pilot_stamps:
82+
# Else, check its VO
5883
pilots = await get_pilots_by_stamp(
5984
pilot_db=pilot_db,
6085
pilot_stamps=pilot_stamps,
@@ -74,13 +99,6 @@ async def policy(
7499
detail="You don't have access to all pilots.",
75100
)
76101

77-
return
78-
79-
raise HTTPException(
80-
status_code=status.HTTP_403_FORBIDDEN,
81-
detail="You don't have the rights to modify a pilot.",
82-
)
83-
84102

85103
CheckPilotManagementPolicyCallable = Annotated[
86104
Callable, Depends(PilotManagementAccessPolicy.check)

diracx-routers/src/diracx/routers/pilots/management.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from diracx.logic.pilots.query import get_pilot_ids_by_job_id
2929
from diracx.routers.utils.users import AuthorizedUserInfo, verify_dirac_access_token
3030

31-
from ..dependencies import PilotAgentsDB
31+
from ..dependencies import JobDB, PilotAgentsDB
3232
from ..fastapi_classes import DiracxRouter
3333
from .access_policies import (
3434
ActionType,
@@ -203,6 +203,7 @@ async def update_pilot_fields(
203203
@router.get("/jobs")
204204
async def get_pilot_jobs(
205205
pilot_db: PilotAgentsDB,
206+
job_db: JobDB,
206207
check_permissions: CheckPilotManagementPolicyCallable,
207208
pilot_stamp: Annotated[
208209
str | None, Query(description="The stamp of the pilot.")
@@ -211,14 +212,23 @@ async def get_pilot_jobs(
211212
) -> list[int]:
212213
"""Endpoint only for admins, to get jobs of a pilot."""
213214
if pilot_stamp:
214-
await check_permissions(action=ActionType.READ_PILOT_FIELDS)
215+
# Check VO
216+
await check_permissions(
217+
action=ActionType.READ_PILOT_FIELDS,
218+
pilot_db=pilot_db,
219+
pilot_stamps=[pilot_stamp],
220+
)
215221

216222
return await get_pilot_jobs_ids_by_stamp(
217223
pilot_db=pilot_db,
218224
pilot_stamp=pilot_stamp,
219225
)
220226
elif job_id:
221-
# FIXME: Add some policy, verify that it's the user's job?
227+
# Check job owner
228+
await check_permissions(
229+
action=ActionType.READ_PILOT_FIELDS, job_db=job_db, job_ids=[job_id]
230+
)
231+
222232
return await get_pilot_ids_by_job_id(pilot_db=pilot_db, job_id=job_id)
223233

224234
raise HTTPException(
@@ -230,6 +240,7 @@ async def get_pilot_jobs(
230240
@router.patch("/jobs", status_code=HTTPStatus.NO_CONTENT)
231241
async def add_jobs_to_pilot(
232242
pilot_db: PilotAgentsDB,
243+
job_db: JobDB,
233244
pilot_stamp: Annotated[str, Body(description="The stamp of the pilot.")],
234245
job_ids: Annotated[
235246
list[int], Body(description="The jobs we want to add to the pilot.")
@@ -238,9 +249,12 @@ async def add_jobs_to_pilot(
238249
):
239250
"""Endpoint only for admins, to associate a pilot with a job."""
240251
await check_permissions(
241-
action=ActionType.MANAGE_PILOTS, pilot_db=pilot_db, pilot_stamps=[pilot_stamp]
252+
action=ActionType.MANAGE_PILOTS,
253+
pilot_db=pilot_db,
254+
pilot_stamps=[pilot_stamp],
255+
job_db=job_db,
256+
job_ids=job_ids,
242257
)
243-
# FIXME: Also verify job_ids
244258

245259
try:
246260
await add_jobs_to_pilot_bl(

0 commit comments

Comments
 (0)