diff --git a/pro_tes/api/proTes_policy.conf b/pro_tes/api/proTes_policy.conf new file mode 100644 index 0000000..6cbfff2 --- /dev/null +++ b/pro_tes/api/proTes_policy.conf @@ -0,0 +1,31 @@ +# Request Definition +# This section defines the structure of incoming access requests, including the subject (user), object (resource), and action. +[request_definition] +r = sub, obj, act + +# Policy Definition +# This section specifies the structure of policies, detailing which roles have access to which resources and actions. +[policy_definition] +p = sub, obj, act + +# Role Definition +# 'g' defines general group membership, while 'g2' is used for resource-specific roles like owner, maintainer, and viewer. +[role_definition] +g = _, _ +g2 = _, _, _ # for resource-specific roles + +# Policy Effect +# Determines the policy effect, allowing access if any policy matches. +[policy_effect] +e = some(where (p.eft == allow)) + +# Matchers +# This section contains the custom logic for access control, specifying how roles and actions map to permissions. +# Check if the user is a group member and is attempting to create a new resource. +m = g(r.sub, "group_member") && r.obj == "/tasks" && r.act == "POST" || + # Allow full access to the resource for its owner. + g2(r.sub, "owner", r.obj) || + # Allow maintainers to view and cancel tasks but not modify access permissions. + g2(r.sub, "maintainer", r.obj) && (r.act == "GET" || r.act == "POST:/tasks/{task-id}:cancel") || + # Allow viewers to only view tasks and perform no other actions. + g2(r.sub, "viewer", r.obj) && r.act == "GET" diff --git a/pro_tes/config.yaml b/pro_tes/config.yaml index 78ea53c..2553012 100644 --- a/pro_tes/config.yaml +++ b/pro_tes/config.yaml @@ -17,7 +17,10 @@ server: # Cf. https://foca.readthedocs.io/en/latest/modules/foca.models.html#foca.models.config.SecurityConfig security: auth: + required: True add_key_to_claims: True + claim_identity: sub + claim_issuer: iss algorithms: - RS256 allow_expired: False @@ -26,6 +29,12 @@ security: - userinfo - public_key validation_checks: any + access_control: + db_name: proTesAccess + collection_name: permissions + model: proTES/pro_tes/api/proTes_policy.conf + owner_headers: ['user_id'] + user_headers: ['user_id'] # Database configuration # Cf. https://foca.readthedocs.io/en/latest/modules/foca.models.html#foca.models.config.DBConfig @@ -62,7 +71,6 @@ api: - bearerAuth: [] add_security_fields: x-bearerInfoFunc: foca.security.auth.validate_token - disable_auth: True connexion: strict_validation: True # current specs have inconsistency, therefore disabling response validation diff --git a/pro_tes/ga4gh/tes/server.py b/pro_tes/ga4gh/tes/server.py index 008551a..408a903 100644 --- a/pro_tes/ga4gh/tes/server.py +++ b/pro_tes/ga4gh/tes/server.py @@ -4,6 +4,10 @@ from connexion import request # type: ignore from foca.utils.logging import log_traffic # type: ignore +from foca.security.access_control.register_access_control import ( + check_permissions +) # type: ignore + from pro_tes.ga4gh.tes.service_info import ServiceInfo from pro_tes.ga4gh.tes.task_runs import TaskRuns @@ -33,6 +37,7 @@ def CancelTask( # POST /tasks @log_traffic +@check_permissions def CreateTask(*args, **kwargs) -> dict: """Create task. diff --git a/requirements.txt b/requirements.txt index 983ac80..62b37cd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,3 +10,4 @@ types-PyYAML>=6.0.12 types-requests>=2.28.5 types-simplejson>=3.17.7 types-urllib3>=1.26.17 +pymongo==4.7