Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to new authZ model #262

Draft
wants to merge 3 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 9 additions & 27 deletions htsget_server/authz.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@ def is_authed(id_, request):
print("WARNING: TEST MODE, AUTHORIZATION IS DISABLED")
app.logger.warning("WARNING: TEST MODE, AUTHORIZATION IS DISABLED")
return 200 # no auth
if is_site_admin(request):
return 200
if "Authorization" in request.headers:
authed_datasets = get_authorized_datasets(request)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to get the list of authed_datasets here. I think we can simply use the id to get the dataset name and pass that with the other request info to is_permissible.

obj = database.get_drs_object(id_)
if obj is not None and 'datasets' in obj:
for dataset in obj["datasets"]:
if dataset in authed_datasets:
return 200
if id_:
obj = database.get_drs_object(id_)
if obj is not None and 'datasets' in obj:
for dataset in obj["datasets"]:
if (dataset in authed_datasets) and (authx.auth.is_permissible(request)):
return 200
else:
if (authx.auth.is_permissible(request)): return 200
else:
return 401
return 403
Expand All @@ -38,30 +39,11 @@ def is_testing(request):

def get_authorized_datasets(request):
try:
return authx.auth.get_opa_datasets(request, opa_url=AUTHZ['CANDIG_OPA_URL'], admin_secret=AUTHZ['CANDIG_OPA_SECRET'])
return authx.auth.get_readable_datasets(request, opa_url=AUTHZ['CANDIG_OPA_URL'], admin_secret=AUTHZ['CANDIG_OPA_SECRET'])
except Exception as e:
print(f"Couldn't authorize datasets: {type(e)} {str(e)}")
app.logger.warning(f"Couldn't authorize datasets: {type(e)} {str(e)}")
return []


def is_site_admin(request):
"""
Is the user associated with the token a site admin?
"""
if request.headers.get("Authorization") == f"Bearer {TEST_KEY}":
print("WARNING: TEST MODE, AUTHORIZATION IS DISABLED")
app.logger.warning("WARNING: TEST MODE, AUTHORIZATION IS DISABLED")
return True # no auth
if "Authorization" in request.headers:
try:
return authx.auth.is_site_admin(request, opa_url=AUTHZ['CANDIG_OPA_URL'], admin_secret=AUTHZ['CANDIG_OPA_SECRET'])
except Exception as e:
print(f"Couldn't authorize site_admin: {type(e)} {str(e)}")
app.logger.warning(f"Couldn't authorize site_admin: {type(e)} {str(e)}")
return False
return False


def get_s3_url(request, s3_endpoint=None, bucket=None, object_id=None, access_key=None, secret_key=None, region=None, public=False):
return authx.auth.get_s3_url(request, s3_endpoint=s3_endpoint, bucket=bucket, object_id=object_id, access_key=access_key, secret_key=secret_key, region=region, public=public)
1 change: 0 additions & 1 deletion htsget_server/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

ObjectDBBase = declarative_base()


## Variant search entities

## relationships
Expand Down
12 changes: 4 additions & 8 deletions htsget_server/drs_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,15 @@ def get_access_url(object_id, access_id):


def post_object():
if not authz.is_site_admin(request):
if not authz.is_authed(None, request):
return {"message": "User is not authorized to POST"}, 403
new_object = database.create_drs_object(connexion.request.json)
return new_object, 200


@app.route('/ga4gh/drs/v1/objects/<path:object_id>')
def delete_object(object_id):
if not authz.is_site_admin(request):
if not authz.is_authed(object_id, request):
return {"message": "User is not authorized to POST"}, 403
try:
new_object = database.delete_drs_object(escape(object_id))
Expand All @@ -110,16 +110,14 @@ def list_datasets():
if datasets is None:
return [], 404
try:
if authz.is_site_admin(request):
return list(map(lambda x: x['id'], datasets)), 200
authorized_datasets = authz.get_authorized_datasets(request)
return list(set(map(lambda x: x['id'], datasets)).intersection(set(authorized_datasets))), 200
except Exception as e:
return [], 500


def post_dataset():
if not authz.is_site_admin(request):
if not authz.is_authed(None, request):
return {"message": "User is not authorized to POST"}, 403
new_dataset = database.create_dataset(connexion.request.json)
return new_dataset, 200
Expand All @@ -129,16 +127,14 @@ def get_dataset(dataset_id):
new_dataset = database.get_dataset(dataset_id)
if new_dataset is None:
return {"message": "No matching dataset found"}, 404
if authz.is_site_admin(request):
return new_dataset, 200
authorized_datasets = authz.get_authorized_datasets(request)
if new_dataset["id"] in authorized_datasets:
return new_dataset, 200
return {"message": f"Not authorized to access dataset {dataset_id}"}, 403


def delete_dataset(dataset_id):
if not authz.is_site_admin(request):
if not authz.is_authed(None, request):
return {"message": "User is not authorized to POST"}, 403
try:
new_dataset = database.delete_dataset(dataset_id)
Expand Down
2 changes: 1 addition & 1 deletion htsget_server/htsget_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def get_variants_data(id_, reference_name=None, format_="VCF", start=None, end=N

@app.route('/variants/<path:id_>/index')
def index_variants(id_=None, force=False, genome='hg38', genomic_id=None):
if not authz.is_site_admin(request):
if not authz.is_authed(id_, request):
return {"message": "User is not authorized to index variants"}, 403
if id_ is not None:
params = {"id": id_, "reference_genome": genome}
Expand Down
1 change: 1 addition & 0 deletions htsget_server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from flask_cors import CORS
import connexion
import logging
from sys import stdout
from config import PORT, DEBUG_MODE

# Create the application instance
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ pysam==0.20.0
sqlalchemy==1.4.44
connexion==2.14.1
MarkupSafe==2.1.1
candigv2-authx@git+https://github.com/CanDIG/candigv2-authx.git@v1.0.0
candigv2-authx@git+https://github.com/CanDIG/candigv2-authx.git@new-auth-model
pytest==7.2.0
uwsgi==2.0.21