Skip to content

Commit

Permalink
[uss_qualifier] first DSS op-intents ACL validation (#396)
Browse files Browse the repository at this point in the history
OPIN0035 access control for op intents
  • Loading branch information
Shastick authored Dec 12, 2023
1 parent be006f5 commit 5dadffb
Show file tree
Hide file tree
Showing 22 changed files with 719 additions and 16 deletions.
2 changes: 1 addition & 1 deletion monitoring/prober/infrastructure.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def wrapper_default_scope(*args, **kwargs):
resource_type_code_descriptions: Dict[ResourceType, str] = {}


# Next code: 375
# Next code: 377
def register_resource_type(code: int, description: str) -> ResourceType:
"""Register that the specified code refers to the described resource.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ v1:

# Mapping of <resource name in test suite> to <resource name in resource pool>
resources:
id_generator: id_generator
flight_planners: flight_planners
conflicting_flights: conflicting_flights
invalid_flight_intents: invalid_flight_intents
non_conflicting_flights: non_conflicting_flights
dss: dss
dss_instances: dss_instances
mock_uss: mock_uss
second_utm_auth: second_utm_auth

# This block defines all the resources available in the resource pool.
# Presumably all resources defined below would be used either
Expand All @@ -35,6 +37,30 @@ v1:
# To avoid putting secrets in configuration files, the auth spec (including sensitive information) will be read from the AUTH_SPEC environment variable
environment_variable_containing_auth_spec: AUTH_SPEC

# Means by which uss_qualifier can discover which subscription ('sub' claim of its tokes) it is described by
utm_client_identity:
resource_type: resources.communications.ClientIdentityResource
dependencies:
auth_adapter: utm_auth
specification:
# Audience and scope to be used to issue a dummy query, should it be required to discover the subscription
whoami_audience: localhost
whoami_scope: rid.display_provider

# Means by which uss_qualifier generates identifiers
id_generator:
$content_schema: monitoring/uss_qualifier/resources/definitions/ResourceDeclaration.json
resource_type: resources.interuss.IDGeneratorResource
dependencies:
client_identity: utm_client_identity

# A second auth adapter, for checks that require a second set of credentials for accessing the ecosystem.
# Note that the 'sub' claim of the tokens obtained through this adepter MUST be different from the first auth adapter.
second_utm_auth:
resource_type: resources.communications.AuthAdapterResource
specification:
environment_variable_containing_auth_spec: AUTH_SPEC_2

# Set of USSs capable of being tested as flight planners
flight_planners:
resource_type: resources.flight_planning.FlightPlannersResource
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ utm_auth:
specification:
environment_variable_containing_auth_spec: AUTH_SPEC

second_utm_auth:
$content_schema: monitoring/uss_qualifier/resources/definitions/ResourceDeclaration.json
resource_type: resources.communications.AuthAdapterResource
specification:
environment_variable_containing_auth_spec: AUTH_SPEC_2

utm_client_identity:
$content_schema: monitoring/uss_qualifier/resources/definitions/ResourceDeclaration.json
resource_type: resources.communications.ClientIdentityResource
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ utm_auth:
specification:
environment_variable_containing_auth_spec: AUTH_SPEC

second_utm_auth:
$content_schema: monitoring/uss_qualifier/resources/definitions/ResourceDeclaration.json
resource_type: resources.communications.AuthAdapterResource
specification:
environment_variable_containing_auth_spec: AUTH_SPEC_2

utm_client_identity:
$content_schema: monitoring/uss_qualifier/resources/definitions/ResourceDeclaration.json
resource_type: resources.communications.ClientIdentityResource
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ v1:
mock_uss: 1

utm_auth: {$ref: 'library/environment.yaml#/utm_auth'}
second_utm_auth: {$ref: 'library/environment.yaml#/second_utm_auth'}
utm_client_identity: {$ref: 'library/resources.yaml#/utm_client_identity'}
id_generator: {$ref: 'library/resources.yaml#/id_generator'}
scd_dss: {$ref: 'library/environment.yaml#/scd_dss'}
scd_dss_instances: {$ref: 'library/environment.yaml#/scd_dss_instances'}
flight_planners:
Expand Down Expand Up @@ -53,6 +56,8 @@ v1:
priority_preemption_flights: che_conflicting_flights
dss: scd_dss
dss_instances: scd_dss_instances
id_generator: id_generator
second_utm_auth: second_utm_auth
execution:
stop_fast: true

Expand Down
3 changes: 3 additions & 0 deletions monitoring/uss_qualifier/configurations/dev/uspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ v1:
au_problematically_big_area: {$ref: 'library/resources.yaml#/au_problematically_big_area'}

utm_auth: {$ref: 'library/environment.yaml#/utm_auth'}
second_utm_auth: {$ref: 'library/environment.yaml#/second_utm_auth'}
mock_uss_instances_scdsc: {$ref: 'library/environment.yaml#/mock_uss_instances_scdsc'}
mock_uss_instance_uss6: {$ref: 'library/environment.yaml#/mock_uss_instance_uss6'}
scd_version_providers: {$ref: 'library/environment.yaml#/scd_version_providers'}
Expand Down Expand Up @@ -61,6 +62,7 @@ v1:
evaluation_configuration: netrid_observation_evaluation_configuration
netrid_dss_instances: netrid_dss_instances_v22a
utm_client_identity: utm_client_identity
second_utm_auth: second_utm_auth
id_generator: id_generator
service_area: kentland_service_area
problematically_big_area: au_problematically_big_area
Expand Down Expand Up @@ -89,6 +91,7 @@ v1:
evaluation_configuration: evaluation_configuration
netrid_dss_instances: netrid_dss_instances
utm_client_identity: utm_client_identity
second_utm_auth: second_utm_auth
id_generator: id_generator
service_area: service_area
problematically_big_area: problematically_big_area
Expand Down
37 changes: 34 additions & 3 deletions monitoring/uss_qualifier/resources/astm/f3548/v21/dss.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,14 @@
SetUssAvailabilityStatusParameters,
UssAvailabilityState,
UssAvailabilityStatusResponse,
GetOperationalIntentReferenceResponse,
)

# A base URL for a USS that is not expected to be ever called
# Used in scenarios where we mimic the behavior of a USS and need to provide a base URL.
# As the area used for tests is cleared before the tests, there is no need to have this URL be reachable.
DUMMY_USS_BASE_URL = "https://dummy.uss"


class DSSInstanceSpecification(ImplicitDict):
participant_id: str
Expand Down Expand Up @@ -90,6 +96,30 @@ def find_op_intent(
).operational_intent_references
return result, query

def get_op_intent_reference(
self,
op_intent_id: str,
) -> Tuple[OperationalIntentReference, fetch.Query]:
"""
Retrieve an OP Intent from the DSS, using only its ID
"""
url = f"/dss/v1/operational_intent_references/{op_intent_id}"
query = fetch.query_and_describe(
self.client,
"GET",
url,
QueryType.F3548v21DSSGetOperationalIntentReference,
self.participant_id,
scope=SCOPE_SC,
)
if query.status_code != 200:
result = None
else:
result = ImplicitDict.parse(
query.response.json, GetOperationalIntentReferenceResponse
).operational_intent_reference
return result, query

def get_full_op_intent(
self,
op_intent_ref: OperationalIntentReference,
Expand Down Expand Up @@ -125,11 +155,12 @@ def put_op_intent(
Optional[List[SubscriberToNotify]],
fetch.Query,
]:
if id is None:
url = f"/dss/v1/operational_intent_references/{str(uuid.uuid4())}"
oi_uuid = str(uuid.uuid4()) if id is None else id
if ovn is None:
url = f"/dss/v1/operational_intent_references/{oi_uuid}"
query_type = QueryType.F3548v21DSSCreateOperationalIntentReference
else:
url = f"/dss/v1/operational_intent_references/{id}/{ovn}"
url = f"/dss/v1/operational_intent_references/{oi_uuid}/{ovn}"
query_type = QueryType.F3548v21DSSUpdateOperationalIntentReference

req = PutOperationalIntentReferenceParameters(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
from typing import Dict
from typing import Dict, List

import arrow
from implicitdict import ImplicitDict
from uas_standards.astm.f3548.v21.api import OperationalIntentState

from monitoring.monitorlib.clients.flight_planning.flight_info_template import (
FlightInfoTemplate,
)
from monitoring.monitorlib.geotemporal import Volume4DCollection

from monitoring.uss_qualifier.resources.files import load_dict
from monitoring.uss_qualifier.resources.resource import Resource
from monitoring.uss_qualifier.resources.flight_planning.flight_intent import (
FlightIntentCollection,
FlightIntentsSpecification,
FlightIntentID,
FlightIntent,
)


Expand Down Expand Up @@ -39,3 +44,27 @@ def __init__(self, specification: FlightIntentsSpecification):

def get_flight_intents(self) -> Dict[FlightIntentID, FlightInfoTemplate]:
return self._intent_collection.resolve()


def unpack_flight_intents(
flight_intents: FlightIntentsResource, flight_identifiers: List[str]
):
"""
Extracts the specified flight identifiers from the passed FlightIntentsResource
"""
flight_intents = {
k: FlightIntent.from_flight_info_template(v)
for k, v in flight_intents.get_flight_intents().items()
if k in flight_identifiers
}

extents = []
for intent in flight_intents.values():
extents.extend(intent.request.operational_intent.volumes)
extents.extend(intent.request.operational_intent.off_nominal_volumes)

intents_extent = Volume4DCollection.from_interuss_scd_api(
extents
).bounding_volume.to_f3548v21()

return intents_extent, flight_intents
2 changes: 2 additions & 0 deletions monitoring/uss_qualifier/run_locally.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ echo "Running configuration(s): ${CONFIG_NAME}"
CONFIG_FLAG="--config ${CONFIG_NAME}"

AUTH_SPEC='DummyOAuth(http://oauth.authority.localutm:8085/token,uss_qualifier)'
AUTH_SPEC_2='DummyOAuth(http://oauth.authority.localutm:8085/token,uss_qualifier_2)'

QUALIFIER_OPTIONS="$CONFIG_FLAG $OTHER_ARGS"

Expand All @@ -66,6 +67,7 @@ docker run ${docker_args} --name uss_qualifier \
-u "$(id -u):$(id -g)" \
-e PYTHONBUFFERED=1 \
-e AUTH_SPEC=${AUTH_SPEC} \
-e AUTH_SPEC_2=${AUTH_SPEC_2} \
-e MONITORING_GITHUB_ROOT=${MONITORING_GITHUB_ROOT:-} \
-v "$(pwd)/$OUTPUT_DIR:/app/$OUTPUT_DIR" \
-v "$(pwd)/$CACHE_DIR:/app/$CACHE_DIR" \
Expand Down
1 change: 1 addition & 0 deletions monitoring/uss_qualifier/scenarios/astm/utm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
from .off_nominal_planning.down_uss_equal_priority_not_permitted import (
DownUSSEqualPriorityNotPermitted,
)
from .op_intent_access_control import OpIntentAccessControl
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# ASTM F3548-21 UTM DSS Operational Intent Access Control test scenario

## Overview

This scenario ensures that a DSS will only let the owner of an operational intent modify it.

## Resources

### flight_intents

A `resources.flight_planning.FlightIntentsResource` containing the flight intents to be used in this scenario:

This scenario expects to find at least two separate flight intents in this resource, as it will use their extent
to create two operational intents.

### dss

A `resources.astm.f3548.v21.DSSInstanceResource` pointing to the DSS instance to test for this scenario.

### second_utm_auth

A `resources.communications.AuthAdapterResource` containing a second set of valid credentials for interacting with the DSS.

This second set of credentials is required to validate that the DSS is properly enforcing access control rules, and properly limits the actions of a client against
the resources exposed by the DSS.

The participant under test is responsible for providing this second set of credentials along the primary ones used in most other scenarios.

#### Credential requirements

In general, these test credentials may be in all points equal to the ones used by the `AuthAdapterResource` that is
provided to the `dss` resources above, except for the value contained in the `sub` claim of the token.

For the purpose of this scenario, these credentials must be allowed to create, modify and delete operational intents on the DSS,
as well as querying operational intent references.

##### Required scope

For the purpose of this scenario, the `second_utm_auth` resource must provide access to a token with at least the following scope:

* `utm.strategic_coordination`

##### Separate subscription

Note that the subscription (or 'sub' claim) of the token that will be obtained for this resource
MUST be different from the one of the `dss` resources mentioned above:
this will be verified at runtime, and this scenario will fail if the second set of credentials belong to the same subscription as the main one.

### id_generator

A `resources.interuss.IDGeneratorResource` that will be used to generate the IDs of the operational intents created in this scenario.

## Setup test case

Makes sure that the DSS is in a clean and expected state before running the test, and that the passed resources work as required.

The setup will create two separate operational intents: one for each set of the available credentials.

### Ensure clean workspace test step

#### Operational intents can be queried directly by their ID check

If an existing operational intent cannot directly be queried by its ID, the DSS implementation is in violation of
**[astm.f3548.v21.DSS0005](../../../requirements/astm/f3548/v21.md)**.

#### Operational intents can be searched using valid credentials check

A client with valid credentials should be allowed to search for operational intents in a given area.
Otherwise, the DSS is not in compliance with **[astm.f3548.v21.DSS0005](../../../requirements/astm/f3548/v21.md)**.

#### Operational intents can be deleted by their owner check

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](../../../requirements/astm/f3548/v21.md)**.

### Create operational intents with different credentials test step

This test step ensures that an operation intent created with the main credentials is available for the main test case.

To verify that the second credentials are valid, it will also create an operational intent with those credentials.

#### Can create an operational intent with valid credentials check

If the DSS does not allow the creation of operation intents when the required parameters and credentials are provided,
it is in violation of **[astm.f3548.v21.DSS0005](../../../requirements/astm/f3548/v21.md)**.

#### Passed sets of credentials are different check

This scenario requires two sets of credentials that have a different 'sub' claim in order to validate that the
DSS properly controls access to operational intents.

## Attempt unauthorized flight intent modification test case

This test case ensures that the DSS does not allow a caller to modify or delete operational intent that they did not create.

### Attempt unauthorized flight intent modification test step

This test step will attempt to modify the operational intent that was created using the configured `dss` resource,
using the credentials provided in the `second_utm_auth` resource, and expect all such attempts to fail.

#### Operational intents can be queried directly by their ID check

If an existing operational intent cannot directly be queried by its ID, the DSS implementation is in violation of
**[astm.f3548.v21.DSS0005](../../../requirements/astm/f3548/v21.md)**.

#### Non-owning credentials cannot modify operational intent check

If an operational intent can be modified by a client which did not create it, the DSS implementation is
in violation of **[astm.f3548.v21.OPIN0035](../../../requirements/astm/f3548/v21.md)**.

#### Non-owning credentials cannot delete operational intent check

If an operational intent can be deleted by a client which did not create it, the DSS implementation is
in violation of **[astm.f3548.v21.OPIN0035](../../../requirements/astm/f3548/v21.md)**.

## Cleanup

### Operational intents can be queried directly by their ID check

If an existing operational intent cannot directly be queried by its ID, the DSS implementation is in violation of
**[astm.f3548.v21.DSS0005](../../../requirements/astm/f3548/v21.md)**.

### Operational intents can be deleted by their owner check

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](../../../requirements/astm/f3548/v21.md)**.
Loading

0 comments on commit 5dadffb

Please sign in to comment.