Skip to content

Commit

Permalink
Merge pull request #807 from jeffersonwhite/api-request-uuid-support
Browse files Browse the repository at this point in the history
Add support for A-api-request-uuid query parameter
  • Loading branch information
mattp0 authored Apr 20, 2024
2 parents 0d07f4d + 3a44423 commit 4463527
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 18 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Python
*.pyc
/venv
.venv

# IDE
.idea
Expand Down
1 change: 1 addition & 0 deletions Makefile.config.example
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ LOG_TYPE := flat
# For NGAP Deployments #
########################
# In an NGAP environment you must uncomment the following line or the deployment will fail
# This has been deprecated in NGAP and is no longer necessary
# PERMISSION_BOUNDARY_NAME := NGAPShRoleBoundary

PRIVATE_VPC :=
Expand Down
1 change: 1 addition & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ container path:
file:/var/deps/rain-api-core
```
*NOTE: This is a generated file and you should NOT be committing these changes*

3. Add any source files of that dependency to the `REQUIREMENTS_DEPS` in your `Makefile.config`:
```makefile
REQUIREMENTS_DEPS := $(shell find /host/path/to/rain-api-core/rain_api_core/ -name '*.py')
Expand Down
2 changes: 1 addition & 1 deletion requirements/requirements.in
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cachetools
cfnresponse
chalice
git+https://github.com/asfadmin/rain-api-core.git@318aac226c92cf6f60cc8821d6d94669485972c6
git+https://github.com/asfadmin/rain-api-core.git@a9a00d126878f56213af972f6fb5bf6bb1490909
netaddr
2 changes: 1 addition & 1 deletion requirements/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ pyyaml==6.0.1
# via
# chalice
# rain-api-core
rain-api-core @ git+https://github.com/asfadmin/rain-api-core.git@318aac226c92cf6f60cc8821d6d94669485972c6
rain-api-core @ git+https://github.com/asfadmin/rain-api-core.git@a9a00d126878f56213af972f6fb5bf6bb1490909
# via -r requirements/requirements.in
readchar==4.0.5
# via inquirer
Expand Down
66 changes: 53 additions & 13 deletions tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ def test_try_download_from_bucket(
client.get_bucket_location.return_value = {"LocationConstraint": "us-east-1"}
client.head_object.return_value = {"ContentLength": 2048}

response = app.try_download_from_bucket("somebucket", "somefile", user_profile, {})
response = app.try_download_from_bucket("somebucket", "somefile", user_profile, {}, api_request_uuid=None)
client.head_object.assert_called_once()
assert response.body == ""
assert response.status_code == 303
Expand All @@ -606,7 +606,7 @@ def test_try_download_from_bucket(
monkeypatch.setenv("AWS_DEFAULT_REGION", "us-west-2")
client.head_object.reset_mock()

response = app.try_download_from_bucket("somebucket", "somefile", user_profile, "not a dict")
response = app.try_download_from_bucket("somebucket", "somefile", user_profile, "not a dict", api_request_uuid=None)
client.head_object.assert_not_called()
assert response.body == ""
assert response.status_code == 303
Expand Down Expand Up @@ -635,7 +635,7 @@ def test_try_download_from_bucket_client_error(
mock_get_role_creds.return_value = (mock.Mock(), 1000)
mock_get_role_session().client.side_effect = ClientError({}, "bar")

app.try_download_from_bucket("somebucket", "somefile", user_profile, {})
app.try_download_from_bucket("somebucket", "somefile", user_profile, {}, None)
mock_make_html_response.assert_called_once_with(
{
"contentstring": "There was a problem accessing download data.",
Expand Down Expand Up @@ -672,7 +672,7 @@ def test_try_download_from_bucket_not_found(
"bar"
)

app.try_download_from_bucket("somebucket", "somefile", user_profile, {})
app.try_download_from_bucket("somebucket", "somefile", user_profile, {}, None)
mock_make_html_response.assert_called_once_with(
{
"contentstring": "Could not find requested data.",
Expand Down Expand Up @@ -710,7 +710,7 @@ def test_try_download_from_bucket_invalid_range(
"bar"
)

response = app.try_download_from_bucket("somebucket", "somefile", user_profile, {})
response = app.try_download_from_bucket("somebucket", "somefile", user_profile, {}, None)
assert response.body == "Invalid Range"
assert response.status_code == 416
assert response.headers == {}
Expand Down Expand Up @@ -1197,13 +1197,15 @@ def test_dynamic_url_head_missing_proxy(mock_get_yaml_file, current_request):


@mock.patch(f"{MODULE}.get_yaml_file", autospec=True)
@mock.patch(f"{MODULE}.get_api_request_uuid", autospec=True)
@mock.patch(f"{MODULE}.try_download_from_bucket", autospec=True)
@mock.patch(f"{MODULE}.JwtManager.get_profile_from_headers", autospec=True)
@mock.patch(f"{MODULE}.JWT_COOKIE_NAME", "asf-cookie")
@mock.patch(f"{MODULE}.b_map", None)
def test_dynamic_url(
mock_get_profile,
mock_try_download_from_bucket,
mock_get_api_request_uuid,
mock_get_yaml_file,
data_path,
user_profile,
Expand All @@ -1215,6 +1217,7 @@ def test_dynamic_url(
mock_get_yaml_file.return_value = yaml.full_load(f)

mock_get_profile.return_value = user_profile
mock_get_api_request_uuid.return_value = None
current_request.uri_params = {"proxy": "DATA-TYPE-1/PLATFORM-A/OBJECT_1"}

# Can't use the chalice test client here as it doesn't seem to understand the `{proxy+}` route
Expand All @@ -1224,19 +1227,22 @@ def test_dynamic_url(
"gsfc-ngap-d-pa-dt1",
"OBJECT_1",
user_profile,
{}
{},
None
)
assert response is MOCK_RESPONSE


@mock.patch(f"{MODULE}.get_yaml_file", autospec=True)
@mock.patch(f"{MODULE}.get_api_request_uuid", autospec=True)
@mock.patch(f"{MODULE}.try_download_from_bucket", autospec=True)
@mock.patch(f"{MODULE}.JwtManager.get_profile_from_headers", autospec=True)
@mock.patch(f"{MODULE}.JWT_COOKIE_NAME", "asf-cookie")
@mock.patch(f"{MODULE}.b_map", None)
def test_dynamic_url_public_unauthenticated(
mock_get_profile,
mock_try_download_from_bucket,
mock_get_api_request_uuid,
mock_get_yaml_file,
data_path,
current_request
Expand All @@ -1247,23 +1253,26 @@ def test_dynamic_url_public_unauthenticated(
mock_get_yaml_file.return_value = yaml.full_load(f)

mock_get_profile.return_value = None
mock_get_api_request_uuid.return_value = None
current_request.uri_params = {"proxy": "BROWSE/PLATFORM-A/OBJECT_2"}

# Can't use the chalice test client here as it doesn't seem to understand the `{proxy+}` route
response = app.dynamic_url()

mock_try_download_from_bucket.assert_called_once_with("gsfc-ngap-d-pa-bro", "OBJECT_2", None, {})
mock_try_download_from_bucket.assert_called_once_with("gsfc-ngap-d-pa-bro", "OBJECT_2", None, {}, None)
assert response is MOCK_RESPONSE


@mock.patch(f"{MODULE}.get_yaml_file", autospec=True)
@mock.patch(f"{MODULE}.get_api_request_uuid", autospec=True)
@mock.patch(f"{MODULE}.try_download_from_bucket", autospec=True)
@mock.patch(f"{MODULE}.JwtManager.get_profile_from_headers", autospec=True)
@mock.patch(f"{MODULE}.JWT_COOKIE_NAME", "asf-cookie")
@mock.patch(f"{MODULE}.b_map", None)
def test_dynamic_url_public_authenticated(
mock_get_profile,
mock_try_download_from_bucket,
mock_get_api_request_uuid,
mock_get_yaml_file,
data_path,
user_profile,
Expand All @@ -1275,23 +1284,26 @@ def test_dynamic_url_public_authenticated(
mock_get_yaml_file.return_value = yaml.full_load(f)

mock_get_profile.return_value = user_profile
mock_get_api_request_uuid.return_value = None
current_request.uri_params = {"proxy": "BROWSE/PLATFORM-A/OBJECT_2"}

# Can't use the chalice test client here as it doesn't seem to understand the `{proxy+}` route
response = app.dynamic_url()

mock_try_download_from_bucket.assert_called_once_with("gsfc-ngap-d-pa-bro", "OBJECT_2", user_profile, {})
mock_try_download_from_bucket.assert_called_once_with("gsfc-ngap-d-pa-bro", "OBJECT_2", user_profile, {}, None)
assert response is MOCK_RESPONSE


@mock.patch(f"{MODULE}.get_yaml_file", autospec=True)
@mock.patch(f"{MODULE}.get_api_request_uuid", autospec=True)
@mock.patch(f"{MODULE}.try_download_from_bucket", autospec=True)
@mock.patch(f"{MODULE}.JwtManager.get_profile_from_headers", autospec=True)
@mock.patch(f"{MODULE}.JWT_COOKIE_NAME", "asf-cookie")
@mock.patch(f"{MODULE}.b_map", None)
def test_dynamic_url_public_custom_headers(
mock_get_profile,
mock_try_download_from_bucket,
mock_get_api_request_uuid,
mock_get_yaml_file,
data_path,
current_request
Expand All @@ -1302,6 +1314,7 @@ def test_dynamic_url_public_custom_headers(
mock_get_yaml_file.return_value = yaml.full_load(f)

mock_get_profile.return_value = None
mock_get_api_request_uuid.return_value = None
current_request.uri_params = {"proxy": "HEADERS/BROWSE/OBJECT_1"}

# Can't use the chalice test client here as it doesn't seem to understand the `{proxy+}` route
Expand All @@ -1314,12 +1327,14 @@ def test_dynamic_url_public_custom_headers(
{
"custom-header-1": "custom-header-1-value",
"custom-header-2": "custom-header-2-value"
}
},
None
)
assert response is MOCK_RESPONSE


@mock.patch(f"{MODULE}.get_yaml_file", autospec=True)
@mock.patch(f"{MODULE}.get_api_request_uuid", autospec=True)
@mock.patch(f"{MODULE}.try_download_from_bucket", autospec=True)
@mock.patch(f"{MODULE}.user_in_group", autospec=True)
@mock.patch(f"{MODULE}.JwtManager.get_profile_from_headers", autospec=True)
Expand All @@ -1331,6 +1346,7 @@ def test_dynamic_url_private(
mock_get_profile,
mock_user_in_group,
mock_try_download_from_bucket,
mock_get_api_request_uuid,
mock_get_yaml_file,
data_path,
user_profile,
Expand All @@ -1344,6 +1360,7 @@ def test_dynamic_url_private(
mock_get_yaml_file.return_value = yaml.full_load(f)

mock_get_profile.return_value = user_profile
mock_get_api_request_uuid.return_value = None
current_request.uri_params = {"proxy": "PRIVATE/PLATFORM-A/OBJECT_2"}

# Can't use the chalice test client here as it doesn't seem to understand the `{proxy+}` route
Expand All @@ -1353,12 +1370,14 @@ def test_dynamic_url_private(
"gsfc-ngap-d-pa-priv",
"OBJECT_2",
user_profile,
{"SET-COOKIE": "cookie"}
{"SET-COOKIE": "cookie"},
None
)
assert response is MOCK_RESPONSE


@mock.patch(f"{MODULE}.get_yaml_file", autospec=True)
@mock.patch(f"{MODULE}.get_api_request_uuid", autospec=True)
@mock.patch(f"{MODULE}.try_download_from_bucket", autospec=True)
@mock.patch(f"{MODULE}.user_in_group", autospec=True)
@mock.patch(f"{MODULE}.JwtManager.get_profile_from_headers", autospec=True)
Expand All @@ -1370,6 +1389,7 @@ def test_dynamic_url_private_custom_headers(
mock_get_profile,
mock_user_in_group,
mock_try_download_from_bucket,
mock_get_api_request_uuid,
mock_get_yaml_file,
data_path,
user_profile,
Expand All @@ -1384,6 +1404,7 @@ def test_dynamic_url_private_custom_headers(
mock_get_yaml_file.return_value = yaml.full_load(f)

mock_get_profile.return_value = user_profile
mock_get_api_request_uuid.return_value = None
current_request.uri_params = {"proxy": "HEADERS/PRIVATE/OBJECT_1"}

# Can't use the chalice test client here as it doesn't seem to understand the `{proxy+}` route
Expand All @@ -1397,19 +1418,22 @@ def test_dynamic_url_private_custom_headers(
"custom-header-3": "custom-header-3-value",
"custom-header-4": "custom-header-4-value",
"SET-COOKIE": "cookie"
}
},
None
)
assert response is MOCK_RESPONSE


@mock.patch(f"{MODULE}.get_yaml_file", autospec=True)
@mock.patch(f"{MODULE}.get_api_request_uuid", autospec=True)
@mock.patch(f"{MODULE}.try_download_from_bucket", autospec=True)
@mock.patch(f"{MODULE}.JwtManager.get_profile_from_headers", autospec=True)
@mock.patch(f"{MODULE}.JWT_COOKIE_NAME", "asf-cookie")
@mock.patch(f"{MODULE}.b_map", None)
def test_dynamic_url_public_within_private(
mock_get_profile_from_headers,
mock_try_download_from_bucket,
mock_get_api_request_uuid,
mock_get_yaml_file,
current_request
):
Expand All @@ -1427,12 +1451,13 @@ def test_dynamic_url_public_within_private(
}

mock_get_profile_from_headers.return_value = None
mock_get_api_request_uuid.return_value = None
current_request.uri_params = {"proxy": "FOO/BROWSE/OBJECT_1"}

# Can't use the chalice test client here as it doesn't seem to understand the `{proxy+}` route
response = app.dynamic_url()

mock_try_download_from_bucket.assert_called_once_with("gsfc-ngap-d-bucket", "BROWSE/OBJECT_1", None, {})
mock_try_download_from_bucket.assert_called_once_with("gsfc-ngap-d-bucket", "BROWSE/OBJECT_1", None, {}, None)
assert response is MOCK_RESPONSE


Expand Down Expand Up @@ -1503,6 +1528,7 @@ def test_dynamic_url_directory(


@mock.patch(f"{MODULE}.get_yaml_file", autospec=True)
@mock.patch(f"{MODULE}.get_api_request_uuid", autospec=True)
@mock.patch(f"{MODULE}.try_download_from_bucket", autospec=True)
@mock.patch(f"{MODULE}.JwtManager.get_profile_from_headers", autospec=True)
@mock.patch(f"{MODULE}.RequestAuthorizer._handle_auth_bearer_header", autospec=True)
Expand All @@ -1514,6 +1540,7 @@ def test_dynamic_url_bearer_auth(
mock_handle_auth_bearer_header,
mock_get_profile,
mock_try_download_from_bucket,
mock_get_api_request_uuid,
mock_get_yaml_file,
data_path,
user_profile,
Expand All @@ -1526,6 +1553,7 @@ def test_dynamic_url_bearer_auth(
mock_get_yaml_file.return_value = yaml.full_load(f)

mock_get_profile.return_value = None
mock_get_api_request_uuid.return_value = None
current_request.uri_params = {"proxy": "DATA-TYPE-1/PLATFORM-A/OBJECT_1"}
current_request.headers = {"Authorization": "bearer b64token"}

Expand All @@ -1536,7 +1564,8 @@ def test_dynamic_url_bearer_auth(
"gsfc-ngap-d-pa-dt1",
"OBJECT_1",
user_profile,
{"SET-COOKIE": "cookie"}
{"SET-COOKIE": "cookie"},
None
)
assert response.body == "Mock response"
assert response.status_code == 200
Expand Down Expand Up @@ -1687,3 +1716,14 @@ def test_x_origin_request_id_forwarded(mock_retrieve_secret, client):
response = client.http.get("/profile", headers={"x-origin-request-id": "x_origin_request_1234"})

assert response.headers["x-origin-request-id"] == "x_origin_request_1234"


def test_get_api_request_uuid():
response = app.get_api_request_uuid({"A-api-request-uuid": "test-uuid"})
assert response == "test-uuid"

response = app.get_api_request_uuid({"A-userid": "test-userid"})
assert response is None

response = app.get_api_request_uuid(None)
assert response is None
Loading

0 comments on commit 4463527

Please sign in to comment.