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

HARMONY-1938: Update code to omit Authorization header when redirected to a presigned S3 URL #55

Merged
merged 1 commit into from
Dec 10, 2024
Merged
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
39 changes: 16 additions & 23 deletions harmony_service_lib/earthdata.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
from urllib.parse import urlparse, parse_qs
from requests.auth import AuthBase
from requests import Session


def _is_presigned_url(url: str) -> bool:
"""Check if the URL is an AWS presigned URL. For AWS presigned URLs we do not
want to pass in an authorization header."""
query_params = parse_qs(urlparse(url).query)
return "X-Amz-Algorithm" in query_params or "Signature" in query_params


class EarthdataSession(Session):
"""Session which ensures the Authorization header is sent to correct
servers.
Expand All @@ -15,39 +23,24 @@ class EarthdataSession(Session):
redirect requests.
"""
def rebuild_auth(self, prepared_request, response):
# If not configured with an EarthdataAuth instance, defer to
# default behavior
# If not configured with an EarthdataAuth instance, defer to default behavior
if not self.auth:
return super().rebuild_auth(prepared_request, response)

self.auth(prepared_request)


class EarthdataAuth(AuthBase):
"""Custom Earthdata Auth provider to add EDL Authorization headers to
requests when required for token sharing and federated
authentication.

When instantiated with an EDL application's credentials and a
user's access token, the resulting HTTP Authorization header will
include the properly-encoded app credentials as a Basic auth
header, and the user's access token as a Bearer auth header.
"""Custom Earthdata Auth provider to add EDL Authorization headers."""

"""
def __init__(self, user_access_token: str):
"""Instantiate the Earthdata Auth provider.

Parameters
----------
user_access_token:
The EDL-issued token for the user making the request.
"""
self.authorization_header = f'Bearer {user_access_token}'
self.authorization_header = f"Bearer {user_access_token}"

def __call__(self, r):
"""The EarthdataAuth is a callable which adds Authorization headers
when handling a request for sites backed by Earthdata Login.
"""Add Authorization headers unless the request is to an AWS presigned URL."""
if _is_presigned_url(r.url):
r.headers.pop('Authorization', None)
else:
r.headers["Authorization"] = self.authorization_header

"""
r.headers['Authorization'] = self.authorization_header
return r
16 changes: 15 additions & 1 deletion tests/test_earthdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,27 @@ def test_authdata_auth_creates_correct_header(faker):
assert token in request.headers['Authorization']


def test_earthdata_auth_given_edl_url_adds_auth_header(earthdata_auth):
def test_earthdata_auth_adds_auth_header_(earthdata_auth):
request = FakeRequest()

earthdata_auth(request)

assert 'Authorization' in request.headers

def test_earthdata_auth_removes_auth_header_when_X_Amz_Algorithm_is_set(earthdata_auth):
request = FakeRequest(url='https://presigned.s3.url.com?X-Amz-Algorithm=foo')

earthdata_auth(request)

assert 'Authorization' not in request.headers

def test_earthdata_auth_removes_auth_header_when_signature_is_set(earthdata_auth):
request = FakeRequest(url='https://presigned.s3.url.com?Signature=bar')

earthdata_auth(request)

assert 'Authorization' not in request.headers

def test_earthdata_session_given_no_auth_delegates_to_super(monkeypatch):
called = False

Expand Down
Loading