pycti 6.0.10__tar.gz → 6.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pycti might be problematic. Click here for more details.

Files changed (73) hide show
  1. {pycti-6.0.10 → pycti-6.1.0}/PKG-INFO +2 -2
  2. {pycti-6.0.10 → pycti-6.1.0}/pycti/__init__.py +1 -1
  3. {pycti-6.0.10 → pycti-6.1.0}/pycti/api/opencti_api_client.py +15 -5
  4. {pycti-6.0.10 → pycti-6.1.0}/pycti/api/opencti_api_playbook.py +3 -2
  5. {pycti-6.0.10 → pycti-6.1.0}/pycti/connector/opencti_connector_helper.py +6 -4
  6. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_case_incident.py +1 -1
  7. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_intrusion_set.py +25 -3
  8. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_report.py +13 -0
  9. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_stix_core_object.py +32 -5
  10. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_stix_cyber_observable.py +23 -3
  11. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_stix_domain_object.py +25 -7
  12. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_stix_object_or_stix_relationship.py +63 -4
  13. {pycti-6.0.10 → pycti-6.1.0}/pycti/utils/constants.py +0 -1
  14. {pycti-6.0.10 → pycti-6.1.0}/pycti/utils/opencti_stix2.py +253 -68
  15. {pycti-6.0.10 → pycti-6.1.0}/pycti.egg-info/PKG-INFO +2 -2
  16. {pycti-6.0.10 → pycti-6.1.0}/pycti.egg-info/requires.txt +1 -1
  17. {pycti-6.0.10 → pycti-6.1.0}/setup.cfg +1 -1
  18. {pycti-6.0.10 → pycti-6.1.0}/LICENSE +0 -0
  19. {pycti-6.0.10 → pycti-6.1.0}/README.md +0 -0
  20. {pycti-6.0.10 → pycti-6.1.0}/pycti/api/__init__.py +0 -0
  21. {pycti-6.0.10 → pycti-6.1.0}/pycti/api/opencti_api_connector.py +0 -0
  22. {pycti-6.0.10 → pycti-6.1.0}/pycti/api/opencti_api_work.py +0 -0
  23. {pycti-6.0.10 → pycti-6.1.0}/pycti/connector/__init__.py +0 -0
  24. {pycti-6.0.10 → pycti-6.1.0}/pycti/connector/opencti_connector.py +0 -0
  25. {pycti-6.0.10 → pycti-6.1.0}/pycti/connector/opencti_metric_handler.py +0 -0
  26. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/__init__.py +0 -0
  27. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_attack_pattern.py +0 -0
  28. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_campaign.py +0 -0
  29. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_case_rfi.py +0 -0
  30. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_case_rft.py +0 -0
  31. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_channel.py +0 -0
  32. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_course_of_action.py +0 -0
  33. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_data_component.py +0 -0
  34. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_data_source.py +0 -0
  35. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_event.py +0 -0
  36. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_external_reference.py +0 -0
  37. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_feedback.py +0 -0
  38. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_grouping.py +0 -0
  39. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_identity.py +0 -0
  40. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_incident.py +0 -0
  41. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_indicator.py +0 -0
  42. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_infrastructure.py +0 -0
  43. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_kill_chain_phase.py +0 -0
  44. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_label.py +0 -0
  45. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_language.py +0 -0
  46. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_location.py +0 -0
  47. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_malware.py +0 -0
  48. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_malware_analysis.py +0 -0
  49. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_marking_definition.py +0 -0
  50. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_narrative.py +0 -0
  51. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_note.py +0 -0
  52. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_observed_data.py +0 -0
  53. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_opinion.py +0 -0
  54. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_stix.py +0 -0
  55. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_stix_core_relationship.py +0 -0
  56. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_stix_nested_ref_relationship.py +0 -0
  57. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_stix_sighting_relationship.py +0 -0
  58. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_task.py +0 -0
  59. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_threat_actor.py +0 -0
  60. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_threat_actor_group.py +0 -0
  61. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_threat_actor_individual.py +0 -0
  62. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_tool.py +0 -0
  63. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_vocabulary.py +0 -0
  64. {pycti-6.0.10 → pycti-6.1.0}/pycti/entities/opencti_vulnerability.py +0 -0
  65. {pycti-6.0.10 → pycti-6.1.0}/pycti/utils/__init__.py +0 -0
  66. {pycti-6.0.10 → pycti-6.1.0}/pycti/utils/opencti_logger.py +0 -0
  67. {pycti-6.0.10 → pycti-6.1.0}/pycti/utils/opencti_stix2_splitter.py +0 -0
  68. {pycti-6.0.10 → pycti-6.1.0}/pycti/utils/opencti_stix2_update.py +0 -0
  69. {pycti-6.0.10 → pycti-6.1.0}/pycti/utils/opencti_stix2_utils.py +0 -0
  70. {pycti-6.0.10 → pycti-6.1.0}/pycti.egg-info/SOURCES.txt +0 -0
  71. {pycti-6.0.10 → pycti-6.1.0}/pycti.egg-info/dependency_links.txt +0 -0
  72. {pycti-6.0.10 → pycti-6.1.0}/pycti.egg-info/top_level.txt +0 -0
  73. {pycti-6.0.10 → pycti-6.1.0}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pycti
3
- Version: 6.0.10
3
+ Version: 6.1.0
4
4
  Summary: Python API client for OpenCTI.
5
5
  Home-page: https://github.com/OpenCTI-Platform/client-python
6
6
  Author: Filigran
@@ -42,7 +42,7 @@ Requires-Dist: pre-commit~=3.7.0; extra == "dev"
42
42
  Requires-Dist: pytest-cases~=3.8.0; extra == "dev"
43
43
  Requires-Dist: pytest-cov~=5.0.0; extra == "dev"
44
44
  Requires-Dist: pytest_randomly~=3.15.0; extra == "dev"
45
- Requires-Dist: pytest~=8.1.1; extra == "dev"
45
+ Requires-Dist: pytest~=8.2.0; extra == "dev"
46
46
  Requires-Dist: types-python-dateutil~=2.9.0; extra == "dev"
47
47
  Requires-Dist: wheel~=0.43.0; extra == "dev"
48
48
  Provides-Extra: doc
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
- __version__ = "6.0.10"
2
+ __version__ = "6.1.0"
3
3
 
4
4
  from .api.opencti_api_client import OpenCTIApiClient
5
5
  from .api.opencti_api_connector import OpenCTIApiConnector
@@ -207,6 +207,12 @@ class OpenCTIApiClient:
207
207
  def set_applicant_id_header(self, applicant_id):
208
208
  self.request_headers["opencti-applicant-id"] = applicant_id
209
209
 
210
+ def set_playbook_id_header(self, playbook_id):
211
+ self.request_headers["opencti-playbook-id"] = playbook_id
212
+
213
+ def set_event_id(self, event_id):
214
+ self.request_headers["opencti-event-id"] = event_id
215
+
210
216
  def set_synchronized_upsert_header(self, synchronized):
211
217
  self.request_headers["synchronized-upsert"] = (
212
218
  "true" if synchronized is True else "false"
@@ -616,18 +622,19 @@ class OpenCTIApiClient:
616
622
  """upload a file to OpenCTI API
617
623
 
618
624
  :param `**kwargs`: arguments for file upload (required: `file_name` and `data`)
619
- :return: returns the query respons for the file upload
625
+ :return: returns the query response for the file upload
620
626
  :rtype: dict
621
627
  """
622
628
 
623
629
  file_name = kwargs.get("file_name", None)
630
+ file_markings = kwargs.get("file_markings", None)
624
631
  data = kwargs.get("data", None)
625
632
  mime_type = kwargs.get("mime_type", "text/plain")
626
633
  if file_name is not None:
627
634
  self.app_logger.info("Uploading a file.")
628
635
  query = """
629
- mutation UploadImport($file: Upload!) {
630
- uploadImport(file: $file) {
636
+ mutation UploadImport($file: Upload!, $fileMarkings: [String]) {
637
+ uploadImport(file: $file, fileMarkings: $fileMarkings) {
631
638
  id
632
639
  name
633
640
  }
@@ -639,8 +646,11 @@ class OpenCTIApiClient:
639
646
  mime_type = "application/json"
640
647
  else:
641
648
  mime_type = magic.from_file(file_name, mime=True)
642
-
643
- return self.query(query, {"file": (File(file_name, data, mime_type))})
649
+ query_vars = {"file": (File(file_name, data, mime_type))}
650
+ # optional file markings
651
+ if file_markings is not None:
652
+ query_vars["fileMarkings"] = file_markings
653
+ return self.query(query, query_vars)
644
654
  else:
645
655
  self.app_logger.error("[upload] Missing parameter: file_name")
646
656
  return None
@@ -9,14 +9,15 @@ class OpenCTIApiPlaybook:
9
9
  "Executing playbook step", {"playbook_id": playbook["playbook_id"]}
10
10
  )
11
11
  query = """
12
- mutation PlaybookStepExecution($execution_id: ID!, $execution_start: DateTime!, $data_instance_id: ID!, $playbook_id: ID!, $previous_step_id: ID!, $step_id: ID!, $previous_bundle: String!, $bundle: String!) {
13
- playbookStepExecution(execution_id: $execution_id, execution_start: $execution_start, data_instance_id: $data_instance_id, playbook_id: $playbook_id, previous_step_id: $previous_step_id, step_id: $step_id, previous_bundle: $previous_bundle, bundle: $bundle)
12
+ mutation PlaybookStepExecution($execution_id: ID!, $event_id: ID!, $execution_start: DateTime!, $data_instance_id: ID!, $playbook_id: ID!, $previous_step_id: ID!, $step_id: ID!, $previous_bundle: String!, $bundle: String!) {
13
+ playbookStepExecution(execution_id: $execution_id, event_id: $event_id, execution_start: $execution_start, data_instance_id: $data_instance_id, playbook_id: $playbook_id, previous_step_id: $previous_step_id, step_id: $step_id, previous_bundle: $previous_bundle, bundle: $bundle)
14
14
  }
15
15
  """
16
16
  self.api.query(
17
17
  query,
18
18
  {
19
19
  "execution_id": playbook["execution_id"],
20
+ "event_id": playbook["event_id"],
20
21
  "execution_start": playbook["execution_start"],
21
22
  "playbook_id": playbook["playbook_id"],
22
23
  "data_instance_id": playbook["data_instance_id"],
@@ -282,18 +282,20 @@ class ListenQueue(threading.Thread):
282
282
  is_playbook = "playbook" in json_data["internal"]
283
283
  # If playbook, compute object on data bundle
284
284
  if is_playbook:
285
- execution_id = json_data["internal"]["playbook"]["execution_id"]
286
285
  execution_start = self.helper.date_now()
287
- playbook_id = json_data["internal"]["playbook"]["playbook_id"]
288
- data_instance_id = json_data["internal"]["playbook"][
286
+ event_id = json_data["internal"]["playbook"].get("event_id")
287
+ execution_id = json_data["internal"]["playbook"].get("execution_id")
288
+ playbook_id = json_data["internal"]["playbook"].get("playbook_id")
289
+ data_instance_id = json_data["internal"]["playbook"].get(
289
290
  "data_instance_id"
290
- ]
291
+ )
291
292
  previous_bundle = json.dumps((json_data["event"]["bundle"]))
292
293
  step_id = json_data["internal"]["playbook"]["step_id"]
293
294
  previous_step_id = json_data["internal"]["playbook"][
294
295
  "previous_step_id"
295
296
  ]
296
297
  playbook_data = {
298
+ "event_id": event_id,
297
299
  "execution_id": execution_id,
298
300
  "execution_start": execution_start,
299
301
  "playbook_id": playbook_id,
@@ -530,7 +530,7 @@ class CaseIncident:
530
530
  data = self.opencti.process_multiple(result["data"]["caseIncidents"])
531
531
  final_data = final_data + data
532
532
  while result["data"]["caseIncidents"]["pageInfo"]["hasNextPage"]:
533
- after = result["date"]["caseIncidents"]["pageInfo"]["endCursor"]
533
+ after = result["data"]["caseIncidents"]["pageInfo"]["endCursor"]
534
534
  self.opencti.app_logger.info("Listing Case Incidents", {"after": after})
535
535
  result = self.opencti.query(
536
536
  query,
@@ -286,9 +286,31 @@ class IntrusionSet:
286
286
  "orderMode": order_mode,
287
287
  },
288
288
  )
289
- return self.opencti.process_multiple(
290
- result["data"]["intrusionSets"], with_pagination
291
- )
289
+ if get_all:
290
+ final_data = []
291
+ data = self.opencti.process_multiple(result["data"]["intrusionSets"])
292
+ final_data = final_data + data
293
+ while result["data"]["intrusionSets"]["pageInfo"]["hasNextPage"]:
294
+ after = result["data"]["intrusionSets"]["pageInfo"]["endCursor"]
295
+ self.opencti.app_logger.info("Listing Intrusion-Sets", {"after": after})
296
+ result = self.opencti.query(
297
+ query,
298
+ {
299
+ "filters": filters,
300
+ "search": search,
301
+ "first": first,
302
+ "after": after,
303
+ "orderBy": order_by,
304
+ "orderMode": order_mode,
305
+ },
306
+ )
307
+ data = self.opencti.process_multiple(result["data"]["intrusionSets"])
308
+ final_data = final_data + data
309
+ return final_data
310
+ else:
311
+ return self.opencti.process_multiple(
312
+ result["data"]["intrusionSets"], with_pagination
313
+ )
292
314
 
293
315
  """
294
316
  Read a Intrusion-Set object
@@ -466,6 +466,19 @@ class Report:
466
466
  id = str(uuid.uuid5(uuid.UUID("00abedb4-aa42-466c-9c01-fed23315a9b7"), data))
467
467
  return "report--" + id
468
468
 
469
+ @staticmethod
470
+ def generate_fixed_fake_id(name, published=None):
471
+ name = name.lower().strip()
472
+ if isinstance(published, datetime.datetime):
473
+ published = published.isoformat()
474
+ if published is not None:
475
+ data = {"name": name, "published": published, "fake": "fake"}
476
+ else:
477
+ data = {"name": name, "fake": "fake"}
478
+ data = canonicalize(data, utf8=False)
479
+ id = str(uuid.uuid5(uuid.UUID("00abedb4-aa42-466c-9c01-fed23315a9b7"), data))
480
+ return "report--" + id
481
+
469
482
  """
470
483
  List Report objects
471
484
 
@@ -435,9 +435,18 @@ class StixCoreObject:
435
435
  }
436
436
  }
437
437
  }
438
- }
438
+ }
439
439
  ... on StixCyberObservable {
440
440
  observable_value
441
+ indicators {
442
+ edges {
443
+ node {
444
+ id
445
+ pattern
446
+ pattern_type
447
+ }
448
+ }
449
+ }
441
450
  }
442
451
  ... on AutonomousSystem {
443
452
  number
@@ -1090,9 +1099,18 @@ class StixCoreObject:
1090
1099
  }
1091
1100
  }
1092
1101
  }
1093
- }
1102
+ }
1094
1103
  ... on StixCyberObservable {
1095
1104
  observable_value
1105
+ indicators {
1106
+ edges {
1107
+ node {
1108
+ id
1109
+ pattern
1110
+ pattern_type
1111
+ }
1112
+ }
1113
+ }
1096
1114
  }
1097
1115
  ... on AutonomousSystem {
1098
1116
  number
@@ -1459,13 +1477,21 @@ class StixCoreObject:
1459
1477
  return entity["importFiles"]
1460
1478
 
1461
1479
  def push_list_export(
1462
- self, entity_id, entity_type, file_name, data, list_filters="", mime_type=None
1480
+ self,
1481
+ entity_id,
1482
+ entity_type,
1483
+ file_name,
1484
+ file_markings,
1485
+ data,
1486
+ list_filters="",
1487
+ mime_type=None,
1463
1488
  ):
1464
1489
  query = """
1465
- mutation StixCoreObjectsExportPush($entity_id: String, $entity_type: String!, $file: Upload!, $listFilters: String) {
1466
- stixCoreObjectsExportPush(entity_id: $entity_id, entity_type: $entity_type, file: $file, listFilters: $listFilters)
1490
+ mutation StixCoreObjectsExportPush($entity_id: String, $entity_type: String!, $file: Upload!, $file_markings: [String]!, $listFilters: String) {
1491
+ stixCoreObjectsExportPush(entity_id: $entity_id, entity_type: $entity_type, file: $file, file_markings: $file_markings, listFilters: $listFilters)
1467
1492
  }
1468
1493
  """
1494
+
1469
1495
  if mime_type is None:
1470
1496
  file = self.file(file_name, data)
1471
1497
  else:
@@ -1476,6 +1502,7 @@ class StixCoreObject:
1476
1502
  "entity_id": entity_id,
1477
1503
  "entity_type": entity_type,
1478
1504
  "file": file,
1505
+ "file_markings": file_markings,
1479
1506
  "listFilters": list_filters,
1480
1507
  },
1481
1508
  )
@@ -2316,11 +2316,30 @@ class StixCyberObservable:
2316
2316
  return False
2317
2317
 
2318
2318
  def push_list_export(
2319
- self, entity_id, entity_type, file_name, data, list_filters="", mime_type=None
2319
+ self,
2320
+ entity_id,
2321
+ entity_type,
2322
+ file_name,
2323
+ file_markings,
2324
+ data,
2325
+ list_filters="",
2326
+ mime_type=None,
2320
2327
  ):
2321
2328
  query = """
2322
- mutation StixCyberObservablesExportPush($entity_id: String, $entity_type: String!, $file: Upload!, $listFilters: String) {
2323
- stixCyberObservablesExportPush(entity_id: $entity_id, entity_type: $entity_type, file: $file, listFilters: $listFilters)
2329
+ mutation StixCyberObservablesExportPush(
2330
+ $entity_id: String,
2331
+ $entity_type: String!,
2332
+ $file: Upload!,
2333
+ $file_markings: [String]!,
2334
+ $listFilters: String
2335
+ ) {
2336
+ stixCyberObservablesExportPush(
2337
+ entity_id: $entity_id,
2338
+ entity_type: $entity_type,
2339
+ file: $file,
2340
+ file_markings: $file_markings,
2341
+ listFilters: $listFilters
2342
+ )
2324
2343
  }
2325
2344
  """
2326
2345
  if mime_type is None:
@@ -2333,6 +2352,7 @@ class StixCyberObservable:
2333
2352
  "entity_id": entity_id,
2334
2353
  "entity_type": entity_type,
2335
2354
  "file": file,
2355
+ "file_markings": file_markings,
2336
2356
  "listFilters": list_filters,
2337
2357
  },
2338
2358
  )
@@ -1325,11 +1325,18 @@ class StixDomainObject:
1325
1325
  return None
1326
1326
 
1327
1327
  def push_list_export(
1328
- self, entity_id, entity_type, file_name, data, list_filters="", mime_type=None
1328
+ self,
1329
+ entity_id,
1330
+ entity_type,
1331
+ file_name,
1332
+ file_markings,
1333
+ data,
1334
+ list_filters="",
1335
+ mime_type=None,
1329
1336
  ):
1330
1337
  query = """
1331
- mutation StixDomainObjectsExportPush($entity_id: String, $entity_type: String!, $file: Upload!, $listFilters: String) {
1332
- stixDomainObjectsExportPush(entity_id: $entity_id, entity_type: $entity_type, file: $file, listFilters: $listFilters)
1338
+ mutation StixDomainObjectsExportPush($entity_id: String, $entity_type: String!, $file: Upload!, $file_markings: [String]!, $listFilters: String) {
1339
+ stixDomainObjectsExportPush(entity_id: $entity_id, entity_type: $entity_type, file: $file, file_markings: $file_markings, listFilters: $listFilters)
1333
1340
  }
1334
1341
  """
1335
1342
  if mime_type is None:
@@ -1342,15 +1349,24 @@ class StixDomainObject:
1342
1349
  "entity_id": entity_id,
1343
1350
  "entity_type": entity_type,
1344
1351
  "file": file,
1352
+ "file_markings": file_markings,
1345
1353
  "listFilters": list_filters,
1346
1354
  },
1347
1355
  )
1348
1356
 
1349
- def push_entity_export(self, entity_id, file_name, data, mime_type=None):
1357
+ def push_entity_export(
1358
+ self, entity_id, file_name, data, file_markings, mime_type=None
1359
+ ):
1350
1360
  query = """
1351
- mutation StixDomainObjectEdit($id: ID!, $file: Upload!) {
1361
+ mutation StixDomainObjectEdit(
1362
+ $id: ID!, $file: Upload!,
1363
+ $file_markings: [String]!
1364
+ ) {
1352
1365
  stixDomainObjectEdit(id: $id) {
1353
- exportPush(file: $file)
1366
+ exportPush(
1367
+ file: $file,
1368
+ file_markings: $file_markings
1369
+ )
1354
1370
  }
1355
1371
  }
1356
1372
  """
@@ -1358,7 +1374,9 @@ class StixDomainObject:
1358
1374
  file = self.file(file_name, data)
1359
1375
  else:
1360
1376
  file = self.file(file_name, data, mime_type)
1361
- self.opencti.query(query, {"id": entity_id, "file": file})
1377
+ self.opencti.query(
1378
+ query, {"id": entity_id, "file": file, "file_markings": file_markings}
1379
+ )
1362
1380
 
1363
1381
  """
1364
1382
  Update the Identity author of a Stix-Domain-Object object (created_by)
@@ -1,3 +1,6 @@
1
+ import json
2
+
3
+
1
4
  class StixObjectOrStixRelationship:
2
5
  def __init__(self, opencti):
3
6
  self.opencti = opencti
@@ -329,11 +332,15 @@ class StixObjectOrStixRelationship:
329
332
  }
330
333
  ... on Case {
331
334
  name
332
- }
335
+ }
333
336
  ... on StixCyberObservable {
334
337
  observable_value
335
338
  }
336
339
  ... on StixCoreRelationship {
340
+ id
341
+ standard_id
342
+ entity_type
343
+ parent_types
337
344
  createdBy {
338
345
  ... on Identity {
339
346
  id
@@ -396,6 +403,10 @@ class StixObjectOrStixRelationship:
396
403
  stop_time
397
404
  }
398
405
  ... on StixSightingRelationship {
406
+ id
407
+ standard_id
408
+ entity_type
409
+ parent_types
399
410
  createdBy {
400
411
  ... on Identity {
401
412
  id
@@ -476,9 +487,9 @@ class StixObjectOrStixRelationship:
476
487
  )
477
488
  query = (
478
489
  """
479
- query StixObjectOrStixRelationship($id: String!) {
480
- stixObjectOrStixRelationship(id: $id) {
481
- """
490
+ query StixObjectOrStixRelationship($id: String!) {
491
+ stixObjectOrStixRelationship(id: $id) {
492
+ """
482
493
  + (
483
494
  custom_attributes
484
495
  if custom_attributes is not None
@@ -496,3 +507,51 @@ class StixObjectOrStixRelationship:
496
507
  else:
497
508
  self.opencti.app_logger.error("Missing parameters: id")
498
509
  return None
510
+
511
+ def list(self, **kwargs):
512
+ filters = kwargs.get("filters", None)
513
+ search = kwargs.get("search", None)
514
+ first = kwargs.get("first", 100)
515
+ after = kwargs.get("after", None)
516
+ with_pagination = kwargs.get("with_pagination", False)
517
+ custom_attributes = kwargs.get("customAttributes", None)
518
+
519
+ self.opencti.app_logger.info(
520
+ "Listing StixObjectOrStixRelationships with filters",
521
+ {"filters": json.dumps(filters)},
522
+ )
523
+ query = (
524
+ """
525
+ query StixObjectOrStixRelationships($filters: FilterGroup, $search: String, $first: Int, $after: ID) {
526
+ stixObjectOrStixRelationships(filters: $filters, search: $search, first: $first, after: $after) {
527
+ edges {
528
+ node {
529
+ """
530
+ + (custom_attributes if custom_attributes is not None else self.properties)
531
+ + """
532
+ }
533
+ }
534
+ pageInfo {
535
+ startCursor
536
+ endCursor
537
+ hasNextPage
538
+ hasPreviousPage
539
+ globalCount
540
+ }
541
+ }
542
+ }
543
+ """
544
+ )
545
+ result = self.opencti.query(
546
+ query,
547
+ {
548
+ "filters": filters,
549
+ "search": search,
550
+ "first": first,
551
+ "after": after,
552
+ },
553
+ )
554
+
555
+ return self.opencti.process_multiple(
556
+ result["data"]["stixObjectOrStixRelationships"], with_pagination
557
+ )
@@ -129,7 +129,6 @@ class MultipleRefRelationship(Enum):
129
129
  CHILD = "child"
130
130
  BODY_MULTIPART = "body-multipart"
131
131
  VALUES = "values"
132
- LINKED = "x_opencti_linked-to"
133
132
  SERVICE_DDL = "service-dll"
134
133
  INSTALLED_SOFTWARE = "installed-software"
135
134
  RELATION_ANALYSIS_SCO = "analysis-sco"
@@ -680,6 +680,9 @@ class OpenCTIStix2:
680
680
 
681
681
  author = self.resolve_author(title)
682
682
  report = self.opencti.report.create(
683
+ id=self.opencti.report.generate_fixed_fake_id(
684
+ title, published
685
+ ),
683
686
  name=title,
684
687
  createdBy=author["id"] if author is not None else None,
685
688
  objectMarking=[object_marking_ref_result["id"]],
@@ -788,6 +791,48 @@ class OpenCTIStix2:
788
791
  "reports": reports,
789
792
  }
790
793
 
794
+ def get_listers(self):
795
+ return {
796
+ "Stix-Core-Object": self.opencti.stix_core_object.list,
797
+ "Stix-Domain-Object": self.opencti.stix_domain_object.list,
798
+ "Administrative-Area": self.opencti.location.list,
799
+ "Attack-Pattern": self.opencti.attack_pattern.list,
800
+ "Campaign": self.opencti.campaign.list,
801
+ "Channel": self.opencti.channel.list,
802
+ "Event": self.opencti.event.list,
803
+ "Note": self.opencti.note.list,
804
+ "Observed-Data": self.opencti.observed_data.list,
805
+ "Opinion": self.opencti.opinion.list,
806
+ "Report": self.opencti.report.list,
807
+ "Grouping": self.opencti.grouping.list,
808
+ "Case-Incident": self.opencti.case_incident.list,
809
+ "Feedback": self.opencti.feedback.list,
810
+ "Case-Rfi": self.opencti.case_rfi.list,
811
+ "Case-Rft": self.opencti.case_rft.list,
812
+ "Task": self.opencti.task.list,
813
+ "Course-Of-Action": self.opencti.course_of_action.list,
814
+ "Data-Component": self.opencti.data_component.list,
815
+ "Data-Source": self.opencti.data_source.list,
816
+ "Identity": self.opencti.identity.list,
817
+ "Indicator": self.opencti.indicator.list,
818
+ "Infrastructure": self.opencti.infrastructure.list,
819
+ "Intrusion-Set": self.opencti.intrusion_set.list,
820
+ "Location": self.opencti.location.list,
821
+ "Language": self.opencti.language.list,
822
+ "Malware": self.opencti.malware.list,
823
+ "Malware-Analysis": self.opencti.malware_analysis.list,
824
+ "Threat-Actor": self.opencti.threat_actor_group.list,
825
+ "Threat-Actor-Group": self.opencti.threat_actor_group.list,
826
+ "Threat-Actor-Individual": self.opencti.threat_actor_individual.list,
827
+ "Tool": self.opencti.tool.list,
828
+ "Narrative": self.opencti.narrative.list,
829
+ "Vulnerability": self.opencti.vulnerability.list,
830
+ "Incident": self.opencti.incident.list,
831
+ "Stix-Cyber-Observable": self.opencti.stix_cyber_observable.list,
832
+ "stix-sighting-relationship": self.opencti.stix_sighting_relationship.list,
833
+ "stix-core-relationship": self.opencti.stix_core_relationship.list,
834
+ }
835
+
791
836
  def get_readers(self):
792
837
  return {
793
838
  "Attack-Pattern": self.opencti.attack_pattern.read,
@@ -1512,7 +1557,7 @@ class OpenCTIStix2:
1512
1557
  if "tasks" in entity:
1513
1558
  del entity["tasks"]
1514
1559
 
1515
- if "status" in entity:
1560
+ if "status" in entity and entity["status"] is not None:
1516
1561
  entity["x_opencti_workflow_id"] = entity["status"].get("id")
1517
1562
  if "status" in entity:
1518
1563
  del entity["status"]
@@ -1614,28 +1659,90 @@ class OpenCTIStix2:
1614
1659
 
1615
1660
  return {k: v for k, v in entity.items() if self.opencti.not_empty(v)}
1616
1661
 
1662
+ def prepare_filters_export(self, id: str, access_filter: Dict = None) -> Dict:
1663
+ if access_filter is not None:
1664
+ return {
1665
+ "mode": "and",
1666
+ "filterGroups": [
1667
+ {
1668
+ "mode": "or",
1669
+ "filters": [
1670
+ {
1671
+ "key": "id",
1672
+ "values": [id],
1673
+ }
1674
+ ],
1675
+ "filterGroups": [],
1676
+ },
1677
+ access_filter,
1678
+ ],
1679
+ "filters": [],
1680
+ }
1681
+ else:
1682
+ return {
1683
+ "mode": "and",
1684
+ "filterGroups": [
1685
+ {
1686
+ "mode": "or",
1687
+ "filters": [
1688
+ {
1689
+ "key": "id",
1690
+ "values": [id],
1691
+ }
1692
+ ],
1693
+ "filterGroups": [],
1694
+ },
1695
+ ],
1696
+ "filters": [],
1697
+ }
1698
+
1617
1699
  def prepare_export(
1618
1700
  self,
1619
1701
  entity: Dict,
1620
1702
  mode: str = "simple",
1621
1703
  max_marking_definition_entity: Dict = None,
1704
+ main_filter: Dict = None,
1705
+ access_filter: Dict = None,
1622
1706
  no_custom_attributes: bool = False,
1623
1707
  ) -> List:
1624
- if (
1625
- self.check_max_marking_definition(
1626
- max_marking_definition_entity,
1627
- entity["objectMarking"] if "objectMarking" in entity else [],
1628
- )
1629
- is False
1630
- ):
1631
- self.opencti.app_logger.info(
1632
- "Marking definitions are less than max definition, not exporting.",
1633
- {"type": entity["type"]},
1634
- )
1635
- return []
1636
1708
  result = []
1637
1709
  objects_to_get = []
1638
1710
  relations_to_get = []
1711
+
1712
+ # Container
1713
+ if "objects" in entity and len(entity["objects"]) > 0:
1714
+ del entity["objects"]
1715
+ regarding_of_filter = {
1716
+ "mode": "and",
1717
+ "filterGroups": [],
1718
+ "filters": [
1719
+ {
1720
+ "key": "regardingOf",
1721
+ "mode": "and",
1722
+ "operator": "eq",
1723
+ "values": [
1724
+ {"key": "id", "values": [entity["x_opencti_id"]]},
1725
+ {"key": "relationship_type", "values": ["object"]},
1726
+ ],
1727
+ }
1728
+ ],
1729
+ }
1730
+ filter_groups = []
1731
+ if regarding_of_filter is not None:
1732
+ filter_groups.append(regarding_of_filter)
1733
+ if access_filter is not None:
1734
+ filter_groups.append(access_filter)
1735
+ export_query_filter = {
1736
+ "mode": "and",
1737
+ "filterGroups": filter_groups,
1738
+ "filters": [],
1739
+ }
1740
+ entity["objects"] = (
1741
+ self.opencti.opencti_stix_object_or_stix_relationship.list(
1742
+ filters=export_query_filter
1743
+ )
1744
+ )
1745
+
1639
1746
  # CreatedByRef
1640
1747
  if (
1641
1748
  not no_custom_attributes
@@ -1747,7 +1854,7 @@ class OpenCTIStix2:
1747
1854
  and len(entity["objects"]) > 0
1748
1855
  ):
1749
1856
  entity["object_refs"] = []
1750
- objects_to_get = entity["objects"]
1857
+ objects_to_get = entity["objects"] # To do differently
1751
1858
  for entity_object in entity["objects"]:
1752
1859
  if (
1753
1860
  entity["type"] == "report"
@@ -1819,22 +1926,62 @@ class OpenCTIStix2:
1819
1926
  entity["type"] = "sighting"
1820
1927
  entity["count"] = entity["attribute_count"]
1821
1928
  del entity["attribute_count"]
1822
- entity["sighting_of_ref"] = entity["from"]["standard_id"]
1823
- objects_to_get.append(entity["from"])
1824
- entity["where_sighted_refs"] = [entity["to"]["standard_id"]]
1825
- objects_to_get.append(entity["to"])
1929
+ from_to_check = entity["from"]["id"]
1930
+ relationships_from_filter = self.prepare_filters_export(
1931
+ id=from_to_check, access_filter=access_filter
1932
+ )
1933
+ x = self.opencti.opencti_stix_object_or_stix_relationship.list(
1934
+ filters=relationships_from_filter
1935
+ )
1936
+ if len(x) > 0:
1937
+ entity["sighting_of_ref"] = entity["from"]["id"]
1938
+ # handle from and to separately like Stix Core Relationship and call 2 requests
1939
+ objects_to_get.append(
1940
+ entity["from"]
1941
+ ) # what happen with unauthorized objects ?
1942
+
1943
+ to_to_check = [entity["to"]["id"]]
1944
+ relationships_to_filter = self.prepare_filters_export(
1945
+ id=to_to_check, access_filter=access_filter
1946
+ )
1947
+ y = self.opencti.opencti_stix_object_or_stix_relationship.list(
1948
+ filters=relationships_to_filter
1949
+ )
1950
+ if len(y) > 0:
1951
+ entity["where_sighted_refs"] = [entity["to"]["id"]]
1952
+ objects_to_get.append(entity["to"])
1953
+
1826
1954
  del entity["from"]
1827
1955
  del entity["to"]
1828
1956
  # Stix Core Relationship
1829
1957
  if "from" in entity or "to" in entity:
1830
1958
  entity["type"] = "relationship"
1831
1959
  if "from" in entity:
1832
- entity["source_ref"] = entity["from"]["standard_id"]
1833
- objects_to_get.append(entity["from"])
1960
+ from_to_check = entity["from"]["id"]
1961
+ relationships_from_filter = self.prepare_filters_export(
1962
+ id=from_to_check, access_filter=access_filter
1963
+ )
1964
+ x = self.opencti.opencti_stix_object_or_stix_relationship.list(
1965
+ filters=relationships_from_filter
1966
+ )
1967
+ if len(x) > 0:
1968
+ entity["source_ref"] = entity["from"]["id"]
1969
+ # handle from and to separately like Stix Core Relationship and call 2 requests
1970
+ objects_to_get.append(
1971
+ entity["from"]
1972
+ ) # what happen with unauthorized objects ?
1834
1973
  del entity["from"]
1835
1974
  if "to" in entity:
1836
- entity["target_ref"] = entity["to"]["standard_id"]
1837
- objects_to_get.append(entity["to"])
1975
+ to_to_check = [entity["to"]["id"]]
1976
+ relationships_to_filter = self.prepare_filters_export(
1977
+ id=to_to_check, access_filter=access_filter
1978
+ )
1979
+ y = self.opencti.opencti_stix_object_or_stix_relationship.list(
1980
+ filters=relationships_to_filter
1981
+ )
1982
+ if len(y) > 0:
1983
+ entity["target_ref"] = entity["to"]["id"]
1984
+ objects_to_get.append(entity["to"])
1838
1985
  del entity["to"]
1839
1986
  # Stix Domain Object
1840
1987
  if "attribute_abstract" in entity:
@@ -1877,7 +2024,7 @@ class OpenCTIStix2:
1877
2024
 
1878
2025
  # StixRefRelationship
1879
2026
  stix_nested_ref_relationships = self.opencti.stix_nested_ref_relationship.list(
1880
- fromId=entity["x_opencti_id"]
2027
+ fromId=entity["x_opencti_id"], filters=access_filter
1881
2028
  )
1882
2029
  for stix_nested_ref_relationship in stix_nested_ref_relationships:
1883
2030
  if "standard_id" in stix_nested_ref_relationship["to"]:
@@ -1921,8 +2068,8 @@ class OpenCTIStix2:
1921
2068
  return result
1922
2069
  elif mode == "full":
1923
2070
  uuids = [entity["id"]]
1924
- for x in result:
1925
- uuids.append(x["id"])
2071
+ for y in result:
2072
+ uuids.append(y["id"])
1926
2073
  # Get extra refs
1927
2074
  for key in entity.keys():
1928
2075
  if key.endswith("_ref"):
@@ -1964,7 +2111,7 @@ class OpenCTIStix2:
1964
2111
  )
1965
2112
  # Get extra relations (from AND to)
1966
2113
  stix_core_relationships = self.opencti.stix_core_relationship.list(
1967
- fromOrToId=entity["x_opencti_id"], getAll=True
2114
+ fromOrToId=entity["x_opencti_id"], getAll=True, filters=access_filter
1968
2115
  )
1969
2116
  for stix_core_relationship in stix_core_relationships:
1970
2117
  if self.check_max_marking_definition(
@@ -1980,10 +2127,14 @@ class OpenCTIStix2:
1980
2127
  if stix_core_relationship["to"]["id"] != entity["x_opencti_id"]
1981
2128
  else stix_core_relationship["from"]
1982
2129
  )
1983
- relation_object_data = self.prepare_export(
1984
- self.generate_export(stix_core_relationship),
1985
- "simple",
1986
- max_marking_definition_entity,
2130
+ relation_object_data = (
2131
+ self.prepare_export( # ICI -> remove max marking ?
2132
+ self.generate_export(stix_core_relationship),
2133
+ "simple",
2134
+ max_marking_definition_entity,
2135
+ main_filter,
2136
+ access_filter,
2137
+ )
1987
2138
  )
1988
2139
  relation_object_bundle = self.filter_objects(
1989
2140
  uuids, relation_object_data
@@ -2001,8 +2152,7 @@ class OpenCTIStix2:
2001
2152
  )
2002
2153
  # Get sighting
2003
2154
  stix_sighting_relationships = self.opencti.stix_sighting_relationship.list(
2004
- fromOrToId=entity["x_opencti_id"],
2005
- getAll=True,
2155
+ fromOrToId=entity["x_opencti_id"], getAll=True, filters=access_filter
2006
2156
  )
2007
2157
  for stix_sighting_relationship in stix_sighting_relationships:
2008
2158
  if self.check_max_marking_definition(
@@ -2019,10 +2169,14 @@ class OpenCTIStix2:
2019
2169
  != entity["x_opencti_id"]
2020
2170
  else stix_sighting_relationship["from"]
2021
2171
  )
2022
- relation_object_data = self.prepare_export(
2023
- self.generate_export(stix_sighting_relationship),
2024
- "simple",
2025
- max_marking_definition_entity,
2172
+ relation_object_data = (
2173
+ self.prepare_export( # ICI -> remove max marking ?
2174
+ self.generate_export(stix_sighting_relationship),
2175
+ "simple",
2176
+ max_marking_definition_entity,
2177
+ main_filter,
2178
+ access_filter,
2179
+ )
2026
2180
  )
2027
2181
  relation_object_bundle = self.filter_objects(
2028
2182
  uuids, relation_object_data
@@ -2065,12 +2219,16 @@ class OpenCTIStix2:
2065
2219
  {"type": entity_object["entity_type"]}
2066
2220
  ),
2067
2221
  )
2068
- entity_object_data = do_read(id=entity_object["id"])
2222
+ entity_object_data = do_read(
2223
+ id=entity_object["id"], filters=access_filter
2224
+ )
2069
2225
  if entity_object_data is not None:
2070
2226
  stix_entity_object = self.prepare_export(
2071
2227
  self.generate_export(entity_object_data),
2072
2228
  "simple",
2073
2229
  max_marking_definition_entity,
2230
+ main_filter,
2231
+ access_filter,
2074
2232
  )
2075
2233
  # Add to result
2076
2234
  entity_object_bundle = self.filter_objects(
@@ -2078,9 +2236,18 @@ class OpenCTIStix2:
2078
2236
  )
2079
2237
  uuids = uuids + [x["id"] for x in entity_object_bundle]
2080
2238
  result = result + entity_object_bundle
2081
- for relation_object in relations_to_get:
2239
+ for (
2240
+ relation_object
2241
+ ) in relations_to_get: # never appended after initialization
2242
+
2243
+ def find_relation_object_data(current_relation_object):
2244
+ return current_relation_object.id == relation_object["id"]
2245
+
2082
2246
  relation_object_data = self.prepare_export(
2083
- self.opencti.stix_core_relationship.read(id=relation_object["id"])
2247
+ filter(
2248
+ find_relation_object_data,
2249
+ self.opencti.stix_core_relationship.list(filters=access_filter),
2250
+ )
2084
2251
  )
2085
2252
  relation_object_bundle = self.filter_objects(
2086
2253
  uuids, relation_object_data
@@ -2150,15 +2317,12 @@ class OpenCTIStix2:
2150
2317
  entity_type: str,
2151
2318
  entity_id: str,
2152
2319
  mode: str = "simple",
2320
+ main_filter: Dict = None,
2321
+ access_filter: Dict = None,
2153
2322
  max_marking_definition: Dict = None,
2154
2323
  no_custom_attributes: bool = False,
2155
2324
  only_entity: bool = False,
2156
2325
  ) -> Dict:
2157
- max_marking_definition_entity = (
2158
- self.opencti.marking_definition.read(id=max_marking_definition)
2159
- if max_marking_definition is not None
2160
- else None
2161
- )
2162
2326
  bundle = {
2163
2327
  "type": "bundle",
2164
2328
  "id": "bundle--" + str(uuid.uuid4()),
@@ -2174,14 +2338,12 @@ class OpenCTIStix2:
2174
2338
  if LocationTypes.has_value(entity_type):
2175
2339
  entity_type = "Location"
2176
2340
 
2177
- # Reader
2178
- reader = self.get_readers()
2179
- if StixCyberObservableTypes.has_value(entity_type):
2180
- entity_type = "Stix-Cyber-Observable"
2181
- do_read = reader.get(
2341
+ # Lister
2342
+ listers = self.get_listers()
2343
+ do_list = listers.get(
2182
2344
  entity_type, lambda **kwargs: self.unknown_type({"type": entity_type})
2183
2345
  )
2184
- entity = do_read(id=entity_id)
2346
+ entity = do_list(filters=main_filter)[0]
2185
2347
  if entity is None:
2186
2348
  self.opencti.app_logger.error(
2187
2349
  "Cannot export entity (not found)", {"id": entity_id}
@@ -2191,7 +2353,9 @@ class OpenCTIStix2:
2191
2353
  stix_objects = self.prepare_export(
2192
2354
  self.generate_export(entity, no_custom_attributes),
2193
2355
  mode,
2194
- max_marking_definition_entity,
2356
+ None,
2357
+ main_filter,
2358
+ access_filter,
2195
2359
  no_custom_attributes,
2196
2360
  )
2197
2361
  if stix_objects is not None:
@@ -2206,7 +2370,7 @@ class OpenCTIStix2:
2206
2370
  self,
2207
2371
  entity_type: str,
2208
2372
  search: Dict = None,
2209
- filters: List = None,
2373
+ filters: Dict = None,
2210
2374
  orderBy: str = None,
2211
2375
  orderMode: str = None,
2212
2376
  getAll: bool = True,
@@ -2279,26 +2443,32 @@ class OpenCTIStix2:
2279
2443
  self,
2280
2444
  entity_type: str,
2281
2445
  search: Dict = None,
2282
- filters: List = None,
2446
+ filters: Dict = None,
2283
2447
  order_by: str = None,
2284
2448
  order_mode: str = None,
2285
2449
  mode: str = "simple",
2286
- max_marking_definition: Dict = None,
2450
+ main_filter: Dict = None,
2451
+ access_filter: Dict = None,
2287
2452
  ) -> Dict:
2288
- max_marking_definition_entity = (
2289
- self.opencti.marking_definition.read(id=max_marking_definition)
2290
- if max_marking_definition is not None
2291
- else None
2292
- )
2293
2453
  bundle = {
2294
2454
  "type": "bundle",
2295
2455
  "id": "bundle--" + str(uuid.uuid4()),
2296
2456
  "objects": [],
2297
2457
  }
2458
+ filterGroups = []
2459
+ if filters is not None:
2460
+ filterGroups.append(filters)
2461
+ if access_filter is not None:
2462
+ filterGroups.append(access_filter)
2463
+ export_query_filter = {
2464
+ "mode": "and",
2465
+ "filterGroups": filterGroups,
2466
+ "filters": [],
2467
+ }
2298
2468
  entities_list = self.export_entities_list(
2299
2469
  entity_type=entity_type,
2300
2470
  search=search,
2301
- filters=filters,
2471
+ filters=export_query_filter,
2302
2472
  orderBy=order_by,
2303
2473
  orderMode=order_mode,
2304
2474
  getAll=True,
@@ -2309,7 +2479,9 @@ class OpenCTIStix2:
2309
2479
  entity_bundle = self.prepare_export(
2310
2480
  self.generate_export(entity),
2311
2481
  mode,
2312
- max_marking_definition_entity,
2482
+ None,
2483
+ main_filter,
2484
+ access_filter,
2313
2485
  )
2314
2486
  if entity_bundle is not None:
2315
2487
  entity_bundle_filtered = self.filter_objects(uuids, entity_bundle)
@@ -2322,31 +2494,44 @@ class OpenCTIStix2:
2322
2494
  self,
2323
2495
  entities_list: [str],
2324
2496
  mode: str = "simple",
2325
- max_marking_definition: Dict = None,
2497
+ main_filter: Dict = None,
2498
+ access_filter: Dict = None,
2326
2499
  ) -> Dict:
2327
- max_marking_definition_entity = (
2328
- self.opencti.marking_definition.read(id=max_marking_definition)
2329
- if max_marking_definition is not None
2330
- else None
2500
+
2501
+ entity_data_sdo = self.opencti.stix_domain_object.list(filters=main_filter)
2502
+ entity_data_sco = self.opencti.stix_cyber_observable.list(filters=main_filter)
2503
+ entity_data_scr = self.opencti.stix_core_relationship.list(filters=main_filter)
2504
+ entity_data_ssr = self.opencti.stix_sighting_relationship.list(
2505
+ filters=main_filter
2506
+ )
2507
+
2508
+ entities_list = (
2509
+ entity_data_sdo + entity_data_sco + entity_data_scr + entity_data_ssr
2331
2510
  )
2332
2511
  bundle = {
2333
2512
  "type": "bundle",
2334
2513
  "id": "bundle--" + str(uuid.uuid4()),
2335
2514
  "objects": [],
2336
2515
  }
2516
+
2337
2517
  if entities_list is not None:
2338
2518
  uuids = []
2339
2519
  for entity in entities_list:
2340
2520
  entity_bundle = self.prepare_export(
2341
2521
  self.generate_export(entity),
2342
2522
  mode,
2343
- max_marking_definition_entity,
2523
+ None,
2524
+ main_filter,
2525
+ access_filter,
2344
2526
  )
2345
2527
  if entity_bundle is not None:
2346
2528
  entity_bundle_filtered = self.filter_objects(uuids, entity_bundle)
2347
2529
  for x in entity_bundle_filtered:
2348
2530
  uuids.append(x["id"])
2349
- bundle["objects"] = bundle["objects"] + entity_bundle_filtered
2531
+ bundle["objects"] = (
2532
+ bundle["objects"] + entity_bundle_filtered
2533
+ ) # unsupported operand type(s) for +: 'dict' and 'list'
2534
+
2350
2535
  return bundle
2351
2536
 
2352
2537
  def import_bundle(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pycti
3
- Version: 6.0.10
3
+ Version: 6.1.0
4
4
  Summary: Python API client for OpenCTI.
5
5
  Home-page: https://github.com/OpenCTI-Platform/client-python
6
6
  Author: Filigran
@@ -42,7 +42,7 @@ Requires-Dist: pre-commit~=3.7.0; extra == "dev"
42
42
  Requires-Dist: pytest-cases~=3.8.0; extra == "dev"
43
43
  Requires-Dist: pytest-cov~=5.0.0; extra == "dev"
44
44
  Requires-Dist: pytest_randomly~=3.15.0; extra == "dev"
45
- Requires-Dist: pytest~=8.1.1; extra == "dev"
45
+ Requires-Dist: pytest~=8.2.0; extra == "dev"
46
46
  Requires-Dist: types-python-dateutil~=2.9.0; extra == "dev"
47
47
  Requires-Dist: wheel~=0.43.0; extra == "dev"
48
48
  Provides-Extra: doc
@@ -24,7 +24,7 @@ pre-commit~=3.7.0
24
24
  pytest-cases~=3.8.0
25
25
  pytest-cov~=5.0.0
26
26
  pytest_randomly~=3.15.0
27
- pytest~=8.1.1
27
+ pytest~=8.2.0
28
28
  types-python-dateutil~=2.9.0
29
29
  wheel~=0.43.0
30
30
 
@@ -55,7 +55,7 @@ dev =
55
55
  pytest-cases~=3.8.0
56
56
  pytest-cov~=5.0.0
57
57
  pytest_randomly~=3.15.0
58
- pytest~=8.1.1
58
+ pytest~=8.2.0
59
59
  types-python-dateutil~=2.9.0
60
60
  wheel~=0.43.0
61
61
  doc =
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes