diff --git a/README.md b/README.md index 03ffa7f65ad27c8d4789a7b99f6a8e13d0113114..1f37d4a8a16f9cee4caacba5ed4e57f21ea8c045 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,6 @@ ESAP API Gateway is a 'backend' web application written in Django. It provides a range of services that can be accessed through a REST API. ## Documentation -* backend (API): https://git.astron.nl/astron-sdc/esap-api-gateway/-/wikis/ESAP-API-gateway +* backend (API Gateway): https://git.astron.nl/astron-sdc/esap-api-gateway/-/wikis/ESAP-API-gateway-Overview * frontend (GUI): https://git.astron.nl/astron-sdc/esap-gui/-/wikis/ESAP-GUI diff --git a/esap/esap/configuration/esap_rucio.py b/esap/esap/configuration/esap_rucio.py index 0ef3c25c2dc6d9a5d721a1c03fb2dbe769baf120..84f9482b372ffdc882eace6e55eb700ef8979085 100644 --- a/esap/esap/configuration/esap_rucio.py +++ b/esap/esap/configuration/esap_rucio.py @@ -1,19 +1,15 @@ import requests import urllib.parse import json +from django.conf import settings -rucio_url = "https://escape-rucio.cern.ch" +ID_TOKEN_KEY = "oidc_id_token" +ACCESS_TOKEN_KEY = "oidc_access_token" -AUTH_PORT = 32301 -STANDARD_PORT = 32300 - -RUCIO_AUTH_TOKEN = "<REDACTED>" - - -def validate(): - url = urllib.parse.urljoin(f"{rucio_url}:{AUTH_PORT}", "auth/validate") +def validate(token): + url = urllib.parse.urljoin(f"{settings.RUCIO_HOST}:{settings.RUCIO_AUTH_PORT}", "auth/validate") response = requests.get( - url, headers={"X-Rucio-Auth-Token": RUCIO_AUTH_TOKEN}, verify=False + url, headers={"X-Rucio-Auth-Token": token}, verify=False ) if response.ok: return True @@ -21,13 +17,15 @@ def validate(): return False -def get_scope_names(): - # try: - validated = validate() +def get_scope_names(session): + token = session.get(ACCESS_TOKEN_KEY, None) + if token is None: + return [f"Not logged in {session}, {session.keys()}."] + validated = validate(token) if validated: - url = urllib.parse.urljoin(f"{rucio_url}:{STANDARD_PORT}", "scopes") + url = urllib.parse.urljoin(f"{settings.RUCIO_HOST}:{settings.RUCIO_PORT}", "scopes") response = requests.get( - url + "/", headers={"X-Rucio-Auth-Token": RUCIO_AUTH_TOKEN}, verify=False + url + "/", headers={"X-Rucio-Auth-Token": token}, verify=False ) if response.ok: return json.loads(response.content) @@ -36,41 +34,60 @@ def get_scope_names(): "validated but failed query" ] # , val_response.status_code, val_response.reason] else: - # , val_response.status_code, val_response.reason] - return ["not validated"] + return [f"not validated, {len(token)}, {type(token)}, '{token}'."] # , val_response.status_code, val_response.reason] # except Exception as e: # return ["Failed", "Authentication", e] -title = "Rucio" -logo = "http://rucio.cern.ch/images/wide_logo2.png" +class Config: + title = "Rucio" + logo = "http://rucio.cern.ch/images/wide_logo2.png" + + # the url location of the frontend application, + # this makes it possible to install multiple instances in different directories on the webserver + # that all have their own urls like 'http://esap.astron.nl/esap-gui-dev/queries' + frontend_basename = "esap-rucio" + + # definition of the navigation bar + nav1 = {"title": "Archives", "route": "/archives"} + nav2 = {"title": "Query", "route": "/query"} + navbar = [nav1, nav2] + + ui_schema = {"catalog": {"ui:widget": "hidden"}} + + def __init__(self, session): + self.session=session + self.__query_schema = self.gen_query_schema() -# definition of the query -query_schema = { - "name": "rucio", - "title": "Rucio Query", - "type": "object", - "properties": { - "scope": { - "type": "string", - "title": "Scope", - "enum": get_scope_names(), - "enumNames": get_scope_names(), - }, - "resource_category": { - "type": "string", - "title": "Category", - "enum": ["files", "dids", "replicas"], - "enumNames": ["Files", "DIDs", "Replicas"], - "default": "dids", - }, - "catalog": { - "type": "string", - "enum": ["esap_rucio_entities"], - "enumNames": ["esap_rucio_entities"], - "default": "esap_rucio_entities", - }, - }, -} + @property + def query_schema(self): + return self.__query_schema -ui_schema = {"catalog": {"ui:widget": "hidden"}} + def gen_query_schema(self): + scope_names = get_scope_names(self.session) + return { + "name": "rucio", + "title": "Rucio Query", + "type": "object", + "properties": { + "scope": { + "type": "string", + "title": "Scope", + "enum": scope_names, + "enumNames": scope_names, + }, + "resource_category": { + "type": "string", + "title": "Category", + "enum": ["files", "dids", "replicas"], + "enumNames": ["Files", "DIDs", "Replicas"], + "default": "dids", + }, + "catalog": { + "type": "string", + "enum": ["esap_rucio_entities"], + "enumNames": ["esap_rucio_entities"], + "default": "esap_rucio_entities", + }, + }, + } diff --git a/esap/esap/settings/base.py b/esap/esap/settings/base.py index 343f4132af91c164b5d0e4104294199f5a457403..57671bccde5dadc01c96f920027ce3f66e60d660 100644 --- a/esap/esap/settings/base.py +++ b/esap/esap/settings/base.py @@ -216,6 +216,8 @@ AUTHENTICATION_BACKENDS = ( ) OIDC_DRF_AUTH_BACKEND = 'mozilla_django_oidc.auth.OIDCAuthenticationBackend' +# OIDC environment variables + OIDC_RP_CLIENT_ID = os.environ['OIDC_RP_CLIENT_ID'] OIDC_RP_CLIENT_SECRET = os.environ['OIDC_RP_CLIENT_SECRET'] OIDC_RP_SIGN_ALGO = "RS256" @@ -231,6 +233,13 @@ LOGIN_REDIRECT_URL = os.environ['LOGIN_REDIRECT_URL'] LOGOUT_REDIRECT_URL = os.environ['LOGOUT_REDIRECT_URL'] LOGIN_REDIRECT_URL_FAILURE = os.environ['LOGIN_REDIRECT_URL_FAILURE'] +# Rucio environment variables + +RUCIO_AUTH_TOKEN = os.environ['RUCIO_AUTH_TOKEN'] +RUCIO_HOST = os.environ['RUCIO_HOST'] +RUCIO_PORT = os.environ['RUCIO_PORT'] +RUCIO_AUTH_PORT = os.environ['RUCIO_AUTH_PORT'] + # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/2.0/howto/static-files/ @@ -238,6 +247,6 @@ STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'static') # configuration settings that can be requested through the REST API -VERSION = "ESAP-API version 23 march 2021" +VERSION = "ESAP-API version 29 april 2021" CONFIGURATION_DIR = os.path.join(BASE_DIR, 'configuration') CONFIGURATION_FILE = 'esap_default' diff --git a/esap/query/api/configuration.py b/esap/query/api/configuration.py index 7010d63132cbb0e4c80e13c473342e05a755befb..bc63b811b197dc465d80666499f86413d3c9ae36 100644 --- a/esap/query/api/configuration.py +++ b/esap/query/api/configuration.py @@ -20,7 +20,7 @@ def get_datasets_disabled(): return my_config.datasets_disabled # return expanded configuration -def get_configuration(name=None): +def get_configuration(name=None, session=None): result = {} result['version'] = settings.VERSION @@ -34,6 +34,12 @@ def get_configuration(name=None): else: my_config = importlib.import_module(settings.CONFIGURATION_FILE) + # More sophisticated config files can embed the config in a class called Config + try: + my_config = my_config.Config(session) + except AttributeError as e: + pass + except Exception as error: return {"configuration error in ": name+ ".py : " + str(error)} diff --git a/esap/query/api/services/rucio.py b/esap/query/api/services/rucio.py index d7e03432b7b1faeb86421177acd91a8648f529e6..bddd8bfb9e82ac31dbca67777d9a32c8920a38ed 100644 --- a/esap/query/api/services/rucio.py +++ b/esap/query/api/services/rucio.py @@ -3,7 +3,7 @@ Date created: 2020-10-15 Description: Rucio Service Connector for ESAP. """ - +from django.conf import settings from rest_framework import serializers from .query_base import query_base import requests @@ -15,11 +15,6 @@ logger = logging.getLogger(__name__) AMP_REPLACEMENT = "_and_" -# The request header -RUCIO_HOST = "https://escape-rucio.cern.ch:32300" -RUCIO_PORT = 32300 -RUCIO_AUTH_TOKEN = "<REDACTED>" - URLPATTERNS = dict( scope="{host}/scopes/", dids="{host}/dids/{scope}/", @@ -87,12 +82,12 @@ class rucio_connector(query_base): """ use Rucio REST API to query the data lake """ query_info = query["query_info"] url = query_info["url_pattern"].format( - host=f"{self.url}:{RUCIO_PORT}", **query_info["url_params"] + host=f"{self.url}:{settings.RUCIO_PORT}", **query_info["url_params"] ) response = requests.get( url, query_info["where"], - headers={"X-Rucio-Auth-Token": RUCIO_AUTH_TOKEN}, + headers={"X-Rucio-Auth-Token": settings.RUCIO_AUTH_TOKEN}, verify=False, ) results = [] diff --git a/esap/query/api/views/common_views.py b/esap/query/api/views/common_views.py index e103955cbb8aa2a39ba3900995bfdbcd1235ff68..a8e32ea5fda26a1e200131f3a4598649092a31bf 100644 --- a/esap/query/api/views/common_views.py +++ b/esap/query/api/views/common_views.py @@ -264,9 +264,9 @@ def ConfigurationView(request): pass try: - config_from_settings = configuration.get_configuration(name) + config_from_settings = configuration.get_configuration(name, request.session) except Exception as error: - config_from_settings = "ERROR in configuration: "+str(error) + config_from_settings = "ERROR in configuration: "+str(error) + " session => " + str(request.session) return JsonResponse({'configuration': config_from_settings}) diff --git a/esap/query/api/views/query_views.py b/esap/query/api/views/query_views.py index 389833265be3f292cbc922a756aca4211a0a387a..91ecba4a3c3258678f41467a35a8c80ffdf0d07e 100644 --- a/esap/query/api/views/query_views.py +++ b/esap/query/api/views/query_views.py @@ -361,7 +361,7 @@ class GetTablesFields(generics.ListAPIView): class GetSkyCoordinates(generics.ListAPIView): """ Retrieve a list of fields from the access_url - examples: /esap-api/query/get-fields?dataset_uri=vo_reg&access_url=https://vo.astron.nl/tap + examples: /esap-api/query/get-sky-coordinates/?target_name=M31 """ model = DataSet diff --git a/esap/query/apps.py b/esap/query/apps.py index dad42f688d6df90a209faffafb6e8b2179a1f22c..d7bb3aec65dda20ea36a27501911653caa7f6bee 100644 --- a/esap/query/apps.py +++ b/esap/query/apps.py @@ -3,11 +3,4 @@ from django.apps import AppConfig class MyAppConfig(AppConfig): name = 'query' -# experiment to start a samp client on startup... (warning, blocking) -# def ready(self): -# try: -# print('importing samp') -# from .api.services import samp -# #samp() -# except: -# pass \ No newline at end of file + diff --git a/esap/query/templates/query/index.html b/esap/query/templates/query/index.html index 37960e1c52c22706399e681ce3c565175bca031a..7d9c82ef34eea7f63ef4b237627ca277e18b13c6 100644 --- a/esap/query/templates/query/index.html +++ b/esap/query/templates/query/index.html @@ -70,7 +70,7 @@ </div> -<p class="footer" small>ASTRON - version 26 mar 2021 - 08:00</p> +<p class="footer" small>ASTRON - version 29 april 2021 - 15:00</p> {% endblock %}