Commit 78037e73 authored by George Papathanail's avatar George Papathanail
Browse files

fix(ti): send a platform TI service specification id to SRM

SRM looks up a required traffic_influence capability requirement on the
activate command's service_specification_id. The app registration id OEG
sent only carries the workload requirement, so SRM rejected every TI.

Add TI_SETTINGS__SERVICE_SPECIFICATION_ID, defaulting to the well-known
id derived from "traffic-influence" (baba6a12-c7b6-507b-9805-5755d38131ee),
following the QoD and Location Retrieval pattern. Send it on activate and
use it as the SRM list filter; the appId filter stays on OEG's own records.
SRM must seed a spec at this id.
parent 512a573a
Loading
Loading
Loading
Loading
Loading
+1 −0
Changes for .env.example: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
# CALLBACK_SETTINGS__SECRET_KEY=""
# QOD_SETTINGS__SERVICE_SPECIFICATION_ID="7608e902-b927-559f-b448-e7e9061dfa5c"
# LOCATION_RETRIEVAL_SETTINGS__SERVICE_SPECIFICATION_ID="0129e7ce-8e02-5dfd-bae1-0303bcc7676e"
# TI_SETTINGS__SERVICE_SPECIFICATION_ID="baba6a12-c7b6-507b-9805-5755d38131ee"

# KEYCLOAK_SETTINGS__* default to a deliberately-unreachable `.invalid` host so a
# misconfigured deployment fails loudly instead of silently trusting the wrong
+5 −3
Changes for src/open_exposure_gateway/application/services/traffic_influence_service.py: 5 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ from open_exposure_gateway.application.mappers.traffic_influence_mapper import (
    build_traffic_influence_changed_event,
    build_traffic_influence_response,
)
from open_exposure_gateway.core.config import get_settings
from open_exposure_gateway.core.config import DEFAULT_TI_SERVICE_SPECIFICATION_ID, get_settings
from open_exposure_gateway.core.exceptions import (
    BadRequestException,
    ConflictException,
@@ -107,6 +107,7 @@ class TrafficInfluenceService:
        app_instance_repo: Optional[AppInstanceRepository] = None,
        callback_credential_repo: Optional[CallbackCredentialRepository] = None,
        callback_secret_key: Optional[bytes] = None,
        service_specification_id: UUID = DEFAULT_TI_SERVICE_SPECIFICATION_ID,
    ) -> None:
        self.srm_client = srm_client
        self._publisher = publisher
@@ -119,6 +120,7 @@ class TrafficInfluenceService:
        self._app_instance_repo = app_instance_repo
        self._callback_credential_repo = callback_credential_repo
        self._callback_secret_key = callback_secret_key
        self._service_specification_id = service_specification_id

    def _parse_traffic_influence_id(self, traffic_influence_id: str) -> UUID:
        try:
@@ -277,7 +279,7 @@ class TrafficInfluenceService:
            operation_id=operation_id,
            correlation_id=correlation_id,
            requested_at=requested_at,
            service_specification_id=app_registration_id,
            service_specification_id=self._service_specification_id,
            service_instance_id=traffic_influence_id,
            app_provider_id=app_provider_id,
            zone_id=zone_id,
@@ -788,7 +790,7 @@ class TrafficInfluenceService:
        try:
            capabilities = await self.srm_client.get_traffic_influences(
                app_provider_id=app_provider_id,
                service_specification_id=app_registration_id,
                service_specification_id=self._service_specification_id,
                x_correlator=x_correlator,
            )
            capabilities_by_id = {c.service_instance_id: c for c in capabilities}
+11 −0
Changes for src/open_exposure_gateway/core/config.py: 11 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@ DEFAULT_LOCATION_RETRIEVAL_SERVICE_SPECIFICATION_ID = well_known_service_specifi
    "location-context"
)

DEFAULT_TI_SERVICE_SPECIFICATION_ID = well_known_service_specification_id("traffic-influence")


class SRMSettings(BaseModel):
    base_url: HttpUrl = HttpUrl("http://localhost:8081")
@@ -105,6 +107,14 @@ class LocationRetrievalSettings(BaseModel):
        return self.service_specification_id == DEFAULT_LOCATION_RETRIEVAL_SERVICE_SPECIFICATION_ID


class TiSettings(BaseModel):
    service_specification_id: UUID = DEFAULT_TI_SERVICE_SPECIFICATION_ID

    @property
    def uses_default_service_specification_id(self) -> bool:
        return self.service_specification_id == DEFAULT_TI_SERVICE_SPECIFICATION_ID


class FmSettings(BaseModel):
    base_url: HttpUrl = HttpUrl("http://localhost:8082")
    timeout: float = 10.0
@@ -144,6 +154,7 @@ class Settings(BaseSettings):
    callback_settings: CallbackSettings = CallbackSettings()
    qod_settings: QodSettings = QodSettings()
    location_retrieval_settings: LocationRetrievalSettings = LocationRetrievalSettings()
    ti_settings: TiSettings = TiSettings()
    fm_settings: FmSettings = FmSettings()
    reconciliation_settings: ReconciliationSettings = ReconciliationSettings()

+1 −0
Changes for src/open_exposure_gateway/dependencies.py: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -363,4 +363,5 @@ def get_traffic_influence_service(
        app_instance_repo,
        callback_credential_repo=callback_credential_repo,
        callback_secret_key=get_settings().callback_settings.secret_key_bytes,
        service_specification_id=get_settings().ti_settings.service_specification_id,
    )
+14 −0
Changes for src/open_exposure_gateway/main.py: 14 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -336,6 +336,7 @@ def _build_traffic_influence_service(
        app_instance_repo=SqlAppInstanceRepository(session),
        callback_credential_repo=SqlCallbackCredentialRepository(session),
        callback_secret_key=get_settings().callback_settings.secret_key_bytes,
        service_specification_id=get_settings().ti_settings.service_specification_id,
    )


@@ -498,6 +499,19 @@ async def default_lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
            service_specification_id=str(location_retrieval_settings.service_specification_id),
        )

    ti_settings = settings.ti_settings
    if ti_settings.uses_default_service_specification_id:
        logger.warning(
            "ti_service_specification_id_defaulted",
            service_specification_id=str(ti_settings.service_specification_id),
            detail="TI_SETTINGS__SERVICE_SPECIFICATION_ID is unset; using a hardcoded id.",
        )
    else:
        logger.info(
            "ti_service_specification_id_configured",
            service_specification_id=str(ti_settings.service_specification_id),
        )

    if settings.callback_settings.secret_key is None:
        logger.warning(
            "callback_secret_key_unset",
Loading