pycti 6.6.0__py3-none-any.whl → 6.6.1__py3-none-any.whl

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.

pycti/__init__.py CHANGED
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
- __version__ = "6.6.0"
2
+ __version__ = "6.6.1"
3
3
 
4
4
  from .api.opencti_api_client import OpenCTIApiClient
5
5
  from .api.opencti_api_connector import OpenCTIApiConnector
@@ -12,6 +12,9 @@ from .connector.opencti_connector_helper import (
12
12
  from .connector.opencti_metric_handler import OpenCTIMetricHandler
13
13
  from .entities.opencti_attack_pattern import AttackPattern
14
14
  from .entities.opencti_campaign import Campaign
15
+
16
+ # Administrative entities
17
+ from .entities.opencti_capability import Capability
15
18
  from .entities.opencti_case_incident import CaseIncident
16
19
  from .entities.opencti_case_rfi import CaseRfi
17
20
  from .entities.opencti_case_rft import CaseRft
@@ -21,6 +24,7 @@ from .entities.opencti_data_component import DataComponent
21
24
  from .entities.opencti_data_source import DataSource
22
25
  from .entities.opencti_external_reference import ExternalReference
23
26
  from .entities.opencti_feedback import Feedback
27
+ from .entities.opencti_group import Group
24
28
  from .entities.opencti_grouping import Grouping
25
29
  from .entities.opencti_identity import Identity
26
30
  from .entities.opencti_incident import Incident
@@ -37,6 +41,8 @@ from .entities.opencti_note import Note
37
41
  from .entities.opencti_observed_data import ObservedData
38
42
  from .entities.opencti_opinion import Opinion
39
43
  from .entities.opencti_report import Report
44
+ from .entities.opencti_role import Role
45
+ from .entities.opencti_settings import Settings
40
46
  from .entities.opencti_stix_core_relationship import StixCoreRelationship
41
47
  from .entities.opencti_stix_cyber_observable import StixCyberObservable
42
48
  from .entities.opencti_stix_domain_object import StixDomainObject
@@ -50,6 +56,7 @@ from .entities.opencti_threat_actor import ThreatActor
50
56
  from .entities.opencti_threat_actor_group import ThreatActorGroup
51
57
  from .entities.opencti_threat_actor_individual import ThreatActorIndividual
52
58
  from .entities.opencti_tool import Tool
59
+ from .entities.opencti_user import User
53
60
  from .entities.opencti_vulnerability import Vulnerability
54
61
  from .utils.constants import (
55
62
  CustomObjectCaseIncident,
@@ -151,4 +158,9 @@ __all__ = [
151
158
  "STIX_EXT_MITRE",
152
159
  "STIX_EXT_OCTI_SCO",
153
160
  "STIX_EXT_OCTI",
161
+ "Capability",
162
+ "Role",
163
+ "Group",
164
+ "User",
165
+ "Settings",
154
166
  ]
@@ -14,6 +14,7 @@ from pycti.api.opencti_api_playbook import OpenCTIApiPlaybook
14
14
  from pycti.api.opencti_api_work import OpenCTIApiWork
15
15
  from pycti.entities.opencti_attack_pattern import AttackPattern
16
16
  from pycti.entities.opencti_campaign import Campaign
17
+ from pycti.entities.opencti_capability import Capability
17
18
  from pycti.entities.opencti_case_incident import CaseIncident
18
19
  from pycti.entities.opencti_case_rfi import CaseRfi
19
20
  from pycti.entities.opencti_case_rft import CaseRft
@@ -24,6 +25,7 @@ from pycti.entities.opencti_data_source import DataSource
24
25
  from pycti.entities.opencti_event import Event
25
26
  from pycti.entities.opencti_external_reference import ExternalReference
26
27
  from pycti.entities.opencti_feedback import Feedback
28
+ from pycti.entities.opencti_group import Group
27
29
  from pycti.entities.opencti_grouping import Grouping
28
30
  from pycti.entities.opencti_identity import Identity
29
31
  from pycti.entities.opencti_incident import Incident
@@ -42,6 +44,8 @@ from pycti.entities.opencti_note import Note
42
44
  from pycti.entities.opencti_observed_data import ObservedData
43
45
  from pycti.entities.opencti_opinion import Opinion
44
46
  from pycti.entities.opencti_report import Report
47
+ from pycti.entities.opencti_role import Role
48
+ from pycti.entities.opencti_settings import Settings
45
49
  from pycti.entities.opencti_stix import Stix
46
50
  from pycti.entities.opencti_stix_core_object import StixCoreObject
47
51
  from pycti.entities.opencti_stix_core_relationship import StixCoreRelationship
@@ -59,6 +63,7 @@ from pycti.entities.opencti_threat_actor import ThreatActor
59
63
  from pycti.entities.opencti_threat_actor_group import ThreatActorGroup
60
64
  from pycti.entities.opencti_threat_actor_individual import ThreatActorIndividual
61
65
  from pycti.entities.opencti_tool import Tool
66
+ from pycti.entities.opencti_user import User
62
67
  from pycti.entities.opencti_vocabulary import Vocabulary
63
68
  from pycti.entities.opencti_vulnerability import Vulnerability
64
69
  from pycti.utils.opencti_logger import logger
@@ -128,6 +133,7 @@ class OpenCTIApiClient:
128
133
  # Configure logger
129
134
  self.logger_class = logger(log_level.upper(), json_logging)
130
135
  self.app_logger = self.logger_class("api")
136
+ self.admin_logger = self.logger_class("admin")
131
137
 
132
138
  # Define API
133
139
  self.api_token = token
@@ -198,6 +204,13 @@ class OpenCTIApiClient:
198
204
  self.grouping = Grouping(self)
199
205
  self.indicator = Indicator(self)
200
206
 
207
+ # Admin functionality
208
+ self.capability = Capability(self)
209
+ self.role = Role(self)
210
+ self.group = Group(self)
211
+ self.user = User(self)
212
+ self.settings = Settings(self)
213
+
201
214
  # Check if openCTI is available
202
215
  if perform_health_check and not self.health_check():
203
216
  raise ValueError(
@@ -291,6 +291,11 @@ class ListenQueue(threading.Thread):
291
291
  {"tag": method.delivery_tag},
292
292
  )
293
293
 
294
+ def _set_draft_id(self, draft_id):
295
+ self.helper.draft_id = draft_id
296
+ self.helper.api.set_draft_id(draft_id)
297
+ self.helper.api_impersonate.set_draft_id(draft_id)
298
+
294
299
  def _data_handler(self, json_data) -> None:
295
300
  # Execute the callback
296
301
  try:
@@ -298,6 +303,7 @@ class ListenQueue(threading.Thread):
298
303
  entity_id = event_data.get("entity_id")
299
304
  entity_type = event_data.get("entity_type")
300
305
  validation_mode = event_data.get("validation_mode", "workbench")
306
+ force_validation = event_data.get("force_validation", False)
301
307
  # Set the API headers
302
308
  internal_data = json_data["internal"]
303
309
  work_id = internal_data["work_id"]
@@ -305,9 +311,9 @@ class ListenQueue(threading.Thread):
305
311
  self.helper.work_id = work_id
306
312
 
307
313
  self.helper.validation_mode = validation_mode
308
- self.helper.draft_id = draft_id
309
- self.helper.api.set_draft_id(draft_id)
310
- self.helper.api_impersonate.set_draft_id(draft_id)
314
+ self.helper.force_validation = force_validation
315
+
316
+ self._set_draft_id(draft_id)
311
317
 
312
318
  self.helper.playbook = None
313
319
  self.helper.enrichment_shared_organizations = None
@@ -404,12 +410,14 @@ class ListenQueue(threading.Thread):
404
410
  message = self.callback(event_data)
405
411
  if work_id:
406
412
  self.helper.api.work.to_processed(work_id, message)
413
+ self._set_draft_id("")
407
414
 
408
415
  except Exception as e: # pylint: disable=broad-except
409
416
  self.helper.metric.inc("error_count")
410
417
  self.helper.connector_logger.error(
411
418
  "Error in message processing, reporting error to API"
412
419
  )
420
+ self._set_draft_id("")
413
421
  if work_id:
414
422
  try:
415
423
  self.helper.api.work.to_processed(work_id, str(e), True)
@@ -1114,6 +1122,7 @@ class OpenCTIConnectorHelper: # pylint: disable=too-many-public-methods
1114
1122
  )
1115
1123
  self.work_id = None
1116
1124
  self.validation_mode = "workbench"
1125
+ self.force_validation = False
1117
1126
  self.draft_id = None
1118
1127
  self.playbook = None
1119
1128
  self.enrichment_shared_organizations = None
@@ -1764,6 +1773,7 @@ class OpenCTIConnectorHelper: # pylint: disable=too-many-public-methods
1764
1773
  update = kwargs.get("update", False)
1765
1774
  event_version = kwargs.get("event_version", None)
1766
1775
  bypass_validation = kwargs.get("bypass_validation", False)
1776
+ force_validation = kwargs.get("force_validation", self.force_validation)
1767
1777
  entity_id = kwargs.get("entity_id", None)
1768
1778
  file_markings = kwargs.get("file_markings", None)
1769
1779
  file_name = kwargs.get("file_name", None)
@@ -1826,7 +1836,11 @@ class OpenCTIConnectorHelper: # pylint: disable=too-many-public-methods
1826
1836
  if not file_name and work_id:
1827
1837
  file_name = f"{work_id}.json"
1828
1838
 
1829
- if self.connect_validate_before_import and not bypass_validation and file_name:
1839
+ if (
1840
+ (self.connect_validate_before_import or force_validation)
1841
+ and not bypass_validation
1842
+ and file_name
1843
+ ):
1830
1844
  if validation_mode == "workbench":
1831
1845
  self.api.upload_pending_file(
1832
1846
  file_name=file_name,
@@ -1843,6 +1857,8 @@ class OpenCTIConnectorHelper: # pylint: disable=too-many-public-methods
1843
1857
  if not draft_id:
1844
1858
  self.connector_logger.error("Draft couldn't be created")
1845
1859
  return []
1860
+ if work_id:
1861
+ self.api.work.add_draft_context(work_id, draft_id)
1846
1862
 
1847
1863
  # If directory setup, write the bundle to the target directory
1848
1864
  if bundle_send_to_directory and bundle_send_to_directory_path is not None:
@@ -1916,8 +1932,10 @@ class OpenCTIConnectorHelper: # pylint: disable=too-many-public-methods
1916
1932
  raise ValueError("Nothing to import")
1917
1933
 
1918
1934
  if bundle_send_to_queue:
1919
- if work_id and draft_id:
1920
- self.api.work.add_draft_context(work_id, draft_id)
1935
+ if work_id:
1936
+ self.api.work.add_expectations(work_id, expectations_number)
1937
+ if draft_id:
1938
+ self.api.work.add_draft_context(work_id, draft_id)
1921
1939
  if entities_types is None:
1922
1940
  entities_types = []
1923
1941
  if self.queue_protocol == "amqp":
@@ -0,0 +1,52 @@
1
+ from typing import Dict, List
2
+
3
+
4
+ class Capability:
5
+ """Represents a role capability on the OpenCTI platform
6
+
7
+ See the properties attribute to understand which properties are fetched by
8
+ default from the graphql queries.
9
+ """
10
+
11
+ def __init__(self, opencti):
12
+ self.opencti = opencti
13
+ self.properties = """
14
+ id
15
+ standard_id
16
+ entity_type
17
+ parent_types
18
+ name
19
+ description
20
+ attribute_order
21
+ created_at
22
+ updated_at
23
+ """
24
+
25
+ def list(self, **kwargs) -> List[Dict]:
26
+ """Lists all capabilities available on the platform
27
+
28
+ :param customAttributes: Custom attributes to retrieve from the GraphQL
29
+ query.
30
+ :type customAttributes: str, optional
31
+ :return: List of capabilities
32
+ :rtype: List[Dict]
33
+ """
34
+ custom_attributes = kwargs.get("customAttributes")
35
+ self.opencti.admin_logger.info("Listing capabilities")
36
+ query = (
37
+ """
38
+ query CapabilityList {
39
+ capabilities {
40
+ edges {
41
+ node {
42
+ """
43
+ + (self.properties if custom_attributes is None else custom_attributes)
44
+ + """
45
+ }
46
+ }
47
+ }
48
+ }
49
+ """
50
+ )
51
+ result = self.opencti.query(query)
52
+ return self.opencti.process_multiple(result["data"]["capabilities"])