Skip to content

Commit e3fa8d6

Browse files
committed
Add integration tests for URL headers configuration
1 parent d7efaf4 commit e3fa8d6

File tree

1 file changed

+109
-13
lines changed

1 file changed

+109
-13
lines changed

test/integration/test_landing_requests.py

Lines changed: 109 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,34 @@
2626

2727
TEST_URL = "base64://eyJ0ZXN0IjogInRlc3QifQ==" # base64 encoded {"test": "test"}
2828

29-
30-
class BaseLandingRequestTest(integration_util.IntegrationTestCase):
29+
# URL headers configuration for tests - allows both sensitive and non-sensitive headers
30+
ALLOW_URL_HEADERS_CONF = """
31+
patterns:
32+
# Match all URLs (including base64://) for testing
33+
- url_pattern: "^.*"
34+
headers:
35+
# Sensitive headers - will be encrypted when vault is configured
36+
- name: Authorization
37+
sensitive: true
38+
- name: X-API-Key
39+
sensitive: true
40+
# Non-sensitive headers
41+
- name: Content-Type
42+
sensitive: false
43+
- name: Accept
44+
sensitive: false
45+
- name: Accept-Language
46+
sensitive: false
47+
- name: Accept-Encoding
48+
sensitive: false
49+
- name: Cache-Control
50+
sensitive: false
51+
- name: X-Custom-Header
52+
sensitive: false
53+
"""
54+
55+
56+
class BaseLandingRequestTest(integration_util.IntegrationTestCase, integration_util.ConfigureAllowedUrlHeaders):
3157
"""Base class with common setup for landing request tests."""
3258

3359
dataset_populator: DatasetPopulator
@@ -132,6 +158,7 @@ class TestLandingRequestsIntegration(BaseLandingRequestTest, integration_util.Co
132158
def handle_galaxy_config_kwds(cls, config):
133159
super().handle_galaxy_config_kwds(config)
134160
cls._configure_database_vault(config)
161+
cls._configure_allowed_url_headers(ALLOW_URL_HEADERS_CONF, config)
135162

136163
def test_data_landing_with_encrypted_headers(self):
137164
"""Test that sensitive headers are encrypted in the vault when stored in landing requests.
@@ -144,7 +171,7 @@ def test_data_landing_with_encrypted_headers(self):
144171
headers = {
145172
"Authorization": "Bearer data-test-token-should-be-encrypted",
146173
"X-API-Key": "data-test-api-key-123456",
147-
"User-Agent": "Galaxy-Test/1.0",
174+
"Accept": "application/json",
148175
"Content-Type": "application/json",
149176
"X-Custom-Header": "custom-value",
150177
}
@@ -175,12 +202,13 @@ def test_workflow_landing_with_encrypted_headers(self):
175202
input1_headers = {
176203
"Authorization": "Bearer workflow-test-token-should-be-encrypted",
177204
"X-API-Key": "workflow-test-api-key-123456",
178-
"User-Agent": "Galaxy-Workflow-Test/1.0",
205+
"Accept": "application/json",
179206
"Content-Type": "application/json",
180207
}
181208
input2_headers = {
182209
"Authorization": "Bearer workflow-test-token-should-be-encrypted",
183210
"X-API-Key": "workflow-test-api-key-123456",
211+
"Accept-Language": "en-US",
184212
"X-Custom-Header": "custom-value",
185213
}
186214

@@ -216,25 +244,30 @@ def test_workflow_landing_with_encrypted_headers(self):
216244

217245

218246
class TestLandingRequestsWithoutVaultIntegration(BaseLandingRequestTest):
219-
"""Test landing requests when vault is not configured.
247+
"""Test landing requests when headers are configured but vault is not configured.
220248
221-
This class tests the behavior when no vault is configured but sensitive headers
222-
are present in the request. The system should fail fast rather than storing
223-
sensitive information in plain text.
249+
This class tests the behavior when headers configuration exists but no vault is configured.
250+
When sensitive headers are present, the system should fail because it cannot encrypt them.
224251
"""
225252

253+
@classmethod
254+
def handle_galaxy_config_kwds(cls, config):
255+
super().handle_galaxy_config_kwds(config)
256+
# Configure headers but NOT vault - this tests the vault requirement for sensitive headers
257+
cls._configure_allowed_url_headers(ALLOW_URL_HEADERS_CONF, config)
258+
226259
def test_data_landing_fails_without_vault_when_sensitive_headers_present(self):
227260
"""Test that data landing requests fail when vault is not configured but sensitive headers are present.
228261
229262
This test verifies that when sensitive headers (like Authorization, API keys, etc.) are present
230-
in a landing request but no vault is configured, the system fails fast rather than storing
231-
the sensitive information in plain text in the database.
263+
in a landing request but no vault is configured, the system fails with a 500 error rather than
264+
storing the sensitive information in plain text in the database.
232265
"""
233266
# Create headers with sensitive values
234267
headers = {
235268
"Authorization": "Bearer no-vault-test-token-should-fail",
236269
"X-API-Key": "no-vault-test-api-key-should-fail",
237-
"User-Agent": "Galaxy-Test/1.0",
270+
"Accept": "application/json",
238271
}
239272

240273
# Create data landing request with sensitive headers
@@ -254,7 +287,7 @@ def test_data_landing_succeeds_without_vault_when_no_sensitive_headers(self):
254287
"""
255288
# Create only non-sensitive headers
256289
headers = {
257-
"User-Agent": "Galaxy-Test/1.0",
290+
"Accept": "application/json",
258291
"Content-Type": "application/json",
259292
"X-Custom-Header": "custom-value",
260293
}
@@ -278,7 +311,7 @@ def test_workflow_landing_fails_without_vault_when_sensitive_headers_present(sel
278311
headers = {
279312
"Authorization": "Bearer workflow-no-vault-token-should-fail",
280313
"X-API-Key": "workflow-no-vault-api-key-should-fail",
281-
"User-Agent": "Galaxy-Workflow-Test/1.0",
314+
"Accept": "application/json",
282315
}
283316
workflow_request_state = self._create_workflow_input_with_headers(headers)
284317

@@ -297,3 +330,66 @@ def test_workflow_landing_fails_without_vault_when_sensitive_headers_present(sel
297330
json = payload.model_dump(mode="json")
298331
response = self.dataset_populator._post(create_url, json, json=True, anon=True)
299332
assert response.status_code == 500
333+
334+
335+
class TestLandingRequestsWithoutHeadersConfigIntegration(BaseLandingRequestTest):
336+
"""Test landing requests when no headers configuration exists.
337+
338+
This class tests the behavior when no URL headers configuration file is present.
339+
The system should fail fast with any headers (sensitive or not) because headers
340+
require explicit configuration to be allowed.
341+
"""
342+
343+
def test_data_landing_fails_without_config(self):
344+
"""Test that data landing requests fail when no URL headers configuration exists.
345+
346+
This test verifies the fail-fast behavior: when no URL headers configuration file
347+
exists, ANY attempt to use headers (sensitive or not) will fail immediately with
348+
a clear error message, rather than silently allowing or denying headers.
349+
"""
350+
# Create only non-sensitive headers
351+
headers = {
352+
"Accept": "application/json",
353+
"Content-Type": "application/json",
354+
"X-Custom-Header": "custom-value",
355+
}
356+
357+
# Create data landing request with headers
358+
request_state = self._create_data_landing_request_state(headers)
359+
payload = CreateDataLandingPayload(request_state=request_state, public=True)
360+
361+
# Should fail with 403 because no URL headers configuration is available (fail-fast)
362+
response = self.dataset_populator.create_data_landing_raw(payload)
363+
assert response.status_code == 403
364+
assert "No URL headers configuration is available" in response.json()["err_msg"]
365+
366+
def test_workflow_landing_fails_without_config(self):
367+
"""Test that workflow landing requests fail when no URL headers configuration exists.
368+
369+
This test verifies the fail-fast behavior for workflow landings: when no URL headers
370+
configuration file exists, any attempt to use headers will fail immediately.
371+
"""
372+
# Create workflow input with headers
373+
headers = {
374+
"Authorization": "Bearer workflow-no-vault-token-should-fail",
375+
"X-API-Key": "workflow-no-vault-api-key-should-fail",
376+
"Accept": "application/json",
377+
}
378+
workflow_request_state = self._create_workflow_input_with_headers(headers)
379+
380+
# Create workflow and landing request
381+
workflow_id = self._create_and_make_public_workflow("test_landing_no_config")
382+
payload = CreateWorkflowLandingRequestPayload(
383+
workflow_id=workflow_id,
384+
workflow_target_type="stored_workflow",
385+
request_state=workflow_request_state,
386+
public=True,
387+
)
388+
389+
# Should return 403 status code when trying to create the workflow landing request
390+
# because no URL headers configuration is available
391+
create_url = "workflow_landings"
392+
json = payload.model_dump(mode="json")
393+
response = self.dataset_populator._post(create_url, json, json=True, anon=True)
394+
assert response.status_code == 403
395+
assert "No URL headers configuration is available" in response.json()["err_msg"]

0 commit comments

Comments
 (0)