-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
283 additions
and
82 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
TODO DSS0300 comes in here somewhere |
31 changes: 31 additions & 0 deletions
31
monitoring/uss_qualifier/scenarios/astm/utm/dss_interoperability.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# ASTM F3548-21 UTM DSS interoperability test scenario | ||
|
||
## Overview | ||
|
||
TODO: Complete with details once we check more than the prerequisites. | ||
|
||
This scenario currently only checks that all specified DSS instances are publicly addressable and reachable. | ||
|
||
## Resources | ||
|
||
### primary_dss_instance | ||
|
||
A resources.astm.f3548.v21.DSSInstanceResource containing the "primary" DSS instance for this scenario. | ||
|
||
### all_dss_instances | ||
|
||
A resources.astm.f3548.v21.DSSInstancesResource containing at least two DSS instances complying with ASTM F3548-21. | ||
|
||
## Prerequisites test case | ||
|
||
### Test environment requirements test step | ||
|
||
#### DSS instance is publicly addressable check | ||
|
||
As per **[astm.f3548.v21.DSS0300](../../../requirements/astm/f3548/v21.md)** the DSS instance should be publicly addressable. | ||
As such, this check will fail if the resolved IP of the DSS host is a private IP address, unless that is explicitly | ||
expected. | ||
|
||
#### DSS instance is reachable check | ||
As per **[astm.f3548.v21.DSS0300](../../../requirements/astm/f3548/v21.md)** the DSS instance should be publicly addressable. | ||
As such, this check will fail if the DSS is not reachable with a dummy query. |
119 changes: 119 additions & 0 deletions
119
monitoring/uss_qualifier/scenarios/astm/utm/dss_interoperability.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import ipaddress | ||
import socket | ||
import time | ||
import uuid | ||
from dataclasses import dataclass | ||
import datetime | ||
from enum import Enum | ||
from typing import List, Dict, Optional | ||
from urllib.parse import urlparse | ||
|
||
import s2sphere | ||
|
||
from monitoring.monitorlib.fetch.rid import ISA | ||
from monitoring.uss_qualifier.common_data_definitions import Severity | ||
from monitoring.uss_qualifier.resources.astm.f3411.dss import ( | ||
DSSInstancesResource, | ||
DSSInstanceResource, | ||
) | ||
from monitoring.uss_qualifier.scenarios.astm.netrid.dss_wrapper import DSSWrapper | ||
from monitoring.uss_qualifier.scenarios.scenario import GenericTestScenario | ||
|
||
VERTICES: List[s2sphere.LatLng] = [ | ||
s2sphere.LatLng.from_degrees(lng=130.6205, lat=-23.6558), | ||
s2sphere.LatLng.from_degrees(lng=130.6301, lat=-23.6898), | ||
s2sphere.LatLng.from_degrees(lng=130.6700, lat=-23.6709), | ||
s2sphere.LatLng.from_degrees(lng=130.6466, lat=-23.6407), | ||
] | ||
SHORT_WAIT_SEC = 5 | ||
|
||
|
||
class EntityType(str, Enum): | ||
ISA = "ISA" | ||
Sub = "Sub" | ||
|
||
|
||
@dataclass | ||
class TestEntity(object): | ||
type: EntityType | ||
uuid: str | ||
version: Optional[str] = None | ||
|
||
|
||
class DSSInteroperability(GenericTestScenario): | ||
_dss_primary: DSSWrapper | ||
_dss_others: List[DSSWrapper] | ||
_context: Dict[str, TestEntity] | ||
|
||
def __init__( | ||
self, | ||
primary_dss_instance: DSSInstanceResource, | ||
all_dss_instances: DSSInstancesResource, | ||
): | ||
super().__init__() | ||
self._dss_primary = DSSWrapper(self, primary_dss_instance.dss_instance) | ||
self._dss_others = [ | ||
DSSWrapper(self, dss) | ||
for dss in all_dss_instances.dss_instances | ||
if not dss.is_same_as(primary_dss_instance.dss_instance) | ||
] | ||
self._context: Dict[str, TestEntity] = {} | ||
|
||
def _new_isa(self, name: str) -> TestEntity: | ||
self._context[name] = TestEntity(EntityType.ISA, str(uuid.uuid4())) | ||
return self._context[name] | ||
|
||
def _new_sub(self, name: str) -> TestEntity: | ||
self._context[name] = TestEntity(EntityType.Sub, str(uuid.uuid4())) | ||
return self._context[name] | ||
|
||
def _get_entities_by_prefix(self, prefix: str) -> Dict[str, TestEntity]: | ||
all_entities = dict() | ||
for name, entity in self._context.items(): | ||
if name.startswith(prefix): | ||
all_entities[entity.uuid] = entity | ||
return all_entities | ||
|
||
def run(self): | ||
|
||
self.record_note("dss_instances", f"Provided DSS instances: {[self._dss_primary] + self._dss_others}") | ||
self.begin_test_scenario() | ||
|
||
self.begin_test_case("Prerequisites") | ||
|
||
self.begin_test_step("Test environment requirements") | ||
self._test_env_reqs() | ||
self.end_test_step() | ||
|
||
self.end_test_case() | ||
|
||
self.end_test_scenario() | ||
|
||
def _test_env_reqs(self): | ||
for dss in [self._dss_primary] + self._dss_others: | ||
with self.check( | ||
"DSS instance is publicly addressable", [dss.participant_id] | ||
) as check: | ||
parsed_url = urlparse(dss.base_url) | ||
ip_addr = socket.gethostbyname(parsed_url.hostname) | ||
|
||
if dss.has_private_address: | ||
self.record_note( | ||
f"{dss.participant_id}_private_address", | ||
f"DSS instance (URL: {dss.base_url}, netloc: {parsed_url.netloc}, resolved IP: {ip_addr}) is declared as explicitly having a private address, skipping check", | ||
) | ||
elif ipaddress.ip_address(ip_addr).is_private: | ||
check.record_failed( | ||
summary=f"DSS host {parsed_url.netloc} is not publicly addressable", | ||
severity=Severity.Medium, | ||
participants=[dss.participant_id], | ||
details=f"DSS (URL: {dss.base_url}, netloc: {parsed_url.netloc}, resolved IP: {ip_addr}) is not publicly addressable", | ||
) | ||
|
||
with self.check("DSS instance is reachable", [dss.participant_id]) as check: | ||
# dummy search query | ||
dss.search_subs(check, VERTICES) | ||
|
||
def cleanup(self): | ||
self.begin_cleanup() | ||
self.end_cleanup() |
Oops, something went wrong.