pycti 6.7.20__py3-none-any.whl → 6.8.0__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 +1 -1
- pycti/connector/opencti_connector_helper.py +190 -3
- pycti/connector/opencti_metric_handler.py +44 -15
- pycti/entities/opencti_attack_pattern.py +32 -6
- pycti/entities/opencti_campaign.py +30 -6
- pycti/entities/opencti_case_incident.py +7 -0
- pycti/entities/opencti_case_rfi.py +7 -0
- pycti/entities/opencti_case_rft.py +7 -0
- pycti/entities/opencti_channel.py +7 -0
- pycti/entities/opencti_course_of_action.py +7 -0
- pycti/entities/opencti_data_component.py +7 -0
- pycti/entities/opencti_data_source.py +7 -0
- pycti/entities/opencti_event.py +32 -6
- pycti/entities/opencti_external_reference.py +8 -0
- pycti/entities/opencti_feedback.py +7 -0
- pycti/entities/opencti_grouping.py +7 -0
- pycti/entities/opencti_identity.py +34 -6
- pycti/entities/opencti_incident.py +7 -0
- pycti/entities/opencti_indicator.py +19 -5
- pycti/entities/opencti_intrusion_set.py +58 -19
- pycti/entities/opencti_kill_chain_phase.py +7 -0
- pycti/entities/opencti_label.py +7 -0
- pycti/entities/opencti_language.py +7 -0
- pycti/entities/opencti_location.py +7 -0
- pycti/entities/opencti_malware.py +60 -18
- pycti/entities/opencti_malware_analysis.py +7 -0
- pycti/entities/opencti_marking_definition.py +7 -0
- pycti/entities/opencti_narrative.py +7 -0
- pycti/entities/opencti_note.py +7 -0
- pycti/entities/opencti_observed_data.py +7 -0
- pycti/entities/opencti_opinion.py +7 -0
- pycti/entities/opencti_report.py +7 -0
- pycti/entities/opencti_stix.py +7 -0
- pycti/entities/opencti_stix_core_object.py +8 -0
- pycti/entities/opencti_stix_core_relationship.py +7 -0
- pycti/entities/opencti_stix_cyber_observable.py +9 -0
- pycti/entities/opencti_stix_domain_object.py +8 -0
- pycti/entities/opencti_stix_nested_ref_relationship.py +7 -0
- pycti/entities/opencti_stix_object_or_stix_relationship.py +7 -0
- pycti/entities/opencti_stix_sighting_relationship.py +7 -0
- pycti/entities/opencti_task.py +7 -0
- pycti/entities/opencti_tool.py +52 -18
- pycti/entities/opencti_vocabulary.py +7 -0
- pycti/entities/opencti_vulnerability.py +7 -0
- pycti/utils/opencti_logger.py +57 -0
- pycti/utils/opencti_stix2.py +41 -0
- pycti/utils/opencti_stix2_splitter.py +5 -0
- pycti/utils/opencti_stix2_utils.py +41 -6
- {pycti-6.7.20.dist-info → pycti-6.8.0.dist-info}/METADATA +1 -1
- pycti-6.8.0.dist-info/RECORD +86 -0
- pycti-6.7.20.dist-info/RECORD +0 -86
- {pycti-6.7.20.dist-info → pycti-6.8.0.dist-info}/WHEEL +0 -0
- {pycti-6.7.20.dist-info → pycti-6.8.0.dist-info}/licenses/LICENSE +0 -0
- {pycti-6.7.20.dist-info → pycti-6.8.0.dist-info}/top_level.txt +0 -0
pycti/entities/opencti_report.py
CHANGED
|
@@ -9,6 +9,13 @@ from stix2.canonicalization.Canonicalize import canonicalize
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class Report:
|
|
12
|
+
"""Main Report class for OpenCTI
|
|
13
|
+
|
|
14
|
+
Manages threat intelligence reports in the OpenCTI platform.
|
|
15
|
+
|
|
16
|
+
:param opencti: instance of :py:class:`~pycti.api.opencti_api_client.OpenCTIApiClient`
|
|
17
|
+
"""
|
|
18
|
+
|
|
12
19
|
def __init__(self, opencti):
|
|
13
20
|
self.opencti = opencti
|
|
14
21
|
self.properties = """
|
pycti/entities/opencti_stix.py
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
class Stix:
|
|
2
|
+
"""Main Stix class for OpenCTI
|
|
3
|
+
|
|
4
|
+
Provides generic STIX object operations in the OpenCTI platform.
|
|
5
|
+
|
|
6
|
+
:param opencti: instance of :py:class:`~pycti.api.opencti_api_client.OpenCTIApiClient`
|
|
7
|
+
"""
|
|
8
|
+
|
|
2
9
|
def __init__(self, opencti):
|
|
3
10
|
self.opencti = opencti
|
|
4
11
|
|
|
@@ -3,6 +3,14 @@ import json
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class StixCoreObject:
|
|
6
|
+
"""Main StixCoreObject class for OpenCTI
|
|
7
|
+
|
|
8
|
+
Base class for managing STIX core objects in the OpenCTI platform.
|
|
9
|
+
|
|
10
|
+
:param opencti: instance of :py:class:`~pycti.api.opencti_api_client.OpenCTIApiClient`
|
|
11
|
+
:param file: file handling configuration
|
|
12
|
+
"""
|
|
13
|
+
|
|
6
14
|
def __init__(self, opencti, file):
|
|
7
15
|
self.opencti = opencti
|
|
8
16
|
self.file = file
|
|
@@ -7,6 +7,13 @@ from stix2.canonicalization.Canonicalize import canonicalize
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class StixCoreRelationship:
|
|
10
|
+
"""Main StixCoreRelationship class for OpenCTI
|
|
11
|
+
|
|
12
|
+
Manages STIX relationships between entities in the OpenCTI platform.
|
|
13
|
+
|
|
14
|
+
:param opencti: instance of :py:class:`~pycti.api.opencti_api_client.OpenCTIApiClient`
|
|
15
|
+
"""
|
|
16
|
+
|
|
10
17
|
def __init__(self, opencti):
|
|
11
18
|
self.opencti = opencti
|
|
12
19
|
self.properties = """
|
|
@@ -17,6 +17,15 @@ from .stix_cyber_observable.opencti_stix_cyber_observable_properties import (
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class StixCyberObservable(StixCyberObservableDeprecatedMixin):
|
|
20
|
+
"""Main StixCyberObservable class for OpenCTI
|
|
21
|
+
|
|
22
|
+
Manages STIX cyber observables (indicators of compromise) in the OpenCTI platform.
|
|
23
|
+
Note: Deprecated methods are available through StixCyberObservableDeprecatedMixin.
|
|
24
|
+
|
|
25
|
+
:param opencti: instance of :py:class:`~pycti.api.opencti_api_client.OpenCTIApiClient`
|
|
26
|
+
:param file: file handling configuration
|
|
27
|
+
"""
|
|
28
|
+
|
|
20
29
|
def __init__(self, opencti, file):
|
|
21
30
|
|
|
22
31
|
self.opencti = opencti
|
|
@@ -7,6 +7,14 @@ import magic
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class StixDomainObject:
|
|
10
|
+
"""Main StixDomainObject class for OpenCTI
|
|
11
|
+
|
|
12
|
+
Manages STIX Domain Objects in the OpenCTI platform.
|
|
13
|
+
|
|
14
|
+
:param opencti: instance of :py:class:`~pycti.api.opencti_api_client.OpenCTIApiClient`
|
|
15
|
+
:param file: file handling configuration
|
|
16
|
+
"""
|
|
17
|
+
|
|
10
18
|
def __init__(self, opencti, file):
|
|
11
19
|
self.opencti = opencti
|
|
12
20
|
self.file = file
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
class StixNestedRefRelationship:
|
|
2
|
+
"""Main StixNestedRefRelationship class for OpenCTI
|
|
3
|
+
|
|
4
|
+
Manages nested reference relationships in the OpenCTI platform.
|
|
5
|
+
|
|
6
|
+
:param opencti: instance of :py:class:`~pycti.api.opencti_api_client.OpenCTIApiClient`
|
|
7
|
+
"""
|
|
8
|
+
|
|
2
9
|
def __init__(self, opencti):
|
|
3
10
|
self.opencti = opencti
|
|
4
11
|
self.properties = """
|
|
@@ -2,6 +2,13 @@ import json
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class StixObjectOrStixRelationship:
|
|
5
|
+
"""Main StixObjectOrStixRelationship class for OpenCTI
|
|
6
|
+
|
|
7
|
+
Manages generic STIX objects and relationships in the OpenCTI platform.
|
|
8
|
+
|
|
9
|
+
:param opencti: instance of :py:class:`~pycti.api.opencti_api_client.OpenCTIApiClient`
|
|
10
|
+
"""
|
|
11
|
+
|
|
5
12
|
def __init__(self, opencti):
|
|
6
13
|
self.opencti = opencti
|
|
7
14
|
self.properties = """
|
|
@@ -7,6 +7,13 @@ from stix2.canonicalization.Canonicalize import canonicalize
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class StixSightingRelationship:
|
|
10
|
+
"""Main StixSightingRelationship class for OpenCTI
|
|
11
|
+
|
|
12
|
+
Manages STIX sighting relationships in the OpenCTI platform.
|
|
13
|
+
|
|
14
|
+
:param opencti: instance of :py:class:`~pycti.api.opencti_api_client.OpenCTIApiClient`
|
|
15
|
+
"""
|
|
16
|
+
|
|
10
17
|
def __init__(self, opencti):
|
|
11
18
|
self.opencti = opencti
|
|
12
19
|
self.properties = """
|
pycti/entities/opencti_task.py
CHANGED
|
@@ -7,6 +7,13 @@ from stix2.canonicalization.Canonicalize import canonicalize
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class Task:
|
|
10
|
+
"""Main Task class for OpenCTI
|
|
11
|
+
|
|
12
|
+
Manages tasks and to-do items in the OpenCTI platform.
|
|
13
|
+
|
|
14
|
+
:param opencti: instance of :py:class:`~pycti.api.opencti_api_client.OpenCTIApiClient`
|
|
15
|
+
"""
|
|
16
|
+
|
|
10
17
|
def __init__(self, opencti):
|
|
11
18
|
self.opencti = opencti
|
|
12
19
|
self.properties = """
|
pycti/entities/opencti_tool.py
CHANGED
|
@@ -7,6 +7,13 @@ from stix2.canonicalization.Canonicalize import canonicalize
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class Tool:
|
|
10
|
+
"""Main Tool class for OpenCTI
|
|
11
|
+
|
|
12
|
+
Manages tools used by threat actors in the OpenCTI platform.
|
|
13
|
+
|
|
14
|
+
:param opencti: instance of :py:class:`~pycti.api.opencti_api_client.OpenCTIApiClient`
|
|
15
|
+
"""
|
|
16
|
+
|
|
10
17
|
def __init__(self, opencti):
|
|
11
18
|
self.opencti = opencti
|
|
12
19
|
self.properties = """
|
|
@@ -136,6 +143,13 @@ class Tool:
|
|
|
136
143
|
|
|
137
144
|
@staticmethod
|
|
138
145
|
def generate_id(name):
|
|
146
|
+
"""Generate a STIX ID for a Tool.
|
|
147
|
+
|
|
148
|
+
:param name: The name of the tool
|
|
149
|
+
:type name: str
|
|
150
|
+
:return: STIX ID for the tool
|
|
151
|
+
:rtype: str
|
|
152
|
+
"""
|
|
139
153
|
name = name.lower().strip()
|
|
140
154
|
data = {"name": name}
|
|
141
155
|
data = canonicalize(data, utf8=False)
|
|
@@ -144,19 +158,30 @@ class Tool:
|
|
|
144
158
|
|
|
145
159
|
@staticmethod
|
|
146
160
|
def generate_id_from_data(data):
|
|
161
|
+
"""Generate a STIX ID from tool data.
|
|
162
|
+
|
|
163
|
+
:param data: Dictionary containing 'name' key
|
|
164
|
+
:type data: dict
|
|
165
|
+
:return: STIX ID for the tool
|
|
166
|
+
:rtype: str
|
|
167
|
+
"""
|
|
147
168
|
return Tool.generate_id(data["name"])
|
|
148
169
|
|
|
149
|
-
|
|
150
|
-
List Tool objects
|
|
170
|
+
def list(self, **kwargs):
|
|
171
|
+
"""List Tool objects.
|
|
151
172
|
|
|
152
173
|
:param filters: the filters to apply
|
|
153
174
|
:param search: the search keyword
|
|
154
175
|
:param first: return the first n rows from the after ID (or the beginning if not set)
|
|
155
176
|
:param after: ID of the first row for pagination
|
|
156
|
-
:
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
177
|
+
:param orderBy: field to order results by
|
|
178
|
+
:param orderMode: ordering mode (asc/desc)
|
|
179
|
+
:param customAttributes: custom attributes to return
|
|
180
|
+
:param getAll: whether to retrieve all results
|
|
181
|
+
:param withPagination: whether to include pagination info
|
|
182
|
+
:return: List of Tool objects
|
|
183
|
+
:rtype: list
|
|
184
|
+
"""
|
|
160
185
|
filters = kwargs.get("filters", None)
|
|
161
186
|
search = kwargs.get("search", None)
|
|
162
187
|
first = kwargs.get("first", 100)
|
|
@@ -229,15 +254,15 @@ class Tool:
|
|
|
229
254
|
result["data"]["tools"], with_pagination
|
|
230
255
|
)
|
|
231
256
|
|
|
232
|
-
|
|
233
|
-
Read a Tool object
|
|
257
|
+
def read(self, **kwargs):
|
|
258
|
+
"""Read a Tool object.
|
|
234
259
|
|
|
235
260
|
:param id: the id of the Tool
|
|
236
261
|
:param filters: the filters to apply if no id provided
|
|
237
|
-
:
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
262
|
+
:param customAttributes: custom attributes to return
|
|
263
|
+
:return: Tool object
|
|
264
|
+
:rtype: dict or None
|
|
265
|
+
"""
|
|
241
266
|
id = kwargs.get("id", None)
|
|
242
267
|
filters = kwargs.get("filters", None)
|
|
243
268
|
custom_attributes = kwargs.get("customAttributes", None)
|
|
@@ -272,14 +297,23 @@ class Tool:
|
|
|
272
297
|
)
|
|
273
298
|
return None
|
|
274
299
|
|
|
275
|
-
|
|
276
|
-
Create a Tool object
|
|
300
|
+
def create(self, **kwargs):
|
|
301
|
+
"""Create a Tool object.
|
|
277
302
|
|
|
278
303
|
:param name: the name of the Tool
|
|
279
|
-
:
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
304
|
+
:param description: description of the tool
|
|
305
|
+
:param aliases: list of aliases
|
|
306
|
+
:param tool_types: types of tool
|
|
307
|
+
:param tool_version: version of the tool
|
|
308
|
+
:param killChainPhases: kill chain phases
|
|
309
|
+
:param createdBy: creator identity
|
|
310
|
+
:param objectMarking: marking definitions
|
|
311
|
+
:param objectLabel: labels
|
|
312
|
+
:param externalReferences: external references
|
|
313
|
+
:param update: whether to update existing tool
|
|
314
|
+
:return: Tool object
|
|
315
|
+
:rtype: dict or None
|
|
316
|
+
"""
|
|
283
317
|
stix_id = kwargs.get("stix_id", None)
|
|
284
318
|
created_by = kwargs.get("createdBy", None)
|
|
285
319
|
object_marking = kwargs.get("objectMarking", None)
|
|
@@ -5,6 +5,13 @@ from stix2.canonicalization.Canonicalize import canonicalize
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class Vocabulary:
|
|
8
|
+
"""Main Vocabulary class for OpenCTI
|
|
9
|
+
|
|
10
|
+
Manages vocabularies and controlled vocabularies in the OpenCTI platform.
|
|
11
|
+
|
|
12
|
+
:param opencti: instance of :py:class:`~pycti.api.opencti_api_client.OpenCTIApiClient`
|
|
13
|
+
"""
|
|
14
|
+
|
|
8
15
|
def __init__(self, opencti):
|
|
9
16
|
self.opencti = opencti
|
|
10
17
|
self.properties = """
|
|
@@ -7,6 +7,13 @@ from stix2.canonicalization.Canonicalize import canonicalize
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class Vulnerability:
|
|
10
|
+
"""Main Vulnerability class for OpenCTI
|
|
11
|
+
|
|
12
|
+
Manages vulnerability information including CVE data in the OpenCTI platform.
|
|
13
|
+
|
|
14
|
+
:param opencti: instance of :py:class:`~pycti.api.opencti_api_client.OpenCTIApiClient`
|
|
15
|
+
"""
|
|
16
|
+
|
|
10
17
|
def __init__(self, opencti):
|
|
11
18
|
self.opencti = opencti
|
|
12
19
|
self.properties = """
|
pycti/utils/opencti_logger.py
CHANGED
|
@@ -5,7 +5,15 @@ from pythonjsonlogger import jsonlogger
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class CustomJsonFormatter(jsonlogger.JsonFormatter):
|
|
8
|
+
"""Custom JSON formatter for structured logging."""
|
|
9
|
+
|
|
8
10
|
def add_fields(self, log_record, record, message_dict):
|
|
11
|
+
"""Add custom fields to the log record.
|
|
12
|
+
|
|
13
|
+
:param log_record: The log record dictionary
|
|
14
|
+
:param record: The LogRecord instance
|
|
15
|
+
:param message_dict: The message dictionary
|
|
16
|
+
"""
|
|
9
17
|
super(CustomJsonFormatter, self).add_fields(log_record, record, message_dict)
|
|
10
18
|
if not log_record.get("timestamp"):
|
|
11
19
|
# This doesn't use record.created, so it is slightly off
|
|
@@ -18,6 +26,14 @@ class CustomJsonFormatter(jsonlogger.JsonFormatter):
|
|
|
18
26
|
|
|
19
27
|
|
|
20
28
|
def logger(level, json_logging=True):
|
|
29
|
+
"""Create a logger with JSON or standard formatting.
|
|
30
|
+
|
|
31
|
+
:param level: Logging level (e.g., logging.INFO, logging.DEBUG)
|
|
32
|
+
:param json_logging: Whether to use JSON formatting for logs
|
|
33
|
+
:type json_logging: bool
|
|
34
|
+
:return: AppLogger class
|
|
35
|
+
:rtype: class
|
|
36
|
+
"""
|
|
21
37
|
# Exceptions
|
|
22
38
|
logging.getLogger("urllib3").setLevel(logging.WARNING)
|
|
23
39
|
logging.getLogger("pika").setLevel(logging.ERROR)
|
|
@@ -37,22 +53,63 @@ def logger(level, json_logging=True):
|
|
|
37
53
|
|
|
38
54
|
@staticmethod
|
|
39
55
|
def prepare_meta(meta=None):
|
|
56
|
+
"""Prepare metadata for logging.
|
|
57
|
+
|
|
58
|
+
:param meta: Metadata dictionary or None
|
|
59
|
+
:type meta: dict or None
|
|
60
|
+
:return: Formatted metadata or None
|
|
61
|
+
:rtype: dict or None
|
|
62
|
+
"""
|
|
40
63
|
return None if meta is None else {"attributes": meta}
|
|
41
64
|
|
|
42
65
|
@staticmethod
|
|
43
66
|
def setup_logger_level(lib, log_level):
|
|
67
|
+
"""Set the logging level for a specific library.
|
|
68
|
+
|
|
69
|
+
:param lib: Library name
|
|
70
|
+
:type lib: str
|
|
71
|
+
:param log_level: Logging level to set
|
|
72
|
+
"""
|
|
44
73
|
logging.getLogger(lib).setLevel(log_level)
|
|
45
74
|
|
|
46
75
|
def debug(self, message, meta=None):
|
|
76
|
+
"""Log a debug message.
|
|
77
|
+
|
|
78
|
+
:param message: Message to log
|
|
79
|
+
:type message: str
|
|
80
|
+
:param meta: Optional metadata to include
|
|
81
|
+
:type meta: dict or None
|
|
82
|
+
"""
|
|
47
83
|
self.local_logger.debug(message, extra=AppLogger.prepare_meta(meta))
|
|
48
84
|
|
|
49
85
|
def info(self, message, meta=None):
|
|
86
|
+
"""Log an info message.
|
|
87
|
+
|
|
88
|
+
:param message: Message to log
|
|
89
|
+
:type message: str
|
|
90
|
+
:param meta: Optional metadata to include
|
|
91
|
+
:type meta: dict or None
|
|
92
|
+
"""
|
|
50
93
|
self.local_logger.info(message, extra=AppLogger.prepare_meta(meta))
|
|
51
94
|
|
|
52
95
|
def warning(self, message, meta=None):
|
|
96
|
+
"""Log a warning message.
|
|
97
|
+
|
|
98
|
+
:param message: Message to log
|
|
99
|
+
:type message: str
|
|
100
|
+
:param meta: Optional metadata to include
|
|
101
|
+
:type meta: dict or None
|
|
102
|
+
"""
|
|
53
103
|
self.local_logger.warning(message, extra=AppLogger.prepare_meta(meta))
|
|
54
104
|
|
|
55
105
|
def error(self, message, meta=None):
|
|
106
|
+
"""Log an error message with exception info.
|
|
107
|
+
|
|
108
|
+
:param message: Message to log
|
|
109
|
+
:type message: str
|
|
110
|
+
:param meta: Optional metadata to include
|
|
111
|
+
:type meta: dict or None
|
|
112
|
+
"""
|
|
56
113
|
# noinspection PyTypeChecker
|
|
57
114
|
self.local_logger.error(
|
|
58
115
|
message, exc_info=1, extra=AppLogger.prepare_meta(meta)
|
pycti/utils/opencti_stix2.py
CHANGED
|
@@ -98,6 +98,11 @@ class OpenCTIStix2:
|
|
|
98
98
|
######### UTILS
|
|
99
99
|
# region utils
|
|
100
100
|
def unknown_type(self, stix_object: Dict) -> None:
|
|
101
|
+
"""Log an error for unknown STIX object types.
|
|
102
|
+
|
|
103
|
+
:param stix_object: STIX object with unknown type
|
|
104
|
+
:type stix_object: Dict
|
|
105
|
+
"""
|
|
101
106
|
self.opencti.app_logger.error(
|
|
102
107
|
"Unknown object type, doing nothing...", {"type": stix_object["type"]}
|
|
103
108
|
)
|
|
@@ -116,6 +121,13 @@ class OpenCTIStix2:
|
|
|
116
121
|
return None
|
|
117
122
|
|
|
118
123
|
def format_date(self, date: Any = None) -> str:
|
|
124
|
+
"""Format a date to ISO 8601 string format.
|
|
125
|
+
|
|
126
|
+
:param date: Date to format (various formats supported)
|
|
127
|
+
:type date: Any
|
|
128
|
+
:return: ISO 8601 formatted date string
|
|
129
|
+
:rtype: str
|
|
130
|
+
"""
|
|
119
131
|
"""converts multiple input date formats to OpenCTI style dates
|
|
120
132
|
|
|
121
133
|
:param date: input date
|
|
@@ -814,6 +826,11 @@ class OpenCTIStix2:
|
|
|
814
826
|
|
|
815
827
|
# Please use get_reader instead of this definition
|
|
816
828
|
def get_readers(self):
|
|
829
|
+
"""Get a dictionary mapping entity types to their read methods.
|
|
830
|
+
|
|
831
|
+
:return: Dictionary mapping entity types to read functions
|
|
832
|
+
:rtype: dict
|
|
833
|
+
"""
|
|
817
834
|
return {
|
|
818
835
|
"Attack-Pattern": self.opencti.attack_pattern.read,
|
|
819
836
|
"Campaign": self.opencti.campaign.read,
|
|
@@ -861,6 +878,13 @@ class OpenCTIStix2:
|
|
|
861
878
|
}
|
|
862
879
|
|
|
863
880
|
def get_reader(self, entity_type: str):
|
|
881
|
+
"""Get the appropriate reader function for a given entity type.
|
|
882
|
+
|
|
883
|
+
:param entity_type: Type of the entity
|
|
884
|
+
:type entity_type: str
|
|
885
|
+
:return: Reader function for the entity type
|
|
886
|
+
:rtype: callable or None
|
|
887
|
+
"""
|
|
864
888
|
# Map types
|
|
865
889
|
if entity_type == "StixFile":
|
|
866
890
|
entity_type = "File"
|
|
@@ -881,6 +905,11 @@ class OpenCTIStix2:
|
|
|
881
905
|
# endregion
|
|
882
906
|
|
|
883
907
|
def get_stix_helper(self):
|
|
908
|
+
"""Get a dictionary mapping STIX types to their helper functions.
|
|
909
|
+
|
|
910
|
+
:return: Dictionary mapping STIX types to generate_id functions
|
|
911
|
+
:rtype: dict
|
|
912
|
+
"""
|
|
884
913
|
# Import
|
|
885
914
|
return {
|
|
886
915
|
# entities
|
|
@@ -929,6 +958,11 @@ class OpenCTIStix2:
|
|
|
929
958
|
}
|
|
930
959
|
|
|
931
960
|
def get_internal_helper(self):
|
|
961
|
+
"""Get a dictionary mapping internal types to their helper functions.
|
|
962
|
+
|
|
963
|
+
:return: Dictionary mapping internal types to generate_id functions
|
|
964
|
+
:rtype: dict
|
|
965
|
+
"""
|
|
932
966
|
# Import
|
|
933
967
|
return {
|
|
934
968
|
"user": self.opencti.user,
|
|
@@ -947,6 +981,13 @@ class OpenCTIStix2:
|
|
|
947
981
|
}
|
|
948
982
|
|
|
949
983
|
def generate_standard_id_from_stix(self, data):
|
|
984
|
+
"""Generate a standard ID from STIX data.
|
|
985
|
+
|
|
986
|
+
:param data: STIX data dictionary
|
|
987
|
+
:type data: dict
|
|
988
|
+
:return: Generated standard ID or None
|
|
989
|
+
:rtype: str or None
|
|
990
|
+
"""
|
|
950
991
|
stix_helpers = self.get_stix_helper()
|
|
951
992
|
helper = stix_helpers.get(data["type"])
|
|
952
993
|
return helper.generate_id_from_data(data)
|
|
@@ -34,6 +34,11 @@ def is_id_supported(key):
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
class OpenCTIStix2Splitter:
|
|
37
|
+
"""STIX2 bundle splitter for OpenCTI
|
|
38
|
+
|
|
39
|
+
Splits large STIX2 bundles into smaller chunks for processing.
|
|
40
|
+
"""
|
|
41
|
+
|
|
37
42
|
def __init__(self):
|
|
38
43
|
self.cache_index = {}
|
|
39
44
|
self.cache_refs = {}
|
|
@@ -150,8 +150,20 @@ OBSERVABLES_VALUE_INT = [
|
|
|
150
150
|
|
|
151
151
|
|
|
152
152
|
class OpenCTIStix2Utils:
|
|
153
|
+
"""Utility class for STIX2 operations in OpenCTI
|
|
154
|
+
|
|
155
|
+
Provides helper methods for STIX2 conversions and pattern generation.
|
|
156
|
+
"""
|
|
157
|
+
|
|
153
158
|
@staticmethod
|
|
154
159
|
def stix_observable_opencti_type(observable_type):
|
|
160
|
+
"""Convert STIX observable type to OpenCTI type.
|
|
161
|
+
|
|
162
|
+
:param observable_type: STIX observable type
|
|
163
|
+
:type observable_type: str
|
|
164
|
+
:return: Corresponding OpenCTI type or "Unknown"
|
|
165
|
+
:rtype: str
|
|
166
|
+
"""
|
|
155
167
|
if observable_type in STIX_CYBER_OBSERVABLE_MAPPING:
|
|
156
168
|
return STIX_CYBER_OBSERVABLE_MAPPING[observable_type]
|
|
157
169
|
else:
|
|
@@ -159,6 +171,15 @@ class OpenCTIStix2Utils:
|
|
|
159
171
|
|
|
160
172
|
@staticmethod
|
|
161
173
|
def create_stix_pattern(observable_type, observable_value):
|
|
174
|
+
"""Create a STIX pattern from an observable type and value.
|
|
175
|
+
|
|
176
|
+
:param observable_type: Type of the observable
|
|
177
|
+
:type observable_type: str
|
|
178
|
+
:param observable_value: Value of the observable
|
|
179
|
+
:type observable_value: str
|
|
180
|
+
:return: STIX pattern string or None if type not supported
|
|
181
|
+
:rtype: str or None
|
|
182
|
+
"""
|
|
162
183
|
if observable_type in PATTERN_MAPPING:
|
|
163
184
|
lhs = ObjectPath(
|
|
164
185
|
(
|
|
@@ -175,14 +196,16 @@ class OpenCTIStix2Utils:
|
|
|
175
196
|
else:
|
|
176
197
|
return None
|
|
177
198
|
|
|
178
|
-
"""Generate random stix id (uuid v1)
|
|
179
|
-
This id will stored and resolved by openCTI
|
|
180
|
-
We will stored only 5 stix of this type to prevent database flooding
|
|
181
|
-
:param stix_type: the stix type
|
|
182
|
-
"""
|
|
183
|
-
|
|
184
199
|
@staticmethod
|
|
185
200
|
def generate_random_stix_id(stix_type):
|
|
201
|
+
"""Generate random stix id (uuid v1) - DEPRECATED.
|
|
202
|
+
|
|
203
|
+
This function is deprecated and should not be used anymore.
|
|
204
|
+
Please use the generate_id function for SDO or proper SCO constructor.
|
|
205
|
+
|
|
206
|
+
:param stix_type: the stix type
|
|
207
|
+
:raises ValueError: Always raises an error as this function is deprecated
|
|
208
|
+
"""
|
|
186
209
|
raise ValueError(
|
|
187
210
|
"This function should not be used anymore, please use the generate_id function for SDO or proper SCO constructor"
|
|
188
211
|
)
|
|
@@ -191,6 +214,18 @@ class OpenCTIStix2Utils:
|
|
|
191
214
|
def retrieveClassForMethod(
|
|
192
215
|
openCTIApiClient, entity: Dict, type_path: str, method: str
|
|
193
216
|
) -> Any:
|
|
217
|
+
"""Retrieve the appropriate API class for a given entity type and method.
|
|
218
|
+
|
|
219
|
+
:param openCTIApiClient: OpenCTI API client instance
|
|
220
|
+
:param entity: Entity dictionary containing the type
|
|
221
|
+
:type entity: Dict
|
|
222
|
+
:param type_path: Path to the type field in the entity
|
|
223
|
+
:type type_path: str
|
|
224
|
+
:param method: Name of the method to check for
|
|
225
|
+
:type method: str
|
|
226
|
+
:return: The API class that has the specified method, or None
|
|
227
|
+
:rtype: Any
|
|
228
|
+
"""
|
|
194
229
|
if entity is not None and type_path in entity:
|
|
195
230
|
attributeName = entity[type_path].lower().replace("-", "_")
|
|
196
231
|
if hasattr(openCTIApiClient, attributeName):
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
pycti/__init__.py,sha256=2jJqqSQ9XcoSWljStEp5XRIGqPNE3cwjZzHgy_tL-_U,5676
|
|
2
|
+
pycti/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
pycti/api/opencti_api_client.py,sha256=lbygp2fOsmTKIrM-8Y7GxFzCZzdFStC0dhxyKYs0Wzo,35368
|
|
4
|
+
pycti/api/opencti_api_connector.py,sha256=8xwHuLINP3ZCImzE9_K_iCR9QEA3K6aHpK4bJhcZf20,5582
|
|
5
|
+
pycti/api/opencti_api_draft.py,sha256=ZFrva6p7VZA7rCtIpyfyA-KTWvcTaWvpy51_Edi9rG4,428
|
|
6
|
+
pycti/api/opencti_api_internal_file.py,sha256=v_IFGZC3tngrZiaf9K64lnJbQgczgjym2NUECmdV_jk,802
|
|
7
|
+
pycti/api/opencti_api_notification.py,sha256=uTBSjym2RfSYHTnfBIVmWj5kATrzQ2lRQ178Jy5bsu0,1375
|
|
8
|
+
pycti/api/opencti_api_pir.py,sha256=3yDfUNVe9G_G9OrCcL3pBTE31kcstKXhXCiSrGhpUYY,992
|
|
9
|
+
pycti/api/opencti_api_playbook.py,sha256=yKg54sRaE4gtmQURQ_7jFjcyQJqchWsn-Uepe6MZUfs,2183
|
|
10
|
+
pycti/api/opencti_api_public_dashboard.py,sha256=aa4trEuaf7WstmiS4WAHoe1qmYmaFWmbO0N4N_iXPGM,711
|
|
11
|
+
pycti/api/opencti_api_trash.py,sha256=r_zi57n5TfLw9LYs2UFg33Nvyy3Huc6CjpK2mRQsmao,1065
|
|
12
|
+
pycti/api/opencti_api_work.py,sha256=uV1mbPz3zmNZjoNHVmX6SyWPQKEHkpSDXkb_a2NIOA4,8982
|
|
13
|
+
pycti/api/opencti_api_workspace.py,sha256=ycqOTEXeUHF2k8H4jhoYDd1W6ijFcNUjYf4eSdLpH0k,611
|
|
14
|
+
pycti/connector/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
+
pycti/connector/opencti_connector.py,sha256=8lCZFvcA9-S1x6vFl756hgWAlzKfrnq-C4AIdDJr-Kg,2715
|
|
16
|
+
pycti/connector/opencti_connector_helper.py,sha256=ZxVZnPqhpJtaPqrludIppnG06ohMZUYNnNifiagsink,94765
|
|
17
|
+
pycti/connector/opencti_metric_handler.py,sha256=piykdwqNUh5klpPAogsbo7tn0N7sa3wU4D2BQieNEso,4725
|
|
18
|
+
pycti/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
|
+
pycti/entities/opencti_attack_pattern.py,sha256=Mf5ltnxG5XIgMdaplhSBFhuMBwsjGFZvkfhTX7jpTOw,23580
|
|
20
|
+
pycti/entities/opencti_campaign.py,sha256=MhkzqwMsu1w9VnOUHq4dQVViLh6KeAAI3YmLOAqJYhg,18969
|
|
21
|
+
pycti/entities/opencti_capability.py,sha256=mAR3AT__w6ULuAgc4T_QYxDwW9Jz8bsXQ8SDKF2BCL4,1515
|
|
22
|
+
pycti/entities/opencti_case_incident.py,sha256=GESR5355ED9jE83uDNVTKsWJF2ClU9L53mMX_--3Nd0,34937
|
|
23
|
+
pycti/entities/opencti_case_rfi.py,sha256=0pcujjHV5xbysASPXDceQVkuRS77Gl97HI6ron7XhkU,35251
|
|
24
|
+
pycti/entities/opencti_case_rft.py,sha256=eai_CkcEEl2NquhfJOhGoyUii92CITkQR8YfkDP6fgY,36171
|
|
25
|
+
pycti/entities/opencti_channel.py,sha256=zBb9YzpNCWrC1lx8b3q8X9Xif7ijlJXqwxoXge_Z-14,16891
|
|
26
|
+
pycti/entities/opencti_course_of_action.py,sha256=I6h2JV9zW-7TIX_uRT0puC7nrWSe3X2gVD2tVnoPMyA,19203
|
|
27
|
+
pycti/entities/opencti_data_component.py,sha256=C35DZH3WW20lEqJQjbkF9s6IeaqN0Rl-hLRAEwKQgZY,19771
|
|
28
|
+
pycti/entities/opencti_data_source.py,sha256=1l8k8MC_vALyUNjiFOdV526Joyvh9dnWwCeW-2YFhec,18650
|
|
29
|
+
pycti/entities/opencti_event.py,sha256=iVFTMVFxtQonbZWfl4e69fmbfT0KqJ47n8IArPAwlfY,18026
|
|
30
|
+
pycti/entities/opencti_external_reference.py,sha256=mIea4c8AXS31GlhCnd9MXgLR_ypKCJv4_9V49VG3RXE,13922
|
|
31
|
+
pycti/entities/opencti_feedback.py,sha256=O29gU2PXqFXBGBxEL6zhyOxBJvVWgwNqTjfDFIuzVxA,32921
|
|
32
|
+
pycti/entities/opencti_group.py,sha256=GgtA1zZunjXjxPdXc3wOV8Veitte0IGmRF1WwFYWs80,26390
|
|
33
|
+
pycti/entities/opencti_grouping.py,sha256=QVUcHBrvSOY2O2EDqL2BDtUdSMowOHj07mozfHl7mt4,31418
|
|
34
|
+
pycti/entities/opencti_identity.py,sha256=sPI8wRJp2asVBlJubb6OR54ZMDu6Q7gkoPAn56_zlxs,27820
|
|
35
|
+
pycti/entities/opencti_incident.py,sha256=GT2PBAYERZH4X-TrjPGl1Gi1EXD_0w1KE5v5ZEqQriY,19163
|
|
36
|
+
pycti/entities/opencti_indicator.py,sha256=aEjI6GIxy42lctIbqb9A8jEQ9UG6VKc-P2gqhBa4OCA,23203
|
|
37
|
+
pycti/entities/opencti_infrastructure.py,sha256=-vuGCDiwWH60GmLOpUelVDPtvM9XB9DhfGDwM0S2OpI,20331
|
|
38
|
+
pycti/entities/opencti_intrusion_set.py,sha256=TRdAZu6hfC7ws8MXzutRxAX0G6eubCbqq5b2a1gppyk,21156
|
|
39
|
+
pycti/entities/opencti_kill_chain_phase.py,sha256=Q5xiYy4rZ9BKHbX52soHPLCq3_iOe9nCDWYNAx6ehbw,8210
|
|
40
|
+
pycti/entities/opencti_label.py,sha256=Nk9yHhZkR0rwgHjhw4e93J_kjCaQm3iTBJdL6y96gpw,8947
|
|
41
|
+
pycti/entities/opencti_language.py,sha256=bP_ZUDCm6xyjL-GC8P03nH6qQm673-a9kLFx91g8I9M,16768
|
|
42
|
+
pycti/entities/opencti_location.py,sha256=0UGHHHnA9qS14bJQek8C2Vx-L53Ynj2yoQQOcusYO-I,18867
|
|
43
|
+
pycti/entities/opencti_malware.py,sha256=BNdGy8M3KfDYlKgYQwJ6zHTMbz9ouDY2AiypnM_RvOw,22671
|
|
44
|
+
pycti/entities/opencti_malware_analysis.py,sha256=mP7Jp9Rik7chrXsTBNX-5IXGXuCKO--05ZhbGoI0V5I,22310
|
|
45
|
+
pycti/entities/opencti_marking_definition.py,sha256=kY4WsFqZlxVIDg-lqZUS-b2JO0j9JcsHN9xZxfeDhxs,13920
|
|
46
|
+
pycti/entities/opencti_narrative.py,sha256=3TPIsCu7T7qCO1uFiHj4rmePHtEP6eNQKJBI9jxg_Vg,17660
|
|
47
|
+
pycti/entities/opencti_note.py,sha256=b-4vm1YzoN0csqLucdaErd6TEYak5NwJm0SOfoNFdCU,31278
|
|
48
|
+
pycti/entities/opencti_observed_data.py,sha256=ME1YvnU2-y8M-88LfwvnkNKsZbNK7_BJRZP5-ZY8w0Q,31594
|
|
49
|
+
pycti/entities/opencti_opinion.py,sha256=1kG6J5WhxgPi8NpNmyAyy4bZjEMc4h8Jl8OzB7s6XNc,22852
|
|
50
|
+
pycti/entities/opencti_report.py,sha256=AT88ZBipX2LqrR4gFEK7btifcZ12fKtfy1zRZoQkufc,35507
|
|
51
|
+
pycti/entities/opencti_role.py,sha256=ryfPmZ_ch2sRGgqEr6_qxChTcGoeqvHW0MvlGHkLgdw,14039
|
|
52
|
+
pycti/entities/opencti_settings.py,sha256=3dArFaPPdcFTV44uGRffjHpnDE-MKIXgd496QZcH6Bw,13547
|
|
53
|
+
pycti/entities/opencti_stix.py,sha256=W8DQSg1QfWFNU1hR4jHiSbzB_N9BMakSlQTl-yOVQbQ,2616
|
|
54
|
+
pycti/entities/opencti_stix_core_object.py,sha256=EAAdFkAd3jKSNXSqV2oSLtDhSMYf0iID7oQwEvI7Xb0,63719
|
|
55
|
+
pycti/entities/opencti_stix_core_relationship.py,sha256=d5m__t5XjFo7gKFX-3oWFaSHPr4QEiYNCx98dlsJhAc,48012
|
|
56
|
+
pycti/entities/opencti_stix_cyber_observable.py,sha256=2k7PRSP6DQEpOH37T_pkxoq4hRtTGI_PQruVM55C7XM,93698
|
|
57
|
+
pycti/entities/opencti_stix_domain_object.py,sha256=6VGill8b0Vr22yUe8fAP0dOpWDXaDtteJ4rqhLqwzKM,83173
|
|
58
|
+
pycti/entities/opencti_stix_nested_ref_relationship.py,sha256=81mS3ccqlsiZf20ssvhTPmtDvoTsBWPUSXe2pkulQVc,12705
|
|
59
|
+
pycti/entities/opencti_stix_object_or_stix_relationship.py,sha256=wOWVEXiGnFORTOVIrdMqAo55InbCEcBD6Nl2FAkYHpY,20256
|
|
60
|
+
pycti/entities/opencti_stix_sighting_relationship.py,sha256=qnxraGftKSA6qK8QjqyAOqhsm-r6Akfp-nybpa6Jh8Y,32060
|
|
61
|
+
pycti/entities/opencti_task.py,sha256=SHio0zRheHxDHOTMlZeB4PWzFV0XZmeQYffCcDnmKo0,25653
|
|
62
|
+
pycti/entities/opencti_threat_actor.py,sha256=vFPeo0pOYSqHBKVlWc4o8RjuP2PP0A09KWU6rsYXnvA,11201
|
|
63
|
+
pycti/entities/opencti_threat_actor_group.py,sha256=dV28sDfADoDpATyk8w2fN1ZGOoad3LCk7lnij3nFBY8,20828
|
|
64
|
+
pycti/entities/opencti_threat_actor_individual.py,sha256=l-E0RShOofXTZgw2HUyrDprXm8K3yvxh620hqAl-a-4,21178
|
|
65
|
+
pycti/entities/opencti_tool.py,sha256=WHCnTzgYyrWB_vaksoY5CRGgZjqANeza3a3b8cTeVKI,16932
|
|
66
|
+
pycti/entities/opencti_user.py,sha256=XrsD84uKiItk2AUucM682Zjb1ikAQIRF17MS969TGQ4,30492
|
|
67
|
+
pycti/entities/opencti_vocabulary.py,sha256=wxVfWyeI_O0zqQYtX5xAOOkZDSQi1UQiGazcJKRg5Tg,6720
|
|
68
|
+
pycti/entities/opencti_vulnerability.py,sha256=zMIbVIOAclUcThSi-u-OL_xgBLmroXVkF4H2E7PpOxo,53444
|
|
69
|
+
pycti/entities/indicator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
70
|
+
pycti/entities/indicator/opencti_indicator_properties.py,sha256=iQvSeMHB-vSTzINnRxqIJfC3OgMHyhbXUVF2juU7DoE,5219
|
|
71
|
+
pycti/entities/stix_cyber_observable/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
72
|
+
pycti/entities/stix_cyber_observable/opencti_stix_cyber_observable_deprecated.py,sha256=q-2G6OOqvUC1U2hSKxD8uT5T18M_IDkl72Tn1KoumQI,1847
|
|
73
|
+
pycti/entities/stix_cyber_observable/opencti_stix_cyber_observable_properties.py,sha256=lB4ORi5t9R5n8CwZ35FCIdfpVlDBPGJMg2dqtTMDfOo,11345
|
|
74
|
+
pycti/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
75
|
+
pycti/utils/constants.py,sha256=VRYRvDm6hkTR0ZcHHWMzQBwqlPRskYnusBpgoX0S05A,12854
|
|
76
|
+
pycti/utils/opencti_logger.py,sha256=MApWthWJrSeBI0rumnhLhBtanjrtmfP6PJqOiQjcCOY,4091
|
|
77
|
+
pycti/utils/opencti_stix2.py,sha256=xeBh1tMh_8k6tcfy7aYSM1OryhhzBdIuMtuRZlKTO6w,135505
|
|
78
|
+
pycti/utils/opencti_stix2_identifier.py,sha256=k8L1z4q1xdCBfxqUba4YS_kT-MmbJFxYh0RvfGOmrOs,837
|
|
79
|
+
pycti/utils/opencti_stix2_splitter.py,sha256=wOOgPM5FYYbCEhFAg9om54AzyNRwK_RzocsJJ6kViqY,11489
|
|
80
|
+
pycti/utils/opencti_stix2_update.py,sha256=CnMyqkeVA0jgyxEcgqna8sABU4YPMjkEJ228GVurIn4,14658
|
|
81
|
+
pycti/utils/opencti_stix2_utils.py,sha256=10CF7ip1XEURyd6EUMDpBHPQvmi5uGUxh1QDOw6LKJk,6955
|
|
82
|
+
pycti-6.8.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
83
|
+
pycti-6.8.0.dist-info/METADATA,sha256=xWf8Fad7HWccEKk6GzlELhvgw74ncgKzQ5mPQyZc6V8,5535
|
|
84
|
+
pycti-6.8.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
85
|
+
pycti-6.8.0.dist-info/top_level.txt,sha256=cqEpxitAhHP4VgSA6xmrak6Yk9MeBkwoMTB6k7d2ZnE,6
|
|
86
|
+
pycti-6.8.0.dist-info/RECORD,,
|