From d2ce9cb6de57ebb847bc6f9d64d2c14e8b5b5622 Mon Sep 17 00:00:00 2001 From: Jeremy Cloarec Date: Fri, 13 Jun 2025 16:52:01 +0200 Subject: [PATCH 1/2] [client] add remove from draft/share/unshare methods for sightings and relationships --- .../opencti_stix_core_relationship.py | 85 +++++++++++++++++++ .../opencti_stix_sighting_relationship.py | 85 +++++++++++++++++++ pycti/utils/opencti_stix2.py | 44 ++++++++-- 3 files changed, 207 insertions(+), 7 deletions(-) diff --git a/pycti/entities/opencti_stix_core_relationship.py b/pycti/entities/opencti_stix_core_relationship.py index d47609ab0..8ae4f1bc8 100644 --- a/pycti/entities/opencti_stix_core_relationship.py +++ b/pycti/entities/opencti_stix_core_relationship.py @@ -1247,3 +1247,88 @@ def import_from_stix2(self, **kwargs): self.opencti.app_logger.error( "[opencti_stix_core_relationship] Missing parameters: stixObject" ) + + +""" + Share element to multiple organizations + + :param entity_id: the stix_core_relationship id + :param organization_id:s the organization to share with + :return void + """ + + +def organization_share(self, entity_id, organization_ids, sharing_direct_container): + query = """ + mutation StixCoreRelationshipEdit($id: ID!, $organizationId: [ID!]!, $directContainerSharing: Boolean) { + stixCoreRelationshipEdit(id: $id) { + restrictionOrganizationAdd(organizationId: $organizationId, directContainerSharing: $directContainerSharing) { + id + } + } + } + """ + self.opencti.query( + query, + { + "id": entity_id, + "organizationId": organization_ids, + "directContainerSharing": sharing_direct_container, + }, + ) + + +""" + Unshare element from multiple organizations + + :param entity_id: the stix_core_relationship id + :param organization_id:s the organization to share with + :return void +""" + + +def organization_unshare(self, entity_id, organization_ids, sharing_direct_container): + query = """ + mutation StixCoreRelationshipEdit($id: ID!, $organizationId: [ID!]!, $directContainerSharing: Boolean) { + stixCoreRelationshipEdit(id: $id) { + restrictionOrganizationDelete(organizationId: $organizationId, directContainerSharing: $directContainerSharing) { + id + } + } + } + """ + self.opencti.query( + query, + { + "id": entity_id, + "organizationId": organization_ids, + "directContainerSharing": sharing_direct_container, + }, + ) + + +""" + Remove a stix_core_relationship object from draft (revert) + + :param id: the stix_core_relationship id + :return void + """ + + +def remove_from_draft(self, **kwargs): + id = kwargs.get("id", None) + if id is not None: + self.opencti.app_logger.info("Draft remove stix_core_relationship", {"id": id}) + query = """ + mutation StixCoreRelationshipEditDraftRemove($id: ID!) { + stixCoreRelationshipEdit(id: $id) { + removeFromDraft + } + } + """ + self.opencti.query(query, {"id": id}) + else: + self.opencti.app_logger.error( + "[stix_core_relationship] Cant remove from draft, missing parameters: id" + ) + return None diff --git a/pycti/entities/opencti_stix_sighting_relationship.py b/pycti/entities/opencti_stix_sighting_relationship.py index 8d4f5bfa1..397a15ae7 100644 --- a/pycti/entities/opencti_stix_sighting_relationship.py +++ b/pycti/entities/opencti_stix_sighting_relationship.py @@ -802,6 +802,91 @@ def update_created_by(self, **kwargs): self.opencti.app_logger.error("Missing parameters: id") return False + +""" + Share element to multiple organizations + + :param entity_id: the stix_sighting id + :param organization_id:s the organization to share with + :return void + """ + + +def organization_share(self, entity_id, organization_ids, sharing_direct_container): + query = """ + mutation StixSightingRelationshipEdit($id: ID!, $organizationId: [ID!]!, $directContainerSharing: Boolean) { + stixSightingRelationshipEdit(id: $id) { + restrictionOrganizationAdd(organizationId: $organizationId, directContainerSharing: $directContainerSharing) { + id + } + } + } + """ + self.opencti.query( + query, + { + "id": entity_id, + "organizationId": organization_ids, + "directContainerSharing": sharing_direct_container, + }, + ) + + +""" + Unshare element from multiple organizations + + :param entity_id: the stix_sighting id + :param organization_id:s the organization to share with + :return void +""" + + +def organization_unshare(self, entity_id, organization_ids, sharing_direct_container): + query = """ + mutation StixSightingRelationshipEdit($id: ID!, $organizationId: [ID!]!, $directContainerSharing: Boolean) { + stixSightingRelationshipEdit(id: $id) { + restrictionOrganizationDelete(organizationId: $organizationId, directContainerSharing: $directContainerSharing) { + id + } + } + } + """ + self.opencti.query( + query, + { + "id": entity_id, + "organizationId": organization_ids, + "directContainerSharing": sharing_direct_container, + }, + ) + + +""" + Remove a stix_sighting object from draft (revert) + + :param id: the stix_sighting id + :return void + """ + + +def remove_from_draft(self, **kwargs): + id = kwargs.get("id", None) + if id is not None: + self.opencti.app_logger.info("Draft remove stix_sighting", {"id": id}) + query = """ + mutation StixSightingRelationshipEditDraftRemove($id: ID!) { + stixSightingRelationshipEdit(id: $id) { + removeFromDraft + } + } + """ + self.opencti.query(query, {"id": id}) + else: + self.opencti.app_logger.error( + "[stix_sighting] Cant remove from draft, missing parameters: id" + ) + return None + """ Delete a stix_sighting diff --git a/pycti/utils/opencti_stix2.py b/pycti/utils/opencti_stix2.py index 7ae903dfe..d2d5a6ffc 100644 --- a/pycti/utils/opencti_stix2.py +++ b/pycti/utils/opencti_stix2.py @@ -2522,9 +2522,20 @@ def organization_share(self, item): ) if sharing_direct_container is None: sharing_direct_container = item["sharing_direct_container"] - self.opencti.stix_core_object.organization_share( - item["id"], organization_ids, sharing_direct_container - ) + + if item["type"] == "relationship": + self.opencti.stix_core_relationship.organization_share( + item["id"], organization_ids, sharing_direct_container + ) + elif item["type"] == "sighting": + self.opencti.stix_sighting_relationship.organization_share( + item["id"], organization_ids, sharing_direct_container + ) + else: + # Element is considered stix core object + self.opencti.stix_core_object.organization_share( + item["id"], organization_ids, sharing_direct_container + ) def organization_unshare(self, item): organization_ids = self.opencti.get_attribute_in_extension( @@ -2537,9 +2548,19 @@ def organization_unshare(self, item): ) if sharing_direct_container is None: sharing_direct_container = item["sharing_direct_container"] - self.opencti.stix_core_object.organization_unshare( - item["id"], organization_ids, sharing_direct_container - ) + if item["type"] == "relationship": + self.opencti.stix_core_relationship.organization_unshare( + item["id"], organization_ids, sharing_direct_container + ) + elif item["type"] == "sighting": + self.opencti.stix_sighting_relationship.organization_unshare( + item["id"], organization_ids, sharing_direct_container + ) + else: + # Element is considered stix core object + self.opencti.stix_core_object.organization_unshare( + item["id"], organization_ids, sharing_direct_container + ) def element_operation_delete(self, item, operation): # If data is stix, just use the generic stix function for deletion @@ -2564,11 +2585,20 @@ def element_operation_delete(self, item, operation): "Delete operation or not found stix helper", {"type": item["type"]} ) + def element_remove_from_draft(self, item): + if item["type"] == "relationship": + self.opencti.stix_core_relationship.remove_from_draft(id=item["id"]) + elif item["type"] == "sighting": + self.opencti.stix_sighting_relationship.remove_from_draft(id=item["id"]) + else: + # Element is considered stix core object + self.opencti.stix_core_object.remove_from_draft(id=item["id"]) + def apply_opencti_operation(self, item, operation): if operation == "delete" or operation == "delete_force": self.element_operation_delete(item=item, operation=operation) elif operation == "revert_draft": - self.opencti.stix_core_object.remove_from_draft(id=item["id"]) + self.element_remove_from_draft(item=item) elif operation == "restore": self.opencti.trash.restore(item["id"]) elif operation == "merge": From 7f3f8794b6b0e599d091b88228bc0828af118e38 Mon Sep 17 00:00:00 2001 From: Jeremy Cloarec Date: Fri, 13 Jun 2025 16:56:54 +0200 Subject: [PATCH 2/2] [client] add remove from draft/share/unshare methods for sightings and relationships --- .../opencti_stix_core_relationship.py | 124 +++++++++-------- .../opencti_stix_sighting_relationship.py | 126 +++++++++--------- 2 files changed, 122 insertions(+), 128 deletions(-) diff --git a/pycti/entities/opencti_stix_core_relationship.py b/pycti/entities/opencti_stix_core_relationship.py index 8ae4f1bc8..8a40db706 100644 --- a/pycti/entities/opencti_stix_core_relationship.py +++ b/pycti/entities/opencti_stix_core_relationship.py @@ -1248,8 +1248,7 @@ def import_from_stix2(self, **kwargs): "[opencti_stix_core_relationship] Missing parameters: stixObject" ) - -""" + """ Share element to multiple organizations :param entity_id: the stix_core_relationship id @@ -1257,78 +1256,77 @@ def import_from_stix2(self, **kwargs): :return void """ - -def organization_share(self, entity_id, organization_ids, sharing_direct_container): - query = """ - mutation StixCoreRelationshipEdit($id: ID!, $organizationId: [ID!]!, $directContainerSharing: Boolean) { - stixCoreRelationshipEdit(id: $id) { - restrictionOrganizationAdd(organizationId: $organizationId, directContainerSharing: $directContainerSharing) { - id + def organization_share(self, entity_id, organization_ids, sharing_direct_container): + query = """ + mutation StixCoreRelationshipEdit($id: ID!, $organizationId: [ID!]!, $directContainerSharing: Boolean) { + stixCoreRelationshipEdit(id: $id) { + restrictionOrganizationAdd(organizationId: $organizationId, directContainerSharing: $directContainerSharing) { + id + } } } - } - """ - self.opencti.query( - query, - { - "id": entity_id, - "organizationId": organization_ids, - "directContainerSharing": sharing_direct_container, - }, - ) - - -""" - Unshare element from multiple organizations - - :param entity_id: the stix_core_relationship id - :param organization_id:s the organization to share with - :return void -""" + """ + self.opencti.query( + query, + { + "id": entity_id, + "organizationId": organization_ids, + "directContainerSharing": sharing_direct_container, + }, + ) + """ + Unshare element from multiple organizations + + :param entity_id: the stix_core_relationship id + :param organization_id:s the organization to share with + :return void + """ -def organization_unshare(self, entity_id, organization_ids, sharing_direct_container): - query = """ - mutation StixCoreRelationshipEdit($id: ID!, $organizationId: [ID!]!, $directContainerSharing: Boolean) { - stixCoreRelationshipEdit(id: $id) { - restrictionOrganizationDelete(organizationId: $organizationId, directContainerSharing: $directContainerSharing) { - id + def organization_unshare( + self, entity_id, organization_ids, sharing_direct_container + ): + query = """ + mutation StixCoreRelationshipEdit($id: ID!, $organizationId: [ID!]!, $directContainerSharing: Boolean) { + stixCoreRelationshipEdit(id: $id) { + restrictionOrganizationDelete(organizationId: $organizationId, directContainerSharing: $directContainerSharing) { + id + } } } - } - """ - self.opencti.query( - query, - { - "id": entity_id, - "organizationId": organization_ids, - "directContainerSharing": sharing_direct_container, - }, - ) - + """ + self.opencti.query( + query, + { + "id": entity_id, + "organizationId": organization_ids, + "directContainerSharing": sharing_direct_container, + }, + ) -""" + """ Remove a stix_core_relationship object from draft (revert) :param id: the stix_core_relationship id :return void """ - -def remove_from_draft(self, **kwargs): - id = kwargs.get("id", None) - if id is not None: - self.opencti.app_logger.info("Draft remove stix_core_relationship", {"id": id}) - query = """ - mutation StixCoreRelationshipEditDraftRemove($id: ID!) { - stixCoreRelationshipEdit(id: $id) { - removeFromDraft + def remove_from_draft(self, **kwargs): + id = kwargs.get("id", None) + if id is not None: + self.opencti.app_logger.info( + "Draft remove stix_core_relationship", {"id": id} + ) + query = """ + mutation StixCoreRelationshipEditDraftRemove($id: ID!) { + stixCoreRelationshipEdit(id: $id) { + removeFromDraft + } } - } - """ - self.opencti.query(query, {"id": id}) - else: - self.opencti.app_logger.error( - "[stix_core_relationship] Cant remove from draft, missing parameters: id" - ) - return None + """ + self.opencti.query(query, {"id": id}) + else: + self.opencti.app_logger.error( + "[stix_core_relationship] Cant remove from draft, missing parameters: id" + ) + return None diff --git a/pycti/entities/opencti_stix_sighting_relationship.py b/pycti/entities/opencti_stix_sighting_relationship.py index 397a15ae7..f9f9a488c 100644 --- a/pycti/entities/opencti_stix_sighting_relationship.py +++ b/pycti/entities/opencti_stix_sighting_relationship.py @@ -802,8 +802,7 @@ def update_created_by(self, **kwargs): self.opencti.app_logger.error("Missing parameters: id") return False - -""" + """ Share element to multiple organizations :param entity_id: the stix_sighting id @@ -811,81 +810,78 @@ def update_created_by(self, **kwargs): :return void """ - -def organization_share(self, entity_id, organization_ids, sharing_direct_container): - query = """ - mutation StixSightingRelationshipEdit($id: ID!, $organizationId: [ID!]!, $directContainerSharing: Boolean) { - stixSightingRelationshipEdit(id: $id) { - restrictionOrganizationAdd(organizationId: $organizationId, directContainerSharing: $directContainerSharing) { - id - } - } - } - """ - self.opencti.query( - query, - { - "id": entity_id, - "organizationId": organization_ids, - "directContainerSharing": sharing_direct_container, - }, - ) - - -""" - Unshare element from multiple organizations - - :param entity_id: the stix_sighting id - :param organization_id:s the organization to share with - :return void -""" - - -def organization_unshare(self, entity_id, organization_ids, sharing_direct_container): - query = """ - mutation StixSightingRelationshipEdit($id: ID!, $organizationId: [ID!]!, $directContainerSharing: Boolean) { - stixSightingRelationshipEdit(id: $id) { - restrictionOrganizationDelete(organizationId: $organizationId, directContainerSharing: $directContainerSharing) { - id + def organization_share(self, entity_id, organization_ids, sharing_direct_container): + query = """ + mutation StixSightingRelationshipEdit($id: ID!, $organizationId: [ID!]!, $directContainerSharing: Boolean) { + stixSightingRelationshipEdit(id: $id) { + restrictionOrganizationAdd(organizationId: $organizationId, directContainerSharing: $directContainerSharing) { + id + } } } - } - """ - self.opencti.query( - query, - { - "id": entity_id, - "organizationId": organization_ids, - "directContainerSharing": sharing_direct_container, - }, - ) - - -""" - Remove a stix_sighting object from draft (revert) + """ + self.opencti.query( + query, + { + "id": entity_id, + "organizationId": organization_ids, + "directContainerSharing": sharing_direct_container, + }, + ) - :param id: the stix_sighting id + """ + Unshare element from multiple organizations + + :param entity_id: the stix_sighting id + :param organization_id:s the organization to share with :return void """ - -def remove_from_draft(self, **kwargs): - id = kwargs.get("id", None) - if id is not None: - self.opencti.app_logger.info("Draft remove stix_sighting", {"id": id}) + def organization_unshare( + self, entity_id, organization_ids, sharing_direct_container + ): query = """ - mutation StixSightingRelationshipEditDraftRemove($id: ID!) { + mutation StixSightingRelationshipEdit($id: ID!, $organizationId: [ID!]!, $directContainerSharing: Boolean) { stixSightingRelationshipEdit(id: $id) { - removeFromDraft + restrictionOrganizationDelete(organizationId: $organizationId, directContainerSharing: $directContainerSharing) { + id + } } } """ - self.opencti.query(query, {"id": id}) - else: - self.opencti.app_logger.error( - "[stix_sighting] Cant remove from draft, missing parameters: id" + self.opencti.query( + query, + { + "id": entity_id, + "organizationId": organization_ids, + "directContainerSharing": sharing_direct_container, + }, ) - return None + + """ + Remove a stix_sighting object from draft (revert) + + :param id: the stix_sighting id + :return void + """ + + def remove_from_draft(self, **kwargs): + id = kwargs.get("id", None) + if id is not None: + self.opencti.app_logger.info("Draft remove stix_sighting", {"id": id}) + query = """ + mutation StixSightingRelationshipEditDraftRemove($id: ID!) { + stixSightingRelationshipEdit(id: $id) { + removeFromDraft + } + } + """ + self.opencti.query(query, {"id": id}) + else: + self.opencti.app_logger.error( + "[stix_sighting] Cant remove from draft, missing parameters: id" + ) + return None """ Delete a stix_sighting