Skip to content

Commit 33d0ad1

Browse files
committed
[uss_qualifier] netrid: DSS0020 - check DSS endpoints are encrypted
1 parent dd28059 commit 33d0ad1

File tree

15 files changed

+276
-23
lines changed

15 files changed

+276
-23
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
from urllib.parse import urlparse
2+
3+
import requests
4+
5+
from monitoring.uss_qualifier.resources.astm.f3411.dss import DSSInstanceResource
6+
from monitoring.uss_qualifier.scenarios.scenario import GenericTestScenario
7+
from monitoring.uss_qualifier.suites.suite import ExecutionContext
8+
9+
10+
class EndpointEncryption(GenericTestScenario):
11+
"""
12+
Ensures that the endpoints of a DSS are not accessible unencrypted:
13+
- HTTP access should be impossible or redirect to HTTPS
14+
- HTTPS access should be possible
15+
16+
TODO: add a check for minimal cipher strength to a 128bit AES equivalent or more.
17+
"""
18+
19+
def __init__(
20+
self,
21+
dss: DSSInstanceResource,
22+
):
23+
super().__init__()
24+
self._dss = dss.dss_instance
25+
26+
def run(self, context: ExecutionContext):
27+
self.begin_test_scenario(context)
28+
29+
if not self._dss.base_url.startswith("https://"):
30+
self.record_note(
31+
"encrypted_endpoints",
32+
"Cannot check encryption requirement when DSS endpoint is specified with an http:// base URL",
33+
)
34+
self.end_test_scenario()
35+
return
36+
37+
self._case_http_unavailable_or_redirect()
38+
39+
self.end_test_scenario()
40+
41+
def _case_http_unavailable_or_redirect(self):
42+
self.begin_test_case("Connect to HTTP port")
43+
self.begin_test_step("Attempt to connect to the DSS instance on the HTTP port")
44+
45+
parsed_url = urlparse(self._dss.base_url)
46+
hostname = parsed_url.hostname
47+
48+
if hostname is not None:
49+
with self.check(
50+
"Connection to HTTP port fails or redirects to HTTPS port",
51+
self._dss.participant_id,
52+
) as check:
53+
try:
54+
response = requests.get(
55+
f"http://{hostname}/{parsed_url.path}",
56+
timeout=10,
57+
allow_redirects=False,
58+
)
59+
# If we can connect, we want to check that we are being redirected:
60+
if response.status_code not in [301, 308]:
61+
check.record_failed(
62+
"Connection to HTTP port did not redirect",
63+
details=f"Was expecting a 301 or 308 response, but obtained status code: {response.status_code}",
64+
)
65+
if "Location" not in response.headers:
66+
check.record_failed(
67+
"Location header missing in redirect response",
68+
details="Was expecting a Location header in the response, but it was not present",
69+
)
70+
if response.headers.get("Location").startswith("http://"):
71+
check.record_failed(
72+
"Connection to HTTP port redirected to HTTP",
73+
details=f"Was expecting a redirection to an https:// URL. Location header: {response.headers.get('Location')}",
74+
)
75+
if not response.headers.get("Location").startswith(
76+
f"https://{parsed_url.hostname}/{parsed_url.path}"
77+
):
78+
check.record_failed(
79+
"Redirect to unexpected destination",
80+
details=f"Was expecting a redirection to https://{parsed_url.hostname}/{parsed_url.path}, was {response.headers.get('Location')}",
81+
)
82+
except requests.RequestException:
83+
# Connection was impossible: all is good
84+
pass
85+
86+
self.end_test_step()
87+
self.end_test_case()
88+
89+
def _case_https_works(self):
90+
self.begin_test_case("Connect to HTTPS port")
91+
self.begin_test_step("Attempt to connect to the DSS instance on the HTTPS port")
92+
93+
parsed_url = urlparse(self._dss.base_url)
94+
hostname = parsed_url.hostname
95+
96+
if hostname is not None:
97+
with self.check(
98+
"A request can be sent over HTTPS",
99+
self._dss.participant_id,
100+
) as check:
101+
try:
102+
requests.get(
103+
f"https://{hostname}/{parsed_url.path}",
104+
timeout=10,
105+
allow_redirects=False,
106+
)
107+
# We don't care about the response details, just that the connection was successful
108+
# (a 404 would still indicate that HTTPS is working well)
109+
except requests.RequestException as e:
110+
check.record_failed(
111+
"Connection to HTTPS port failed",
112+
details=f"Encountered exception while attempting HTTPS request: {e}",
113+
)
114+
115+
self.end_test_step()
116+
self.end_test_case()

monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77
from .token_validation import TokenValidation
88
from .crdb_access import CRDBAccess
99
from .heavy_traffic_concurrent import HeavyTrafficConcurrent
10+
from .endpoint_encryption import EndpointEncryption
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# ASTM NetRID DSS: Endpoint encryption test scenario
2+
3+
## Overview
4+
5+
Ensures that a DSS only exposes its endpoints via HTTPS.
6+
7+
## Resources
8+
9+
### dss
10+
11+
[`DSSInstanceResource`](../../../../../resources/astm/f3411/dss.py) to be tested in this scenario.
12+
13+
14+
## Connect to HTTP port test case
15+
16+
Tries to connect to the http port (80) of the DSS instance, and expects either a refusal of the connection,
17+
or a redirection to the https port (443).
18+
19+
Note: this test case will be skipped if the DSS instance is configured to use HTTP.
20+
21+
### Attempt to connect to the DSS instance on the HTTP port test step
22+
23+
#### 🛑 Connection to HTTP port fails or redirects to HTTPS port check
24+
25+
If the DSS instance accepts the connection on the HTTP port and does not immediately redirect to the HTTPS port
26+
upon reception of an HTTP request, it is in violation of **[astm.f3411.v19.DSS0020](../../../../../requirements/astm/f3411/v19.md)**.
27+
28+
## Connect to HTTPS port test case
29+
30+
Try to connect to the DSS instance over HTTPS.
31+
32+
### Attempt to connect to the DSS instance on the HTTPS port test step
33+
34+
#### 🛑 A request can be sent over HTTPS check
35+
36+
If the DSS instance cannot be reached over HTTPS, it is in violation of **[astm.f3411.v19.DSS0020](../../../../../requirements/astm/f3411/v19.md)**.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from monitoring.uss_qualifier.scenarios.astm.netrid.common.dss.endpoint_encryption import (
2+
EndpointEncryption as CommonEndpointEncryption,
3+
)
4+
from monitoring.uss_qualifier.scenarios.scenario import TestScenario
5+
6+
7+
class EndpointEncryption(TestScenario, CommonEndpointEncryption):
8+
pass
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# ASTM NetRID DSS: Endpoint encryption test scenario
2+
3+
## Overview
4+
5+
Ensures that a DSS only exposes its endpoints via HTTPS.
6+
7+
## Resources
8+
9+
### dss
10+
11+
[`DSSInstanceResource`](../../../../../resources/astm/f3411/dss.py) to be tested in this scenario.
12+
13+
## Connect to HTTP port test case
14+
15+
Tries to connect to the http port (80) of the DSS instance, and expects either a refusal of the connection,
16+
or a redirection to the https port (443).
17+
18+
Note: this test case will be skipped if the DSS instance is configured to use HTTP.
19+
20+
### Attempt to connect to the DSS instance on the HTTP port test step
21+
22+
#### 🛑 Connection to HTTP port fails or redirects to HTTPS port check
23+
24+
If the DSS instance accepts the connection on the HTTP port and does not immediately redirect to the HTTPS port
25+
upon reception of an HTTP request, it is in violation of **[astm.f3411.v22a.DSS0020](../../../../../requirements/astm/f3411/v22a.md)**.
26+
27+
## Connect to HTTPS port test case
28+
29+
Try to connect to the DSS instance over HTTPS.
30+
31+
### Attempt to connect to the DSS instance on the HTTPS port test step
32+
33+
#### 🛑 A request can be sent over HTTPS check
34+
35+
If the DSS instance cannot be reached over HTTPS, it is in violation of **[astm.f3411.v22a.DSS0020](../../../../../requirements/astm/f3411/v22a.md)**.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from monitoring.uss_qualifier.scenarios.astm.netrid.common.dss.endpoint_encryption import (
2+
EndpointEncryption as CommonEndpointEncryption,
3+
)
4+
from monitoring.uss_qualifier.scenarios.scenario import TestScenario
5+
6+
7+
class EndpointEncryption(TestScenario, CommonEndpointEncryption):
8+
pass

monitoring/uss_qualifier/suites/astm/netrid/f3411_19.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,16 @@
2121
<th><a href="../../README.md#checked-in">Checked in</a></th>
2222
</tr>
2323
<tr>
24-
<td rowspan="62" style="vertical-align:top;"><a href="../../../requirements/astm/f3411/v19.md">astm<br>.f3411<br>.v19</a></td>
24+
<td rowspan="63" style="vertical-align:top;"><a href="../../../requirements/astm/f3411/v19.md">astm<br>.f3411<br>.v19</a></td>
2525
<td><a href="../../../requirements/astm/f3411/v19.md">DSS0010</a></td>
2626
<td>Implemented</td>
2727
<td><a href="../../../scenarios/astm/netrid/v19/dss/token_validation.md">ASTM NetRID DSS: Token Validation</a></td>
2828
</tr>
29+
<tr>
30+
<td><a href="../../../requirements/astm/f3411/v19.md">DSS0020</a></td>
31+
<td>Implemented</td>
32+
<td><a href="../../../scenarios/astm/netrid/v19/dss/endpoint_encryption.md">ASTM NetRID DSS: Endpoint encryption</a></td>
33+
</tr>
2934
<tr>
3035
<td><a href="../../../requirements/astm/f3411/v19.md">DSS0030,a</a></td>
3136
<td>Implemented</td>

monitoring/uss_qualifier/suites/astm/netrid/f3411_19/dss_probing.md

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,17 @@
44

55
## [Actions](../../../README.md#actions)
66

7-
1. Scenario: [ASTM NetRID DSS: Simple ISA](../../../../scenarios/astm/netrid/v19/dss/isa_simple.md) ([`scenarios.astm.netrid.v19.dss.ISASimple`](../../../../scenarios/astm/netrid/v19/dss/isa_simple.py))
8-
2. Scenario: [ASTM NetRID DSS: Submitted ISA Validations](../../../../scenarios/astm/netrid/v19/dss/isa_validation.md) ([`scenarios.astm.netrid.v19.dss.ISAValidation`](../../../../scenarios/astm/netrid/v19/dss/isa_validation.py))
9-
3. Scenario: [ASTM NetRID DSS: ISA Expiry](../../../../scenarios/astm/netrid/v19/dss/isa_expiry.md) ([`scenarios.astm.netrid.v19.dss.ISAExpiry`](../../../../scenarios/astm/netrid/v19/dss/isa_expiry.py))
10-
4. Scenario: [ASTM NetRID DSS: ISA Subscription Interactions](../../../../scenarios/astm/netrid/v19/dss/isa_subscription_interactions.md) ([`scenarios.astm.netrid.v19.dss.ISASubscriptionInteractions`](../../../../scenarios/astm/netrid/v19/dss/isa_subscription_interactions.py))
11-
5. Scenario: [ASTM NetRID DSS: Subscription Validation](../../../../scenarios/astm/netrid/v19/dss/subscription_validation.md) ([`scenarios.astm.netrid.v19.dss.SubscriptionValidation`](../../../../scenarios/astm/netrid/v19/dss/subscription_validation.py))
12-
6. Scenario: [ASTM NetRID DSS: Subscription Simple](../../../../scenarios/astm/netrid/v19/dss/subscription_simple.md) ([`scenarios.astm.netrid.v19.dss.SubscriptionSimple`](../../../../scenarios/astm/netrid/v19/dss/subscription_simple.py))
13-
7. Scenario: [ASTM F3411-19 NetRID DSS interoperability](../../../../scenarios/astm/netrid/v19/dss_interoperability.md) ([`scenarios.astm.netrid.v19.DSSInteroperability`](../../../../scenarios/astm/netrid/v19/dss_interoperability.py))
14-
8. Scenario: [ASTM NetRID DSS: Token Validation](../../../../scenarios/astm/netrid/v19/dss/token_validation.md) ([`scenarios.astm.netrid.v19.dss.TokenValidation`](../../../../scenarios/astm/netrid/v19/dss/token_validation.py))
15-
9. Scenario: [ASTM NetRID DSS: Direct CRDB access](../../../../scenarios/astm/netrid/v19/dss/crdb_access.md) ([`scenarios.astm.netrid.v19.dss.CRDBAccess`](../../../../scenarios/astm/netrid/v19/dss/crdb_access.py))
16-
10. Scenario: [ASTM NetRID DSS: Concurrent Requests](../../../../scenarios/astm/netrid/v19/dss/heavy_traffic_concurrent.md) ([`scenarios.astm.netrid.v19.dss.HeavyTrafficConcurrent`](../../../../scenarios/astm/netrid/v19/dss/heavy_traffic_concurrent.py))
7+
1. Scenario: [ASTM NetRID DSS: Endpoint encryption](../../../../scenarios/astm/netrid/v19/dss/endpoint_encryption.md) ([`scenarios.astm.netrid.v19.dss.EndpointEncryption`](../../../../scenarios/astm/netrid/v19/dss/endpoint_encryption.py))
8+
2. Scenario: [ASTM NetRID DSS: Simple ISA](../../../../scenarios/astm/netrid/v19/dss/isa_simple.md) ([`scenarios.astm.netrid.v19.dss.ISASimple`](../../../../scenarios/astm/netrid/v19/dss/isa_simple.py))
9+
3. Scenario: [ASTM NetRID DSS: Submitted ISA Validations](../../../../scenarios/astm/netrid/v19/dss/isa_validation.md) ([`scenarios.astm.netrid.v19.dss.ISAValidation`](../../../../scenarios/astm/netrid/v19/dss/isa_validation.py))
10+
4. Scenario: [ASTM NetRID DSS: ISA Expiry](../../../../scenarios/astm/netrid/v19/dss/isa_expiry.md) ([`scenarios.astm.netrid.v19.dss.ISAExpiry`](../../../../scenarios/astm/netrid/v19/dss/isa_expiry.py))
11+
5. Scenario: [ASTM NetRID DSS: ISA Subscription Interactions](../../../../scenarios/astm/netrid/v19/dss/isa_subscription_interactions.md) ([`scenarios.astm.netrid.v19.dss.ISASubscriptionInteractions`](../../../../scenarios/astm/netrid/v19/dss/isa_subscription_interactions.py))
12+
6. Scenario: [ASTM NetRID DSS: Subscription Validation](../../../../scenarios/astm/netrid/v19/dss/subscription_validation.md) ([`scenarios.astm.netrid.v19.dss.SubscriptionValidation`](../../../../scenarios/astm/netrid/v19/dss/subscription_validation.py))
13+
7. Scenario: [ASTM NetRID DSS: Subscription Simple](../../../../scenarios/astm/netrid/v19/dss/subscription_simple.md) ([`scenarios.astm.netrid.v19.dss.SubscriptionSimple`](../../../../scenarios/astm/netrid/v19/dss/subscription_simple.py))
14+
8. Scenario: [ASTM F3411-19 NetRID DSS interoperability](../../../../scenarios/astm/netrid/v19/dss_interoperability.md) ([`scenarios.astm.netrid.v19.DSSInteroperability`](../../../../scenarios/astm/netrid/v19/dss_interoperability.py))
15+
9. Scenario: [ASTM NetRID DSS: Token Validation](../../../../scenarios/astm/netrid/v19/dss/token_validation.md) ([`scenarios.astm.netrid.v19.dss.TokenValidation`](../../../../scenarios/astm/netrid/v19/dss/token_validation.py))
16+
10. Scenario: [ASTM NetRID DSS: Direct CRDB access](../../../../scenarios/astm/netrid/v19/dss/crdb_access.md) ([`scenarios.astm.netrid.v19.dss.CRDBAccess`](../../../../scenarios/astm/netrid/v19/dss/crdb_access.py))
17+
11. Scenario: [ASTM NetRID DSS: Concurrent Requests](../../../../scenarios/astm/netrid/v19/dss/heavy_traffic_concurrent.md) ([`scenarios.astm.netrid.v19.dss.HeavyTrafficConcurrent`](../../../../scenarios/astm/netrid/v19/dss/heavy_traffic_concurrent.py))
1718

1819
## [Checked requirements](../../../README.md#checked-requirements)
1920

@@ -25,11 +26,16 @@
2526
<th><a href="../../../README.md#checked-in">Checked in</a></th>
2627
</tr>
2728
<tr>
28-
<td rowspan="38" style="vertical-align:top;"><a href="../../../../requirements/astm/f3411/v19.md">astm<br>.f3411<br>.v19</a></td>
29+
<td rowspan="39" style="vertical-align:top;"><a href="../../../../requirements/astm/f3411/v19.md">astm<br>.f3411<br>.v19</a></td>
2930
<td><a href="../../../../requirements/astm/f3411/v19.md">DSS0010</a></td>
3031
<td>Implemented</td>
3132
<td><a href="../../../../scenarios/astm/netrid/v19/dss/token_validation.md">ASTM NetRID DSS: Token Validation</a></td>
3233
</tr>
34+
<tr>
35+
<td><a href="../../../../requirements/astm/f3411/v19.md">DSS0020</a></td>
36+
<td>Implemented</td>
37+
<td><a href="../../../../scenarios/astm/netrid/v19/dss/endpoint_encryption.md">ASTM NetRID DSS: Endpoint encryption</a></td>
38+
</tr>
3339
<tr>
3440
<td><a href="../../../../requirements/astm/f3411/v19.md">DSS0030,a</a></td>
3541
<td>Implemented</td>

monitoring/uss_qualifier/suites/astm/netrid/f3411_19/dss_probing.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ resources:
99
problematically_big_area: resources.VerticesResource
1010
test_exclusions: resources.dev.TestExclusionsResource?
1111
actions:
12+
- test_scenario:
13+
scenario_type: scenarios.astm.netrid.v19.dss.EndpointEncryption
14+
resources:
15+
dss: dss
1216
- test_scenario:
1317
scenario_type: scenarios.astm.netrid.v19.dss.ISASimple
1418
resources:

monitoring/uss_qualifier/suites/astm/netrid/f3411_22a.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@
2020
<th><a href="../../README.md#status">Status</a></th>
2121
<th><a href="../../README.md#checked-in">Checked in</a></th>
2222
</tr>
23+
<tr>
24+
<td rowspan="1" style="vertical-align:top;"><a href="../../../requirements/astm/f3411/v19.md">astm<br>.f3411<br>.v19</a></td>
25+
<td><a href="../../../requirements/astm/f3411/v19.md">DSS0020</a></td>
26+
<td>Implemented</td>
27+
<td><a href="../../../scenarios/astm/netrid/v19/dss/endpoint_encryption.md">ASTM NetRID DSS: Endpoint encryption</a></td>
28+
</tr>
2329
<tr>
2430
<td rowspan="87" style="vertical-align:top;"><a href="../../../requirements/astm/f3411/v22a.md">astm<br>.f3411<br>.v22a</a></td>
2531
<td><a href="../../../requirements/astm/f3411/v22a.md">DSS0010</a></td>

0 commit comments

Comments
 (0)