From 2c7d7c74a4afe731398e090089ff1dd3ba981c39 Mon Sep 17 00:00:00 2001 From: mmolenda Date: Fri, 20 Jun 2025 17:20:57 +0200 Subject: [PATCH 1/3] STIX: mapping inforep reliability --- README.md | 2 +- setup.py | 4 ++-- test/fixtures/report_inforep_stix.json | 3 ++- titan_client/__init__.py | 2 +- titan_client/api_client.py | 2 +- titan_client/titan_stix/mappers/common.py | 1 + titan_client/titan_stix/mappers/reports.py | 16 ++++++++++++++++ 7 files changed, 24 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a4fac4b..5443550 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Official low-level client for Intel 471's Titan API. It aims at providing common This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: - API version: 1.20.0 -- Package version: 1.20.0.12 +- Package version: 1.20.0.13 - Build package: org.openapitools.codegen.languages.PythonLegacyClientCodegen ## Requirements. diff --git a/setup.py b/setup.py index 2ac79a2..5da095b 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ Official low-level client for Intel 471's Titan API. It aims at providing common ground for all the endpoints in Python. - The version of the OpenAPI document: 1.20.0.12 + The version of the OpenAPI document: 1.20.0.13 Generated by: https://openapi-generator.tech """ @@ -13,7 +13,7 @@ from setuptools import setup, find_packages # noqa: H301 NAME = "Titan Client" -VERSION = "1.20.0.12" +VERSION = "1.20.0.13" # To install the library, run the following # # python setup.py install diff --git a/test/fixtures/report_inforep_stix.json b/test/fixtures/report_inforep_stix.json index 14424bc..380b423 100644 --- a/test/fixtures/report_inforep_stix.json +++ b/test/fixtures/report_inforep_stix.json @@ -75,7 +75,8 @@ "marking-definition--f88d31f6-486f-44da-b317-01333bde0b82" ], "content": "

Source Characterization

\nLorem ipsum", - "x_intel471_com_uid": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "x_intel471_com_uid": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "x_opencti_reliability": "C - Fairly reliable" } ] } \ No newline at end of file diff --git a/titan_client/__init__.py b/titan_client/__init__.py index 5d2dfea..3132028 100644 --- a/titan_client/__init__.py +++ b/titan_client/__init__.py @@ -14,7 +14,7 @@ from __future__ import absolute_import -__version__ = "1.20.0.12" +__version__ = "1.20.0.13" # import apis into sdk package from titan_client.api.actors_api import ActorsApi diff --git a/titan_client/api_client.py b/titan_client/api_client.py index e414353..bf4a41c 100644 --- a/titan_client/api_client.py +++ b/titan_client/api_client.py @@ -78,7 +78,7 @@ def __init__(self, configuration=None, header_name=None, header_value=None, self.default_headers[header_name] = header_value self.cookie = cookie # Set default User-Agent. - self.user_agent = 'OpenAPI-Generator/1.20.0.12/python' + self.user_agent = 'OpenAPI-Generator/1.20.0.13/python' self.client_side_validation = configuration.client_side_validation def __enter__(self): diff --git a/titan_client/titan_stix/mappers/common.py b/titan_client/titan_stix/mappers/common.py index 19ab483..f0ac720 100644 --- a/titan_client/titan_stix/mappers/common.py +++ b/titan_client/titan_stix/mappers/common.py @@ -134,6 +134,7 @@ def map_confidence(self, confidence: Union[str, None]): def map_tactic(self, tactic: str): if tactic and len(tactic) > 0: return tactic.replace("_", "-").replace(" ", "-").lower() + return None @staticmethod def shorten(text: str, limit: int) -> str: diff --git a/titan_client/titan_stix/mappers/reports.py b/titan_client/titan_stix/mappers/reports.py index b9831c4..bcfe869 100644 --- a/titan_client/titan_stix/mappers/reports.py +++ b/titan_client/titan_stix/mappers/reports.py @@ -256,6 +256,9 @@ def _map_report(self, source: dict, object_refs: StixObjects = None) -> StixObje "content": self._get_opencti_content(source) } } + if report_type == ReportType.INFOREP: + if source_reliability := self._map_source_reliability(source.get("admiraltyCode")): + report_kwargs["custom_properties"]["x_opencti_reliability"] = source_reliability report = Report(**report_kwargs) stix_objects.add(report) return stix_objects @@ -390,3 +393,16 @@ def _get_opencti_content(self, source: dict): content_bits.append(f"

{heading}

") content_bits.append(value) return "\n".join(content_bits) + + def _map_source_reliability(self, admiralty_code: Union[str, None]): + if admiralty_code and len(admiralty_code) > 0: + reliability_code = admiralty_code[0].upper() + return { + "A": "A - Completely reliable", + "B": "B - Usually reliable", + "C": "C - Fairly reliable", + "D": "D - Not usually reliable", + "E": "E - Unreliable", + "F": "F - Reliability cannot be judged" + }.get(reliability_code) + return None \ No newline at end of file From 4ecb13580c944248ac7ed539d98efd6b0f32d6a6 Mon Sep 17 00:00:00 2001 From: mmolenda Date: Wed, 13 Aug 2025 15:32:45 +0200 Subject: [PATCH 2/3] Catch ValueError in stix entities mapper --- titan_client/titan_stix/mappers/entities.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/titan_client/titan_stix/mappers/entities.py b/titan_client/titan_stix/mappers/entities.py index a7be16f..e11df47 100644 --- a/titan_client/titan_stix/mappers/entities.py +++ b/titan_client/titan_stix/mappers/entities.py @@ -57,7 +57,7 @@ def map(self, type: str, value: str, *args, **kwargs): # noqa need `type` here value = value_extractor(value) try: return mapper_config.mapper(value, type=type, *args, **kwargs) - except InvalidValueError as e: + except (InvalidValueError, ValueError) as e: log.info(f"Skipping entity. {e}") return log.info(f"Skipping entity. No suitable mapper. type=`{type}` value=`{value}`") From cf05c768ba2afdfbb37ea5df9632dfd5573fed7d Mon Sep 17 00:00:00 2001 From: mmolenda Date: Wed, 13 Aug 2025 16:00:07 +0200 Subject: [PATCH 3/3] make rawText field in reports optional --- docs/FullReportSchema.md | 2 +- docs/FullReportSchemaAllOf.md | 2 +- titan_client/configuration.py | 2 +- titan_client/models/full_report_schema.py | 5 ++--- titan_client/models/full_report_schema_all_of.py | 5 ++--- 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/docs/FullReportSchema.md b/docs/FullReportSchema.md index 5aa17f8..f7277de 100644 --- a/docs/FullReportSchema.md +++ b/docs/FullReportSchema.md @@ -28,7 +28,7 @@ Name | Type | Description | Notes **uid** | **str** | Unique report identifier. | **victims** | [**list[SimpleReportSchemaVictimsInner]**](SimpleReportSchemaVictimsInner.md) | Purported victims list. | [optional] **executive_summary** | **str** | Executive summary in HTML format. | [optional] -**raw_text** | **str** | Raw text in HTML format. | +**raw_text** | **str** | Raw text in HTML format. | [optional] **raw_text_translated** | **str** | Translated text in HTML format. | [optional] **researcher_comments** | **str** | Researcher's comments in HTML format. | [optional] diff --git a/docs/FullReportSchemaAllOf.md b/docs/FullReportSchemaAllOf.md index 975094b..86d62d7 100644 --- a/docs/FullReportSchemaAllOf.md +++ b/docs/FullReportSchemaAllOf.md @@ -5,7 +5,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **executive_summary** | **str** | Executive summary in HTML format. | [optional] -**raw_text** | **str** | Raw text in HTML format. | +**raw_text** | **str** | Raw text in HTML format. | [optional] **raw_text_translated** | **str** | Translated text in HTML format. | [optional] **researcher_comments** | **str** | Researcher's comments in HTML format. | [optional] diff --git a/titan_client/configuration.py b/titan_client/configuration.py index c503d60..3e203f9 100644 --- a/titan_client/configuration.py +++ b/titan_client/configuration.py @@ -409,7 +409,7 @@ def to_debug_report(self): "OS: {env}\n"\ "Python Version: {pyversion}\n"\ "Version of the API: 1.20.0\n"\ - "SDK Package Version: 10".\ + "SDK Package Version: 1.20.0.13".\ format(env=sys.platform, pyversion=sys.version) def get_host_settings(self): diff --git a/titan_client/models/full_report_schema.py b/titan_client/models/full_report_schema.py index e512520..79b2d70 100644 --- a/titan_client/models/full_report_schema.py +++ b/titan_client/models/full_report_schema.py @@ -177,7 +177,8 @@ def __init__(self, actor_handle=None, actor_subject_of_report=None, admiralty_co self.victims = victims if executive_summary is not None: self.executive_summary = executive_summary - self.raw_text = raw_text + if raw_text is not None: + self.raw_text = raw_text if raw_text_translated is not None: self.raw_text_translated = raw_text_translated if researcher_comments is not None: @@ -762,8 +763,6 @@ def raw_text(self, raw_text): :param raw_text: The raw_text of this FullReportSchema. # noqa: E501 :type raw_text: str """ - if self.local_vars_configuration.client_side_validation and raw_text is None: # noqa: E501 - raise ValueError("Invalid value for `raw_text`, must not be `None`") # noqa: E501 self._raw_text = raw_text diff --git a/titan_client/models/full_report_schema_all_of.py b/titan_client/models/full_report_schema_all_of.py index f61c250..fa2fb6a 100644 --- a/titan_client/models/full_report_schema_all_of.py +++ b/titan_client/models/full_report_schema_all_of.py @@ -65,7 +65,8 @@ def __init__(self, executive_summary=None, raw_text=None, raw_text_translated=No if executive_summary is not None: self.executive_summary = executive_summary - self.raw_text = raw_text + if raw_text is not None: + self.raw_text = raw_text if raw_text_translated is not None: self.raw_text_translated = raw_text_translated if researcher_comments is not None: @@ -114,8 +115,6 @@ def raw_text(self, raw_text): :param raw_text: The raw_text of this FullReportSchemaAllOf. # noqa: E501 :type raw_text: str """ - if self.local_vars_configuration.client_side_validation and raw_text is None: # noqa: E501 - raise ValueError("Invalid value for `raw_text`, must not be `None`") # noqa: E501 self._raw_text = raw_text