From 48b2cb40e121cb65b3a79e926966710b9f39765e Mon Sep 17 00:00:00 2001 From: Landry Trebon Date: Thu, 15 May 2025 15:28:02 +0200 Subject: [PATCH 1/9] [client-python] WIP PIR api --- pycti/api/opencti_api_client.py | 2 ++ pycti/api/opencti_api_pir.py | 37 +++++++++++++++++++++++++++++++++ pycti/utils/opencti_stix2.py | 8 +++++++ 3 files changed, 47 insertions(+) create mode 100644 pycti/api/opencti_api_pir.py diff --git a/pycti/api/opencti_api_client.py b/pycti/api/opencti_api_client.py index bbde7d68..553328de 100644 --- a/pycti/api/opencti_api_client.py +++ b/pycti/api/opencti_api_client.py @@ -9,6 +9,7 @@ import requests from pycti import __version__ +from pycti.api.opencti_api_pir import OpenCTIApiPir from pycti.api.opencti_api_connector import OpenCTIApiConnector from pycti.api.opencti_api_playbook import OpenCTIApiPlaybook from pycti.api.opencti_api_work import OpenCTIApiWork @@ -170,6 +171,7 @@ def __init__( self.playbook = OpenCTIApiPlaybook(self) self.connector = OpenCTIApiConnector(self) self.stix2 = OpenCTIStix2(self) + self.pir = OpenCTIApiPir(self) # Define the entities self.vocabulary = Vocabulary(self) diff --git a/pycti/api/opencti_api_pir.py b/pycti/api/opencti_api_pir.py new file mode 100644 index 00000000..8b754a2b --- /dev/null +++ b/pycti/api/opencti_api_pir.py @@ -0,0 +1,37 @@ +class OpenCTIApiPir: + """OpenCTIApiPir""" + + def __init__(self, api): + self.api = api + + def add_pir_dependency(self, **kwargs): + id = kwargs.get("id", None) + input = kwargs.get("input", None) + query = """ + mutation PirAddDependency($id: ID!, $input: PirAddDependencyInput!) { + pirAddDependency(id: $id, input: $input) + } + """ + self.api.query( + query, + { + "id": id, + "input": input, + }, + ) + + def delete_pir_dependency(self, **kwargs): + id = kwargs.get("id", None) + input = kwargs.get("input", None) + query = """ + mutation PirDeleteDependency($id: ID!, $input: PirDeleteDependencyInput!) { + pirDeleteDependency(id: $id, input: $input) + } + """ + self.api.query( + query, + { + "id": id, + "input": input, + }, + ) \ No newline at end of file diff --git a/pycti/utils/opencti_stix2.py b/pycti/utils/opencti_stix2.py index a303844c..f4d1d82a 100644 --- a/pycti/utils/opencti_stix2.py +++ b/pycti/utils/opencti_stix2.py @@ -2484,6 +2484,14 @@ def apply_opencti_operation(self, item, operation): self.opencti.stix.merge(id=target_id, object_ids=source_ids) elif operation == "patch": self.apply_patch(item=item) + elif operation == "add_pir_dependency": + id = item["id"] + input = item["input"] + self.opencti.pir.add_pir_dependency(id=id, input=input) + elif operation == "delete_pir_dependency": + id = item["id"] + input = item["input"] + self.opencti.pir.delete_pir_dependency(id=id, input=input) else: raise ValueError("Not supported opencti_operation") From 2eb0f40bd25474070e945144a4765f9757c673d9 Mon Sep 17 00:00:00 2001 From: Cathia Archidoit Date: Thu, 15 May 2025 17:02:05 +0200 Subject: [PATCH 2/9] [client & backend] DEBUG LOGS --- pycti/utils/opencti_stix2.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pycti/utils/opencti_stix2.py b/pycti/utils/opencti_stix2.py index f4d1d82a..a8d7ea4d 100644 --- a/pycti/utils/opencti_stix2.py +++ b/pycti/utils/opencti_stix2.py @@ -2475,6 +2475,7 @@ def apply_patch(self, item): self.apply_patch_files(item) def apply_opencti_operation(self, item, operation): + self.opencti.app_logger.info("-- apply_opencti_opeartion --") if operation == "delete": delete_id = item["id"] self.opencti.stix.delete(id=delete_id) @@ -2485,6 +2486,7 @@ def apply_opencti_operation(self, item, operation): elif operation == "patch": self.apply_patch(item=item) elif operation == "add_pir_dependency": + self.opencti.app_logger.info("add_pir_dependency operation !!") id = item["id"] input = item["input"] self.opencti.pir.add_pir_dependency(id=id, input=input) @@ -2504,6 +2506,7 @@ def import_item( work_id: str = None, ): worker_logger = self.opencti.logger_class("worker") + self.opencti.app_logger.info("------import item----------") # Ultimate protection to avoid infinite retry if processing_count > MAX_PROCESSING_COUNT: if work_id is not None: @@ -2744,6 +2747,7 @@ def import_bundle( types: List = None, work_id: str = None, ) -> List: + self.opencti.app_logger.info("---import bundle------") # Check if the bundle is correctly formatted if "type" not in stix_bundle or stix_bundle["type"] != "bundle": raise ValueError("JSON data type is not a STIX2 bundle") @@ -2759,10 +2763,13 @@ def import_bundle( _, bundles = stix2_splitter.split_bundle_with_expectations( stix_bundle, False, event_version ) - # Import every element in a specific order + self.opencti.app_logger.info("---import bundle after splitter------", { "bundles": json.dumps(bundles) }) + # Import every element in a specific order imported_elements = [] for bundle in bundles: + self.opencti.app_logger.info("---bundle------") for item in bundle["objects"]: + self.opencti.app_logger.info("---item------", { "item": item["id"] }) self.import_item(item, update, types, 0, work_id) imported_elements.append({"id": item["id"], "type": item["type"]}) From 5765446a66f53481261d8c482b91342b2bb9aac1 Mon Sep 17 00:00:00 2001 From: Souad Hadjiat Date: Thu, 15 May 2025 17:59:45 +0200 Subject: [PATCH 3/9] [backend] add pir to supported types --- pycti/utils/opencti_stix2_splitter.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pycti/utils/opencti_stix2_splitter.py b/pycti/utils/opencti_stix2_splitter.py index 10a65590..5cc074c7 100644 --- a/pycti/utils/opencti_stix2_splitter.py +++ b/pycti/utils/opencti_stix2_splitter.py @@ -19,6 +19,7 @@ SUPPORTED_STIX_ENTITY_OBJECTS # entities + list(STIX_CYBER_OBSERVABLE_MAPPING.keys()) # observables + ["relationship", "sighting"] # relationships + + ["pir"] ) From 26d95e1034f1705d164aa7a70c32956ab6feb265 Mon Sep 17 00:00:00 2001 From: Cathia Archidoit Date: Fri, 16 May 2025 09:18:29 +0200 Subject: [PATCH 4/9] [client] fix --- pycti/api/opencti_api_pir.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pycti/api/opencti_api_pir.py b/pycti/api/opencti_api_pir.py index 8b754a2b..3472f755 100644 --- a/pycti/api/opencti_api_pir.py +++ b/pycti/api/opencti_api_pir.py @@ -8,7 +8,7 @@ def add_pir_dependency(self, **kwargs): id = kwargs.get("id", None) input = kwargs.get("input", None) query = """ - mutation PirAddDependency($id: ID!, $input: PirAddDependencyInput!) { + mutation PirAddDependency($id: ID!, $input: PirDependencyAddInput!) { pirAddDependency(id: $id, input: $input) } """ From 92c7cf9228d43f34fa7143f9564de4d73fad400f Mon Sep 17 00:00:00 2001 From: Landry Trebon Date: Fri, 16 May 2025 09:32:25 +0200 Subject: [PATCH 5/9] [client-python] remove logs --- pycti/utils/opencti_stix2.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pycti/utils/opencti_stix2.py b/pycti/utils/opencti_stix2.py index a8d7ea4d..eb0d5c96 100644 --- a/pycti/utils/opencti_stix2.py +++ b/pycti/utils/opencti_stix2.py @@ -2475,7 +2475,6 @@ def apply_patch(self, item): self.apply_patch_files(item) def apply_opencti_operation(self, item, operation): - self.opencti.app_logger.info("-- apply_opencti_opeartion --") if operation == "delete": delete_id = item["id"] self.opencti.stix.delete(id=delete_id) @@ -2486,7 +2485,6 @@ def apply_opencti_operation(self, item, operation): elif operation == "patch": self.apply_patch(item=item) elif operation == "add_pir_dependency": - self.opencti.app_logger.info("add_pir_dependency operation !!") id = item["id"] input = item["input"] self.opencti.pir.add_pir_dependency(id=id, input=input) @@ -2506,7 +2504,6 @@ def import_item( work_id: str = None, ): worker_logger = self.opencti.logger_class("worker") - self.opencti.app_logger.info("------import item----------") # Ultimate protection to avoid infinite retry if processing_count > MAX_PROCESSING_COUNT: if work_id is not None: @@ -2747,7 +2744,6 @@ def import_bundle( types: List = None, work_id: str = None, ) -> List: - self.opencti.app_logger.info("---import bundle------") # Check if the bundle is correctly formatted if "type" not in stix_bundle or stix_bundle["type"] != "bundle": raise ValueError("JSON data type is not a STIX2 bundle") @@ -2763,13 +2759,10 @@ def import_bundle( _, bundles = stix2_splitter.split_bundle_with_expectations( stix_bundle, False, event_version ) - self.opencti.app_logger.info("---import bundle after splitter------", { "bundles": json.dumps(bundles) }) # Import every element in a specific order imported_elements = [] for bundle in bundles: - self.opencti.app_logger.info("---bundle------") for item in bundle["objects"]: - self.opencti.app_logger.info("---item------", { "item": item["id"] }) self.import_item(item, update, types, 0, work_id) imported_elements.append({"id": item["id"], "type": item["type"]}) From d280dfb4e075f8e84b41ae9cf195c76458d5c092 Mon Sep 17 00:00:00 2001 From: Landry Trebon Date: Fri, 16 May 2025 09:34:33 +0200 Subject: [PATCH 6/9] [client-python] tab --- pycti/utils/opencti_stix2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pycti/utils/opencti_stix2.py b/pycti/utils/opencti_stix2.py index eb0d5c96..f4d1d82a 100644 --- a/pycti/utils/opencti_stix2.py +++ b/pycti/utils/opencti_stix2.py @@ -2759,7 +2759,7 @@ def import_bundle( _, bundles = stix2_splitter.split_bundle_with_expectations( stix_bundle, False, event_version ) - # Import every element in a specific order + # Import every element in a specific order imported_elements = [] for bundle in bundles: for item in bundle["objects"]: From 7f7b8ce898608ad99be3cc512cec15f464824a6e Mon Sep 17 00:00:00 2001 From: Cathia Archidoit Date: Fri, 16 May 2025 10:34:40 +0200 Subject: [PATCH 7/9] [client] fix --- pycti/api/opencti_api_pir.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pycti/api/opencti_api_pir.py b/pycti/api/opencti_api_pir.py index 3472f755..b7276561 100644 --- a/pycti/api/opencti_api_pir.py +++ b/pycti/api/opencti_api_pir.py @@ -8,7 +8,7 @@ def add_pir_dependency(self, **kwargs): id = kwargs.get("id", None) input = kwargs.get("input", None) query = """ - mutation PirAddDependency($id: ID!, $input: PirDependencyAddInput!) { + mutation PirAddDependency($id: ID!, $input: PIRDependencyAddInput!) { pirAddDependency(id: $id, input: $input) } """ From 161699d003f3b5c31caedbaae65ee4aff09d9889 Mon Sep 17 00:00:00 2001 From: Landry Trebon Date: Fri, 16 May 2025 11:21:57 +0200 Subject: [PATCH 8/9] [client] sort import --- pycti/api/opencti_api_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pycti/api/opencti_api_client.py b/pycti/api/opencti_api_client.py index 553328de..ee0b2a44 100644 --- a/pycti/api/opencti_api_client.py +++ b/pycti/api/opencti_api_client.py @@ -9,8 +9,8 @@ import requests from pycti import __version__ -from pycti.api.opencti_api_pir import OpenCTIApiPir from pycti.api.opencti_api_connector import OpenCTIApiConnector +from pycti.api.opencti_api_pir import OpenCTIApiPir from pycti.api.opencti_api_playbook import OpenCTIApiPlaybook from pycti.api.opencti_api_work import OpenCTIApiWork from pycti.entities.opencti_attack_pattern import AttackPattern From 89365066ad0c11c1ecc7eeeff8afe7988a9c1147 Mon Sep 17 00:00:00 2001 From: Landry Trebon Date: Fri, 16 May 2025 11:30:25 +0200 Subject: [PATCH 9/9] [client] fix format --- pycti/api/opencti_api_pir.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pycti/api/opencti_api_pir.py b/pycti/api/opencti_api_pir.py index b7276561..1c6b9fab 100644 --- a/pycti/api/opencti_api_pir.py +++ b/pycti/api/opencti_api_pir.py @@ -34,4 +34,4 @@ def delete_pir_dependency(self, **kwargs): "id": id, "input": input, }, - ) \ No newline at end of file + )