From 67a0f91dc69ca7cafbe0c9d8d667b3a590e52ac7 Mon Sep 17 00:00:00 2001 From: Rohan Weeden Date: Thu, 2 Jan 2025 15:58:45 -0900 Subject: [PATCH] Refactor EDL call to use EdlClient from rain-api-core --- requirements/requirements.txt | 2 +- thin_egress_app/app.py | 114 +++++++++++----------------------- 2 files changed, 36 insertions(+), 80 deletions(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index ab8a9f7f..3499e4d1 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -48,7 +48,7 @@ pyyaml==6.0.2 # via # chalice # rain-api-core -rain-api-core @ git+https://github.com/asfadmin/rain-api-core.git@f5186c00c8e9d576f710eac62e6ca1e51516d6d7 +rain-api-core @ git+https://github.com/asfadmin/rain-api-core.git@rew/pr-3242-refactor-edl-client # via -r requirements/requirements.in readchar==4.2.1 # via inquirer diff --git a/thin_egress_app/app.py b/thin_egress_app/app.py index fd9bf7c1..eb1b3bdb 100644 --- a/thin_egress_app/app.py +++ b/thin_egress_app/app.py @@ -6,9 +6,7 @@ import urllib.request from functools import wraps from typing import Optional -from urllib import request -from urllib.error import HTTPError -from urllib.parse import quote_plus, urlencode, urlparse +from urllib.parse import quote_plus, urlparse import boto3 import cachetools @@ -37,6 +35,7 @@ def inject(obj): retrieve_secret, ) from rain_api_core.bucket_map import BucketMap +from rain_api_core.edl import EdlClient, EdlException, EulaException from rain_api_core.egress_util import get_bucket_name_prefix, get_presigned_url from rain_api_core.general_util import ( duration, @@ -167,11 +166,6 @@ class TeaException(Exception): """ base exception for TEA """ -class EulaException(TeaException): - def __init__(self, payload: dict): - self.payload = payload - - class RequestAuthorizer: def __init__(self): self._response = None @@ -222,16 +216,23 @@ def _handle_auth_bearer_header(self, token) -> Optional[UserProfile]: """ try: user_id = get_user_from_token(token) + log_context(user_id=user_id) + + user_profile = get_new_token_and_profile( + user_id, + True, + aux_headers=get_aux_request_headers(), + ) except EulaException as e: log.warning("user has not accepted EULA") # TODO(reweeden): changing the response based on user agent looks like a really bad idea... if check_for_browser(app.current_request.headers): template_vars = { - "title": e.payload["error_description"], + "title": e.msg["error_description"], "status_code": 403, "contentstring": ( - f'Could not fetch data because "{e.payload["error_description"]}". Please accept EULA here: ' - f'{e.payload["resolution_url"]} and try again.' + f'Could not fetch data because "{e.msg["error_description"]}". Please accept EULA here: ' + f'{e.msg["resolution_url"]} and try again.' ), "requestid": get_request_id(), } @@ -240,16 +241,13 @@ def _handle_auth_bearer_header(self, token) -> Optional[UserProfile]: else: self._response = Response(body=e.payload, status_code=403, headers={}) return None + except EdlException: + user_profile = None - if user_id: - log_context(user_id=user_id) - aux_headers = get_aux_request_headers() - user_profile = get_new_token_and_profile(user_id, True, aux_headers=aux_headers) - if user_profile: - return user_profile + if user_profile is None: + self._response = do_auth_and_return(app.current_request.context) - self._response = do_auth_and_return(app.current_request.context) - return None + return user_profile def get_error_response(self) -> Optional[Response]: """Get the response to return if the user was not authenticated. This @@ -315,76 +313,34 @@ def get_user_from_token(token): "token": token } - url = "{}/oauth/tokens/user?{}".format( - os.getenv("AUTH_BASE_URL", "https://urs.earthdata.nasa.gov"), - urlencode(params) - ) - authval = f"Basic {urs_creds['UrsAuth']}" headers = {"Authorization": authval} # Tack on auxillary headers headers.update(get_aux_request_headers()) - log.debug("headers: %s, params: %s", headers, params) - _time = time.time() - - req = request.Request(url, headers=headers, method="POST") + client = EdlClient() try: - response = request.urlopen(req) - except HTTPError as e: - response = e - log.debug("%s", e) - - payload = response.read() - log.info(return_timing_object(service="EDL", endpoint=url, method="POST", duration=duration(_time))) - - try: - msg = json.loads(payload) - except json.JSONDecodeError: - log.error("could not get json message from payload: %s", payload) - msg = {} - - log.debug("raw payload: %s", payload) - log.debug("json loads: %s", msg) - log.debug("code: %s", response.code) - - if response.code == 200: - try: - return msg["uid"] - except KeyError as e: - log.error( - "Problem with return from URS: e: %s, url: %s, params: %s, response payload: %s", - e, - url, - params, - payload, - ) - return None - elif response.code == 403: - if "error_description" in msg and "eula" in msg["error_description"].lower(): - # sample json in this case: - # `{"status_code": 403, "error_description": "EULA Acceptance Failure", - # "resolution_url": "http://uat.urs.earthdata.nasa.gov/approve_app?client_id=LqWhtVpLmwaD4VqHeoN7ww"}` - log.warning("user needs to sign the EULA") - raise EulaException(msg) - # Probably an expired token if here - log.warning("403 error from URS: %s", msg) - else: - if "error" in msg: - errtxt = msg["error"] - else: - errtxt = "" - if "error_description" in msg: - errtxt = errtxt + " " + msg["error_description"] + msg = client.request( + "POST", + "/oauth/tokens/user", + params=params, + headers=headers, + ) + user_id = msg.get("uid") + if user_id is None: + log.error("Problem with return from URS: msg: %s", msg) + return user_id + except EulaException: + raise + except EdlException as e: log.error( - "Error getting URS userid from token: %s with code %s", - errtxt, - response.code, + "Error getting URS userid from token: %s, response: %s", + e.inner, + e.payload, ) - log.debug("url: %s, params: %s", url, params) - return None + raise @with_trace()