diff --git a/monitoring/uss_qualifier/scenarios/astm/utm/op_intent_ref_access_control.md b/monitoring/uss_qualifier/scenarios/astm/utm/op_intent_ref_access_control.md index ba560cb673..1cd31a6e86 100644 --- a/monitoring/uss_qualifier/scenarios/astm/utm/op_intent_ref_access_control.md +++ b/monitoring/uss_qualifier/scenarios/astm/utm/op_intent_ref_access_control.md @@ -73,6 +73,18 @@ Otherwise, the DSS is not in compliance with **[astm.f3548.v21.DSS0005,2](../../ If an existing operational intent cannot be deleted when providing the proper ID and OVN, the DSS implementation is in violation of **[astm.f3548.v21.DSS0005,1](../../../requirements/astm/f3548/v21.md)**. +#### ⚠️ Any existing operational intent reference has been removed check + +If, after cleanup, one or more operational intent reference are still present at the DSS, this scenario cannot proceed. + +This scenario is able to remove any operational intent reference that belongs to the configured credentials, but it cannot remove references +that belong to other credentials. + +A regular failure of this check indicates that other scenarios might not properly clean up their resources, or that the _Prepare Flight Planners_ +scenario should be moved in front of the present one. + +If this check fails, the rest of the scenario is entirely skipped. + ### Create operational intent references with different credentials test step This test step ensures that an operation intent reference created with the main credentials is available for the main test case. diff --git a/monitoring/uss_qualifier/scenarios/astm/utm/op_intent_ref_access_control.py b/monitoring/uss_qualifier/scenarios/astm/utm/op_intent_ref_access_control.py index 4e5a545608..a2fe956819 100644 --- a/monitoring/uss_qualifier/scenarios/astm/utm/op_intent_ref_access_control.py +++ b/monitoring/uss_qualifier/scenarios/astm/utm/op_intent_ref_access_control.py @@ -1,10 +1,9 @@ from typing import List -import loguru +from uas_standards.astm.f3548.v21 import api as f3548v21 from uas_standards.astm.f3548.v21.api import OperationalIntentState from monitoring.monitorlib.geotemporal import Volume4DCollection -from uas_standards.astm.f3548.v21 import api as f3548v21 from monitoring.prober.infrastructure import register_resource_type from monitoring.uss_qualifier.resources.astm.f3548.v21 import DSSInstanceResource from monitoring.uss_qualifier.resources.astm.f3548.v21.dss import ( @@ -102,29 +101,35 @@ def run(self, context: ExecutionContext): self.begin_test_case("Setup") self.begin_test_step("Ensure clean workspace") - self._ensure_clean_workspace() + ws_is_clean = self._ensure_clean_workspace() self.end_test_step() - self.begin_test_step( - "Create operational intent references with different credentials" - ) - self._create_op_intents() - self._ensure_credentials_are_different() - self.end_test_step() + if ws_is_clean: + self.begin_test_step( + "Create operational intent references with different credentials" + ) + self._create_op_intents() + self._ensure_credentials_are_different() + self.end_test_step() - self.end_test_case() + self.end_test_case() - self.begin_test_case( - "Attempt unauthorized operational intent reference modification" - ) - self.begin_test_step( - "Attempt unauthorized operational intent reference modification" - ) + self.begin_test_case( + "Attempt unauthorized operational intent reference modification" + ) + self.begin_test_step( + "Attempt unauthorized operational intent reference modification" + ) - self._check_mutation_on_non_owned_intent_fails() + self._check_mutation_on_non_owned_intent_fails() - self.end_test_step() - self.end_test_case() + self.end_test_step() + self.end_test_case() + else: + self.record_note( + "clean_workspace", + "Could not clean up workspace, skipping scenario", + ) self.end_test_scenario() @@ -183,13 +188,11 @@ def _clean_known_op_intents_ids(self): query_timestamps=[dq.request.timestamp], ) - def _ensure_clean_workspace(self): - self._clean_known_op_intents_ids() - + def _attempt_to_delete_remaining_op_intents(self): + """Search for op intents and attempt to delete them using the main credentials""" # Also check for any potential other op_intents and delete them (op_intents_1, q) = self._dss.find_op_intent(self._intents_extent) self.record_query(q) - loguru.logger.info(f"Search query: {q.response}") with self.check( "Operational intent references can be searched using valid credentials", self._pid, @@ -253,6 +256,51 @@ def _ensure_clean_workspace(self): query_timestamps=[dq.request.timestamp], ) + def _ensure_clean_workspace(self) -> bool: + """ + Tries to provide a clean workspace. If it fails to do so and the underlying check + has a severity below HIGH, this function will return false. + + It will only return true if the workspace is clean. + """ + # Record the subscription to help with troubleshooting in case of failures to clean-up + self.record_note("main_credentials", self._dss.client.auth_adapter.get_sub()) + self.record_note( + "secondary_credentials", + self._dss_separate_creds.client.auth_adapter.get_sub(), + ) + # Delete what we know about + self._clean_known_op_intents_ids() + # Search and attempt deleting what may be found through search + self._attempt_to_delete_remaining_op_intents() + + # We can't delete anything that would be left. + (stray_oir, q) = self._dss.find_op_intent(self._intents_extent) + self.record_query(q) + with self.check( + "Operational intent references can be searched using valid credentials", + self._pid, + ) as check: + if q.response.status_code != 200: + check.record_failed( + f"Could not search operational intent references using main credentials", + details=f"DSS responded with {q.response.status_code} to attempt to search OIs", + query_timestamps=[q.request.timestamp], + ) + + with self.check( + "Any existing operational intent reference has been removed", self._pid + ) as check: + if len(stray_oir) > 0: + check.record_failed( + f"Found operational intents that cannot be cleaned up", + details=f"Operational intents that cannot be cleaned up were found: {stray_oir}", + query_timestamps=[q.request.timestamp], + ) + return False + + return True + def _create_op_intents(self): (self._current_ref_1, subscribers1, q1) = self._dss.put_op_intent( id=self._oid_1, diff --git a/monitoring/uss_qualifier/suites/astm/utm/f3548_21.md b/monitoring/uss_qualifier/suites/astm/utm/f3548_21.md index c55bfae8f8..69f6505dd9 100644 --- a/monitoring/uss_qualifier/suites/astm/utm/f3548_21.md +++ b/monitoring/uss_qualifier/suites/astm/utm/f3548_21.md @@ -4,9 +4,9 @@ ## [Actions](../../README.md#actions) -1. Action generator: [`action_generators.astm.f3548.ForEachDSS`](../../../action_generators/astm/f3548/for_each_dss.py) +1. Scenario: [ASTM F3548 flight planners preparation](../../../scenarios/astm/utm/prep_planners.md) ([`scenarios.astm.utm.PrepareFlightPlanners`](../../../scenarios/astm/utm/prep_planners.py)) +2. Action generator: [`action_generators.astm.f3548.ForEachDSS`](../../../action_generators/astm/f3548/for_each_dss.py) 1. Suite: [DSS testing for ASTM NetRID F3548-21](dss_probing.md) ([`suites.astm.utm.dss_probing`](dss_probing.yaml)) -2. Scenario: [ASTM F3548 flight planners preparation](../../../scenarios/astm/utm/prep_planners.md) ([`scenarios.astm.utm.PrepareFlightPlanners`](../../../scenarios/astm/utm/prep_planners.py)) 3. Action generator: [`action_generators.flight_planning.FlightPlannerCombinations`](../../../action_generators/flight_planning/planner_combinations.py) 1. Scenario: [Validation of operational intents](../../../scenarios/astm/utm/flight_intent_validation/flight_intent_validation.md) ([`scenarios.astm.utm.FlightIntentValidation`](../../../scenarios/astm/utm/flight_intent_validation/flight_intent_validation.py)) 4. Action generator: [`action_generators.flight_planning.FlightPlannerCombinations`](../../../action_generators/flight_planning/planner_combinations.py) diff --git a/monitoring/uss_qualifier/suites/astm/utm/f3548_21.yaml b/monitoring/uss_qualifier/suites/astm/utm/f3548_21.yaml index 96fab43374..8e0f38809e 100644 --- a/monitoring/uss_qualifier/suites/astm/utm/f3548_21.yaml +++ b/monitoring/uss_qualifier/suites/astm/utm/f3548_21.yaml @@ -13,6 +13,17 @@ resources: mock_uss: resources.interuss.mock_uss.client.MockUSSResource? id_generator: resources.interuss.IDGeneratorResource actions: +- test_scenario: + scenario_type: scenarios.astm.utm.PrepareFlightPlanners + resources: + flight_planners: flight_planners + mock_uss: mock_uss + dss: dss + flight_intents: invalid_flight_intents + flight_intents2: priority_preemption_flights? + flight_intents3: conflicting_flights? + flight_intents4: non_conflicting_flights? + on_failure: Abort - action_generator: generator_type: action_generators.astm.f3548.ForEachDSS resources: @@ -34,17 +45,6 @@ actions: dss_instances_source: dss_instances dss_instance_id: dss on_failure: Continue -- test_scenario: - scenario_type: scenarios.astm.utm.PrepareFlightPlanners - resources: - flight_planners: flight_planners - mock_uss: mock_uss - dss: dss - flight_intents: invalid_flight_intents - flight_intents2: priority_preemption_flights? - flight_intents3: conflicting_flights? - flight_intents4: non_conflicting_flights? - on_failure: Abort - action_generator: generator_type: action_generators.flight_planning.FlightPlannerCombinations resources: