pycti 6.8.8__py3-none-any.whl → 6.8.9__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/api/opencti_api_client.py +2 -0
- pycti/api/opencti_api_connector.py +1 -0
- pycti/connector/opencti_connector.py +6 -0
- pycti/connector/opencti_connector_helper.py +40 -18
- pycti/entities/opencti_security_coverage.py +336 -0
- pycti/entities/opencti_settings.py +2 -4
- pycti/entities/opencti_stix_core_relationship.py +16 -0
- pycti/utils/opencti_stix2.py +2 -0
- pycti/utils/opencti_stix2_utils.py +1 -0
- {pycti-6.8.8.dist-info → pycti-6.8.9.dist-info}/METADATA +1 -1
- {pycti-6.8.8.dist-info → pycti-6.8.9.dist-info}/RECORD +15 -14
- {pycti-6.8.8.dist-info → pycti-6.8.9.dist-info}/WHEEL +0 -0
- {pycti-6.8.8.dist-info → pycti-6.8.9.dist-info}/licenses/LICENSE +0 -0
- {pycti-6.8.8.dist-info → pycti-6.8.9.dist-info}/top_level.txt +0 -0
pycti/__init__.py
CHANGED
pycti/api/opencti_api_client.py
CHANGED
|
@@ -52,6 +52,7 @@ from pycti.entities.opencti_observed_data import ObservedData
|
|
|
52
52
|
from pycti.entities.opencti_opinion import Opinion
|
|
53
53
|
from pycti.entities.opencti_report import Report
|
|
54
54
|
from pycti.entities.opencti_role import Role
|
|
55
|
+
from pycti.entities.opencti_security_coverage import SecurityCoverage
|
|
55
56
|
from pycti.entities.opencti_settings import Settings
|
|
56
57
|
from pycti.entities.opencti_stix import Stix
|
|
57
58
|
from pycti.entities.opencti_stix_core_object import StixCoreObject
|
|
@@ -223,6 +224,7 @@ class OpenCTIApiClient:
|
|
|
223
224
|
self.narrative = Narrative(self)
|
|
224
225
|
self.language = Language(self)
|
|
225
226
|
self.vulnerability = Vulnerability(self)
|
|
227
|
+
self.security_coverage = SecurityCoverage(self)
|
|
226
228
|
self.attack_pattern = AttackPattern(self)
|
|
227
229
|
self.course_of_action = CourseOfAction(self)
|
|
228
230
|
self.data_component = DataComponent(self)
|
|
@@ -43,6 +43,8 @@ class OpenCTIConnector:
|
|
|
43
43
|
auto: bool,
|
|
44
44
|
only_contextual: bool,
|
|
45
45
|
playbook_compatible: bool,
|
|
46
|
+
auto_update: bool,
|
|
47
|
+
enrichment_resolution: str,
|
|
46
48
|
listen_callback_uri=None,
|
|
47
49
|
):
|
|
48
50
|
self.id = connector_id
|
|
@@ -55,6 +57,8 @@ class OpenCTIConnector:
|
|
|
55
57
|
else:
|
|
56
58
|
self.scope = []
|
|
57
59
|
self.auto = auto
|
|
60
|
+
self.auto_update = auto_update
|
|
61
|
+
self.enrichment_resolution = enrichment_resolution
|
|
58
62
|
self.only_contextual = only_contextual
|
|
59
63
|
self.playbook_compatible = playbook_compatible
|
|
60
64
|
self.listen_callback_uri = listen_callback_uri
|
|
@@ -72,6 +76,8 @@ class OpenCTIConnector:
|
|
|
72
76
|
"type": self.type.name,
|
|
73
77
|
"scope": self.scope,
|
|
74
78
|
"auto": self.auto,
|
|
79
|
+
"auto_update": self.auto_update,
|
|
80
|
+
"enrichment_resolution": self.enrichment_resolution,
|
|
75
81
|
"only_contextual": self.only_contextual,
|
|
76
82
|
"playbook_compatible": self.playbook_compatible,
|
|
77
83
|
"listen_callback_uri": self.listen_callback_uri,
|
|
@@ -365,6 +365,16 @@ class ListenQueue(threading.Thread):
|
|
|
365
365
|
event_data = json_data["event"]
|
|
366
366
|
entity_id = event_data.get("entity_id")
|
|
367
367
|
entity_type = event_data.get("entity_type")
|
|
368
|
+
stix_entity = (
|
|
369
|
+
json.loads(event_data.get("stix_entity"))
|
|
370
|
+
if event_data.get("stix_entity")
|
|
371
|
+
else None
|
|
372
|
+
)
|
|
373
|
+
stix_objects = (
|
|
374
|
+
json.loads(event_data.get("stix_objects"))
|
|
375
|
+
if event_data.get("stix_objects")
|
|
376
|
+
else None
|
|
377
|
+
)
|
|
368
378
|
validation_mode = event_data.get("validation_mode", "workbench")
|
|
369
379
|
force_validation = event_data.get("force_validation", False)
|
|
370
380
|
# Set the API headers
|
|
@@ -430,17 +440,18 @@ class ListenQueue(threading.Thread):
|
|
|
430
440
|
else:
|
|
431
441
|
# If not playbook but enrichment, compute object on enrichment_entity
|
|
432
442
|
opencti_entity = event_data["enrichment_entity"]
|
|
433
|
-
stix_objects
|
|
434
|
-
|
|
435
|
-
|
|
443
|
+
if stix_objects is None:
|
|
444
|
+
stix_objects = self.helper.api.stix2.prepare_export(
|
|
445
|
+
entity=self.helper.api.stix2.generate_export(
|
|
446
|
+
copy.copy(opencti_entity)
|
|
447
|
+
)
|
|
436
448
|
)
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
][0]
|
|
449
|
+
stix_entity = [
|
|
450
|
+
e
|
|
451
|
+
for e in stix_objects
|
|
452
|
+
if e["id"] == opencti_entity["standard_id"]
|
|
453
|
+
or e["id"] == "x-opencti-" + opencti_entity["standard_id"]
|
|
454
|
+
][0]
|
|
444
455
|
event_data["stix_objects"] = stix_objects
|
|
445
456
|
event_data["stix_entity"] = stix_entity
|
|
446
457
|
# Handle organization propagation
|
|
@@ -1116,6 +1127,15 @@ class OpenCTIConnectorHelper: # pylint: disable=too-many-public-methods
|
|
|
1116
1127
|
self.connect_auto = get_config_variable(
|
|
1117
1128
|
"CONNECTOR_AUTO", ["connector", "auto"], config, default=False
|
|
1118
1129
|
)
|
|
1130
|
+
self.connect_auto_update = get_config_variable(
|
|
1131
|
+
"CONNECTOR_AUTO_UPDATE", ["connector", "auto_update"], config, default=False
|
|
1132
|
+
)
|
|
1133
|
+
self.connect_enrichment_resolution = get_config_variable(
|
|
1134
|
+
"CONNECTOR_ENRICHMENT_RESOLUTION",
|
|
1135
|
+
["connector", "enrichment_resolution"],
|
|
1136
|
+
config,
|
|
1137
|
+
default="none",
|
|
1138
|
+
)
|
|
1119
1139
|
self.bundle_send_to_queue = get_config_variable(
|
|
1120
1140
|
"CONNECTOR_SEND_TO_QUEUE",
|
|
1121
1141
|
["connector", "send_to_queue"],
|
|
@@ -1231,14 +1251,16 @@ class OpenCTIConnectorHelper: # pylint: disable=too-many-public-methods
|
|
|
1231
1251
|
)
|
|
1232
1252
|
# Register the connector in OpenCTI
|
|
1233
1253
|
self.connector = OpenCTIConnector(
|
|
1234
|
-
self.connect_id,
|
|
1235
|
-
self.connect_name,
|
|
1236
|
-
self.connect_type,
|
|
1237
|
-
self.connect_scope,
|
|
1238
|
-
self.connect_auto,
|
|
1239
|
-
self.connect_only_contextual,
|
|
1240
|
-
playbook_compatible,
|
|
1241
|
-
|
|
1254
|
+
connector_id=self.connect_id,
|
|
1255
|
+
connector_name=self.connect_name,
|
|
1256
|
+
connector_type=self.connect_type,
|
|
1257
|
+
scope=self.connect_scope,
|
|
1258
|
+
auto=self.connect_auto,
|
|
1259
|
+
only_contextual=self.connect_only_contextual,
|
|
1260
|
+
playbook_compatible=playbook_compatible,
|
|
1261
|
+
auto_update=self.connect_auto_update,
|
|
1262
|
+
enrichment_resolution=self.connect_enrichment_resolution,
|
|
1263
|
+
listen_callback_uri=(
|
|
1242
1264
|
self.listen_protocol_api_uri + self.listen_protocol_api_path
|
|
1243
1265
|
if self.listen_protocol == "API"
|
|
1244
1266
|
else None
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import uuid
|
|
5
|
+
|
|
6
|
+
from stix2.canonicalization.Canonicalize import canonicalize
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SecurityCoverage:
|
|
10
|
+
def __init__(self, opencti):
|
|
11
|
+
self.opencti = opencti
|
|
12
|
+
self.properties = """
|
|
13
|
+
id
|
|
14
|
+
standard_id
|
|
15
|
+
entity_type
|
|
16
|
+
parent_types
|
|
17
|
+
spec_version
|
|
18
|
+
created_at
|
|
19
|
+
updated_at
|
|
20
|
+
external_uri
|
|
21
|
+
objectCovered {
|
|
22
|
+
__typename
|
|
23
|
+
... on StixCoreObject {
|
|
24
|
+
id
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
objectMarking {
|
|
28
|
+
id
|
|
29
|
+
standard_id
|
|
30
|
+
entity_type
|
|
31
|
+
definition_type
|
|
32
|
+
definition
|
|
33
|
+
created
|
|
34
|
+
modified
|
|
35
|
+
x_opencti_order
|
|
36
|
+
x_opencti_color
|
|
37
|
+
}
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
@staticmethod
|
|
41
|
+
def generate_id(covered_ref):
|
|
42
|
+
data = {"covered_ref": covered_ref.lower().strip()}
|
|
43
|
+
data = canonicalize(data, utf8=False)
|
|
44
|
+
id = str(uuid.uuid5(uuid.UUID("00abedb4-aa42-466c-9c01-fed23315a9b7"), data))
|
|
45
|
+
return "security-coverage--" + id
|
|
46
|
+
|
|
47
|
+
@staticmethod
|
|
48
|
+
def generate_id_from_data(data):
|
|
49
|
+
return SecurityCoverage.generate_id(data["covered_ref"])
|
|
50
|
+
|
|
51
|
+
"""
|
|
52
|
+
List securityCoverage objects
|
|
53
|
+
|
|
54
|
+
:param filters: the filters to apply
|
|
55
|
+
:param search: the search keyword
|
|
56
|
+
:param first: return the first n rows from the after ID (or the beginning if not set)
|
|
57
|
+
:param after: ID of the first row for pagination
|
|
58
|
+
:return List of SecurityCoverage objects
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
def list(self, **kwargs):
|
|
62
|
+
filters = kwargs.get("filters", None)
|
|
63
|
+
search = kwargs.get("search", None)
|
|
64
|
+
first = kwargs.get("first", 100)
|
|
65
|
+
after = kwargs.get("after", None)
|
|
66
|
+
order_by = kwargs.get("orderBy", None)
|
|
67
|
+
order_mode = kwargs.get("orderMode", None)
|
|
68
|
+
custom_attributes = kwargs.get("customAttributes", None)
|
|
69
|
+
get_all = kwargs.get("getAll", False)
|
|
70
|
+
with_pagination = kwargs.get("withPagination", False)
|
|
71
|
+
|
|
72
|
+
self.opencti.app_logger.info(
|
|
73
|
+
"Listing SecurityCoverage with filters", {"filters": json.dumps(filters)}
|
|
74
|
+
)
|
|
75
|
+
query = (
|
|
76
|
+
"""
|
|
77
|
+
query SecurityCoverage($filters: FilterGroup, $search: String, $first: Int, $after: ID, $orderBy: SecurityCoverageOrdering, $orderMode: OrderingMode) {
|
|
78
|
+
securityCoverages(filters: $filters, search: $search, first: $first, after: $after, orderBy: $orderBy, orderMode: $orderMode) {
|
|
79
|
+
edges {
|
|
80
|
+
node {
|
|
81
|
+
"""
|
|
82
|
+
+ (custom_attributes if custom_attributes is not None else self.properties)
|
|
83
|
+
+ """
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
pageInfo {
|
|
87
|
+
startCursor
|
|
88
|
+
endCursor
|
|
89
|
+
hasNextPage
|
|
90
|
+
hasPreviousPage
|
|
91
|
+
globalCount
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
"""
|
|
96
|
+
)
|
|
97
|
+
result = self.opencti.query(
|
|
98
|
+
query,
|
|
99
|
+
{
|
|
100
|
+
"filters": filters,
|
|
101
|
+
"search": search,
|
|
102
|
+
"first": first,
|
|
103
|
+
"after": after,
|
|
104
|
+
"orderBy": order_by,
|
|
105
|
+
"orderMode": order_mode,
|
|
106
|
+
},
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
if get_all:
|
|
110
|
+
final_data = []
|
|
111
|
+
data = self.opencti.process_multiple(result["data"]["securityCoverages"])
|
|
112
|
+
final_data = final_data + data
|
|
113
|
+
while result["data"]["securityCoverages"]["pageInfo"]["hasNextPage"]:
|
|
114
|
+
after = result["data"]["securityCoverages"]["pageInfo"]["endCursor"]
|
|
115
|
+
self.opencti.app_logger.info(
|
|
116
|
+
"Listing SecurityCoverage", {"after": after}
|
|
117
|
+
)
|
|
118
|
+
result = self.opencti.query(
|
|
119
|
+
query,
|
|
120
|
+
{
|
|
121
|
+
"filters": filters,
|
|
122
|
+
"search": search,
|
|
123
|
+
"first": first,
|
|
124
|
+
"after": after,
|
|
125
|
+
"orderBy": order_by,
|
|
126
|
+
"orderMode": order_mode,
|
|
127
|
+
},
|
|
128
|
+
)
|
|
129
|
+
data = self.opencti.process_multiple(
|
|
130
|
+
result["data"]["securityCoverages"]
|
|
131
|
+
)
|
|
132
|
+
final_data = final_data + data
|
|
133
|
+
return final_data
|
|
134
|
+
else:
|
|
135
|
+
return self.opencti.process_multiple(
|
|
136
|
+
result["data"]["securityCoverages"], with_pagination
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
"""
|
|
140
|
+
Read a SecurityCoverage object
|
|
141
|
+
|
|
142
|
+
:param id: the id of the SecurityCoverage
|
|
143
|
+
:param filters: the filters to apply if no id provided
|
|
144
|
+
:return SecurityCoverage object
|
|
145
|
+
"""
|
|
146
|
+
|
|
147
|
+
def read(self, **kwargs):
|
|
148
|
+
id = kwargs.get("id", None)
|
|
149
|
+
filters = kwargs.get("filters", None)
|
|
150
|
+
custom_attributes = kwargs.get("customAttributes", None)
|
|
151
|
+
if id is not None:
|
|
152
|
+
self.opencti.app_logger.info("Reading SecurityCoverage", {"id": id})
|
|
153
|
+
query = (
|
|
154
|
+
"""
|
|
155
|
+
query SecurityCoverage($id: String!) {
|
|
156
|
+
securityCoverage(id: $id) {
|
|
157
|
+
"""
|
|
158
|
+
+ (
|
|
159
|
+
custom_attributes
|
|
160
|
+
if custom_attributes is not None
|
|
161
|
+
else self.properties
|
|
162
|
+
)
|
|
163
|
+
+ """
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
"""
|
|
167
|
+
)
|
|
168
|
+
result = self.opencti.query(query, {"id": id})
|
|
169
|
+
return self.opencti.process_multiple_fields(
|
|
170
|
+
result["data"]["securityCoverage"]
|
|
171
|
+
)
|
|
172
|
+
elif filters is not None:
|
|
173
|
+
result = self.list(filters=filters)
|
|
174
|
+
if len(result) > 0:
|
|
175
|
+
return result[0]
|
|
176
|
+
else:
|
|
177
|
+
return None
|
|
178
|
+
else:
|
|
179
|
+
self.opencti.app_logger.error(
|
|
180
|
+
"[opencti_security_coverage] Missing parameters: id or filters"
|
|
181
|
+
)
|
|
182
|
+
return None
|
|
183
|
+
|
|
184
|
+
"""
|
|
185
|
+
Create a Security coverage object
|
|
186
|
+
|
|
187
|
+
:return Security Coverage object
|
|
188
|
+
"""
|
|
189
|
+
|
|
190
|
+
def create(self, **kwargs):
|
|
191
|
+
stix_id = kwargs.get("stix_id", None)
|
|
192
|
+
name = kwargs.get("name", None)
|
|
193
|
+
description = kwargs.get("description", None)
|
|
194
|
+
created_by = kwargs.get("createdBy", None)
|
|
195
|
+
object_marking = kwargs.get("objectMarking", None)
|
|
196
|
+
object_label = kwargs.get("objectLabel", None)
|
|
197
|
+
object_covered = kwargs.get("objectCovered", None)
|
|
198
|
+
external_references = kwargs.get("externalReferences", None)
|
|
199
|
+
external_uri = kwargs.get("external_uri", None)
|
|
200
|
+
coverage_last_result = kwargs.get("coverage_last_result", None)
|
|
201
|
+
coverage_valid_from = kwargs.get("coverage_valid_from", None)
|
|
202
|
+
coverage_valid_to = kwargs.get("coverage_valid_to", None)
|
|
203
|
+
coverage_information = kwargs.get("coverage_information", None)
|
|
204
|
+
auto_enrichment_disable = kwargs.get("auto_enrichment_disable", None)
|
|
205
|
+
|
|
206
|
+
if name is not None and object_covered is not None:
|
|
207
|
+
self.opencti.app_logger.info("Creating Security Coverage", {"name": name})
|
|
208
|
+
query = """
|
|
209
|
+
mutation SecurityCoverageAdd($input: SecurityCoverageAddInput!) {
|
|
210
|
+
securityCoverageAdd(input: $input) {
|
|
211
|
+
id
|
|
212
|
+
standard_id
|
|
213
|
+
entity_type
|
|
214
|
+
parent_types
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
"""
|
|
218
|
+
result = self.opencti.query(
|
|
219
|
+
query,
|
|
220
|
+
{
|
|
221
|
+
"input": {
|
|
222
|
+
"stix_id": stix_id,
|
|
223
|
+
"name": name,
|
|
224
|
+
"description": description,
|
|
225
|
+
"createdBy": created_by,
|
|
226
|
+
"objectMarking": object_marking,
|
|
227
|
+
"objectLabel": object_label,
|
|
228
|
+
"objectCovered": object_covered,
|
|
229
|
+
"external_uri": external_uri,
|
|
230
|
+
"externalReferences": external_references,
|
|
231
|
+
"coverage_last_result": coverage_last_result,
|
|
232
|
+
"coverage_valid_from": coverage_valid_from,
|
|
233
|
+
"coverage_valid_to": coverage_valid_to,
|
|
234
|
+
"coverage_information": coverage_information,
|
|
235
|
+
"auto_enrichment_disable": auto_enrichment_disable,
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
)
|
|
239
|
+
return self.opencti.process_multiple_fields(
|
|
240
|
+
result["data"]["securityCoverageAdd"]
|
|
241
|
+
)
|
|
242
|
+
else:
|
|
243
|
+
self.opencti.app_logger.error(
|
|
244
|
+
"[opencti_security_coverage] "
|
|
245
|
+
"Missing parameters: name or object_covered"
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
"""
|
|
249
|
+
Import a Security coverage from a STIX2 object
|
|
250
|
+
|
|
251
|
+
:param stixObject: the Stix-Object Security coverage
|
|
252
|
+
:return Security coverage object
|
|
253
|
+
"""
|
|
254
|
+
|
|
255
|
+
def import_from_stix2(self, **kwargs):
|
|
256
|
+
stix_object = kwargs.get("stixObject", None)
|
|
257
|
+
extras = kwargs.get("extras", {})
|
|
258
|
+
if stix_object is not None:
|
|
259
|
+
# Search in extensions
|
|
260
|
+
if "x_opencti_stix_ids" not in stix_object:
|
|
261
|
+
stix_object["x_opencti_stix_ids"] = (
|
|
262
|
+
self.opencti.get_attribute_in_extension("stix_ids", stix_object)
|
|
263
|
+
)
|
|
264
|
+
if "x_opencti_granted_refs" not in stix_object:
|
|
265
|
+
stix_object["x_opencti_granted_refs"] = (
|
|
266
|
+
self.opencti.get_attribute_in_extension("granted_refs", stix_object)
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
raw_coverages = stix_object["coverage"] if "coverage" in stix_object else []
|
|
270
|
+
coverage_information = list(
|
|
271
|
+
map(
|
|
272
|
+
lambda cov: {
|
|
273
|
+
"coverage_name": cov["name"],
|
|
274
|
+
"coverage_score": cov["score"],
|
|
275
|
+
},
|
|
276
|
+
raw_coverages,
|
|
277
|
+
)
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
return self.create(
|
|
281
|
+
stix_id=stix_object["id"],
|
|
282
|
+
name=stix_object["name"],
|
|
283
|
+
external_uri=(
|
|
284
|
+
stix_object["external_uri"]
|
|
285
|
+
if "external_uri" in stix_object
|
|
286
|
+
else None
|
|
287
|
+
),
|
|
288
|
+
auto_enrichment_disable=(
|
|
289
|
+
stix_object["auto_enrichment_disable"]
|
|
290
|
+
if "auto_enrichment_disable" in stix_object
|
|
291
|
+
else False
|
|
292
|
+
),
|
|
293
|
+
coverage_last_result=(
|
|
294
|
+
stix_object["last_result"] if "last_result" in stix_object else None
|
|
295
|
+
),
|
|
296
|
+
coverage_valid_from=(
|
|
297
|
+
stix_object["valid_from"] if "valid_from" in stix_object else None
|
|
298
|
+
),
|
|
299
|
+
coverage_valid_to=(
|
|
300
|
+
stix_object["valid_to"] if "valid_to" in stix_object else None
|
|
301
|
+
),
|
|
302
|
+
coverage_information=coverage_information,
|
|
303
|
+
description=(
|
|
304
|
+
self.opencti.stix2.convert_markdown(stix_object["description"])
|
|
305
|
+
if "description" in stix_object
|
|
306
|
+
else None
|
|
307
|
+
),
|
|
308
|
+
createdBy=(
|
|
309
|
+
extras["created_by_id"] if "created_by_id" in extras else None
|
|
310
|
+
),
|
|
311
|
+
objectMarking=(
|
|
312
|
+
extras["object_marking_ids"]
|
|
313
|
+
if "object_marking_ids" in extras
|
|
314
|
+
else None
|
|
315
|
+
),
|
|
316
|
+
objectLabel=(
|
|
317
|
+
extras["object_label_ids"] if "object_label_ids" in extras else None
|
|
318
|
+
),
|
|
319
|
+
objectCovered=(
|
|
320
|
+
stix_object["covered_ref"] if "covered_ref" in stix_object else None
|
|
321
|
+
),
|
|
322
|
+
externalReferences=(
|
|
323
|
+
extras["external_references_ids"]
|
|
324
|
+
if "external_references_ids" in extras
|
|
325
|
+
else None
|
|
326
|
+
),
|
|
327
|
+
x_opencti_stix_ids=(
|
|
328
|
+
stix_object["x_opencti_stix_ids"]
|
|
329
|
+
if "x_opencti_stix_ids" in stix_object
|
|
330
|
+
else None
|
|
331
|
+
),
|
|
332
|
+
)
|
|
333
|
+
else:
|
|
334
|
+
self.opencti.app_logger.error(
|
|
335
|
+
"[opencti_security_coverage] Missing parameters: stixObject"
|
|
336
|
+
)
|
|
@@ -60,11 +60,9 @@ class Settings:
|
|
|
60
60
|
platform_theme_light_logo_login
|
|
61
61
|
platform_map_tile_server_dark
|
|
62
62
|
platform_map_tile_server_light
|
|
63
|
-
platform_openbas_url
|
|
64
|
-
platform_openbas_disable_display
|
|
65
|
-
platform_openerm_url
|
|
66
|
-
platform_openmtd_url
|
|
67
63
|
platform_ai_enabled
|
|
64
|
+
platform_openaev_url
|
|
65
|
+
platform_opengrc_url
|
|
68
66
|
platform_ai_type
|
|
69
67
|
platform_ai_model
|
|
70
68
|
platform_ai_has_token
|
|
@@ -624,6 +624,7 @@ class StixCoreRelationship:
|
|
|
624
624
|
granted_refs = kwargs.get("objectOrganization", None)
|
|
625
625
|
x_opencti_workflow_id = kwargs.get("x_opencti_workflow_id", None)
|
|
626
626
|
x_opencti_stix_ids = kwargs.get("x_opencti_stix_ids", None)
|
|
627
|
+
coverage_information = kwargs.get("coverage_information", None)
|
|
627
628
|
update = kwargs.get("update", False)
|
|
628
629
|
|
|
629
630
|
self.opencti.app_logger.info(
|
|
@@ -668,6 +669,7 @@ class StixCoreRelationship:
|
|
|
668
669
|
"killChainPhases": kill_chain_phases,
|
|
669
670
|
"x_opencti_workflow_id": x_opencti_workflow_id,
|
|
670
671
|
"x_opencti_stix_ids": x_opencti_stix_ids,
|
|
672
|
+
"coverage_information": coverage_information,
|
|
671
673
|
"update": update,
|
|
672
674
|
}
|
|
673
675
|
},
|
|
@@ -1175,6 +1177,19 @@ class StixCoreRelationship:
|
|
|
1175
1177
|
)
|
|
1176
1178
|
)
|
|
1177
1179
|
|
|
1180
|
+
raw_coverages = (
|
|
1181
|
+
stix_relation["coverage"] if "coverage" in stix_relation else []
|
|
1182
|
+
)
|
|
1183
|
+
coverage_information = list(
|
|
1184
|
+
map(
|
|
1185
|
+
lambda cov: {
|
|
1186
|
+
"coverage_name": cov["name"],
|
|
1187
|
+
"coverage_score": cov["score"],
|
|
1188
|
+
},
|
|
1189
|
+
raw_coverages,
|
|
1190
|
+
)
|
|
1191
|
+
)
|
|
1192
|
+
|
|
1178
1193
|
source_ref = stix_relation["source_ref"]
|
|
1179
1194
|
target_ref = stix_relation["target_ref"]
|
|
1180
1195
|
return self.create(
|
|
@@ -1197,6 +1212,7 @@ class StixCoreRelationship:
|
|
|
1197
1212
|
if "stop_time" in stix_relation
|
|
1198
1213
|
else default_date
|
|
1199
1214
|
),
|
|
1215
|
+
coverage_information=coverage_information,
|
|
1200
1216
|
revoked=(
|
|
1201
1217
|
stix_relation["revoked"] if "revoked" in stix_relation else None
|
|
1202
1218
|
),
|
pycti/utils/opencti_stix2.py
CHANGED
|
@@ -885,6 +885,7 @@ class OpenCTIStix2:
|
|
|
885
885
|
"Tool": self.opencti.tool.read,
|
|
886
886
|
"Vocabulary": self.opencti.vocabulary.read,
|
|
887
887
|
"Vulnerability": self.opencti.vulnerability.read,
|
|
888
|
+
"Security-Coverage": self.opencti.security_coverage.read,
|
|
888
889
|
}
|
|
889
890
|
|
|
890
891
|
def get_reader(self, entity_type: str):
|
|
@@ -961,6 +962,7 @@ class OpenCTIStix2:
|
|
|
961
962
|
"narrative": self.opencti.narrative,
|
|
962
963
|
"task": self.opencti.task,
|
|
963
964
|
"x-opencti-task": self.opencti.task,
|
|
965
|
+
"security-coverage": self.opencti.security_coverage,
|
|
964
966
|
"vocabulary": self.opencti.vocabulary,
|
|
965
967
|
# relationships
|
|
966
968
|
"relationship": self.opencti.stix_core_relationship,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
pycti/__init__.py,sha256=
|
|
1
|
+
pycti/__init__.py,sha256=mxG2AQCaVdFshDTHXdIWR-Y1Bg7JsZpYHSLK7QhDKNo,5676
|
|
2
2
|
pycti/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
pycti/api/opencti_api_client.py,sha256=
|
|
4
|
-
pycti/api/opencti_api_connector.py,sha256=
|
|
3
|
+
pycti/api/opencti_api_client.py,sha256=rAUEOYU8ND1oEw4w_hgbRbkpxF_5xVy3inV5Vo9QIfg,35494
|
|
4
|
+
pycti/api/opencti_api_connector.py,sha256=k2Rq1PS9cmVfy822eKUBHL4ebPv3Zh9BTfxzkNt26O8,5671
|
|
5
5
|
pycti/api/opencti_api_draft.py,sha256=ZFrva6p7VZA7rCtIpyfyA-KTWvcTaWvpy51_Edi9rG4,428
|
|
6
6
|
pycti/api/opencti_api_internal_file.py,sha256=v_IFGZC3tngrZiaf9K64lnJbQgczgjym2NUECmdV_jk,802
|
|
7
7
|
pycti/api/opencti_api_notification.py,sha256=uTBSjym2RfSYHTnfBIVmWj5kATrzQ2lRQ178Jy5bsu0,1375
|
|
@@ -12,8 +12,8 @@ pycti/api/opencti_api_trash.py,sha256=r_zi57n5TfLw9LYs2UFg33Nvyy3Huc6CjpK2mRQsma
|
|
|
12
12
|
pycti/api/opencti_api_work.py,sha256=IucltT8DcZtJV3NO4RbVi6tnGtjbyxD78_FIHAPYmK0,9261
|
|
13
13
|
pycti/api/opencti_api_workspace.py,sha256=ycqOTEXeUHF2k8H4jhoYDd1W6ijFcNUjYf4eSdLpH0k,611
|
|
14
14
|
pycti/connector/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
-
pycti/connector/opencti_connector.py,sha256=
|
|
16
|
-
pycti/connector/opencti_connector_helper.py,sha256=
|
|
15
|
+
pycti/connector/opencti_connector.py,sha256=TQpyCH2y3GZgvoniLbAn4Lkf039WzIj5mYQdcMvlj24,2994
|
|
16
|
+
pycti/connector/opencti_connector_helper.py,sha256=VsA-Gj9wasFStQEGG1vjMEMkYcOe72lDabOb1NUqkGg,95815
|
|
17
17
|
pycti/connector/opencti_metric_handler.py,sha256=piykdwqNUh5klpPAogsbo7tn0N7sa3wU4D2BQieNEso,4725
|
|
18
18
|
pycti/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
19
|
pycti/entities/opencti_attack_pattern.py,sha256=Mf5ltnxG5XIgMdaplhSBFhuMBwsjGFZvkfhTX7jpTOw,23580
|
|
@@ -49,10 +49,11 @@ pycti/entities/opencti_observed_data.py,sha256=ME1YvnU2-y8M-88LfwvnkNKsZbNK7_BJR
|
|
|
49
49
|
pycti/entities/opencti_opinion.py,sha256=1kG6J5WhxgPi8NpNmyAyy4bZjEMc4h8Jl8OzB7s6XNc,22852
|
|
50
50
|
pycti/entities/opencti_report.py,sha256=AT88ZBipX2LqrR4gFEK7btifcZ12fKtfy1zRZoQkufc,35507
|
|
51
51
|
pycti/entities/opencti_role.py,sha256=ryfPmZ_ch2sRGgqEr6_qxChTcGoeqvHW0MvlGHkLgdw,14039
|
|
52
|
-
pycti/entities/
|
|
52
|
+
pycti/entities/opencti_security_coverage.py,sha256=1rEs-8NFFj1D8R_IMpaEPyIM4CS_jZgnKx_8Ykkw1Oo,12487
|
|
53
|
+
pycti/entities/opencti_settings.py,sha256=aCbVUACuOK7AXvHp1tPDf3HBftFzJrZ60vHFu_pudAA,13469
|
|
53
54
|
pycti/entities/opencti_stix.py,sha256=W8DQSg1QfWFNU1hR4jHiSbzB_N9BMakSlQTl-yOVQbQ,2616
|
|
54
55
|
pycti/entities/opencti_stix_core_object.py,sha256=EAAdFkAd3jKSNXSqV2oSLtDhSMYf0iID7oQwEvI7Xb0,63719
|
|
55
|
-
pycti/entities/opencti_stix_core_relationship.py,sha256=
|
|
56
|
+
pycti/entities/opencti_stix_core_relationship.py,sha256=wgPvzVvFRb4plQVfDebrtI4SSqcr2abpqLeV0VcpZuM,48631
|
|
56
57
|
pycti/entities/opencti_stix_cyber_observable.py,sha256=2k7PRSP6DQEpOH37T_pkxoq4hRtTGI_PQruVM55C7XM,93698
|
|
57
58
|
pycti/entities/opencti_stix_domain_object.py,sha256=6VGill8b0Vr22yUe8fAP0dOpWDXaDtteJ4rqhLqwzKM,83173
|
|
58
59
|
pycti/entities/opencti_stix_nested_ref_relationship.py,sha256=81mS3ccqlsiZf20ssvhTPmtDvoTsBWPUSXe2pkulQVc,12705
|
|
@@ -74,13 +75,13 @@ pycti/entities/stix_cyber_observable/opencti_stix_cyber_observable_properties.py
|
|
|
74
75
|
pycti/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
75
76
|
pycti/utils/constants.py,sha256=VRYRvDm6hkTR0ZcHHWMzQBwqlPRskYnusBpgoX0S05A,12854
|
|
76
77
|
pycti/utils/opencti_logger.py,sha256=MApWthWJrSeBI0rumnhLhBtanjrtmfP6PJqOiQjcCOY,4091
|
|
77
|
-
pycti/utils/opencti_stix2.py,sha256=
|
|
78
|
+
pycti/utils/opencti_stix2.py,sha256=R0_VRGmd8xaCpSjbol79y8jn0CRrjatd1T2FuUhbIos,137177
|
|
78
79
|
pycti/utils/opencti_stix2_identifier.py,sha256=k8L1z4q1xdCBfxqUba4YS_kT-MmbJFxYh0RvfGOmrOs,837
|
|
79
80
|
pycti/utils/opencti_stix2_splitter.py,sha256=nMGbFPtGz2Vaeb6asWyPiOntHFNjREzJnbLEJHDV_T0,11539
|
|
80
81
|
pycti/utils/opencti_stix2_update.py,sha256=CnMyqkeVA0jgyxEcgqna8sABU4YPMjkEJ228GVurIn4,14658
|
|
81
|
-
pycti/utils/opencti_stix2_utils.py,sha256=
|
|
82
|
-
pycti-6.8.
|
|
83
|
-
pycti-6.8.
|
|
84
|
-
pycti-6.8.
|
|
85
|
-
pycti-6.8.
|
|
86
|
-
pycti-6.8.
|
|
82
|
+
pycti/utils/opencti_stix2_utils.py,sha256=J9DCD11bETq4Dowur3RovddbHOIMBeXBg13gLPHRLkA,7570
|
|
83
|
+
pycti-6.8.9.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
84
|
+
pycti-6.8.9.dist-info/METADATA,sha256=FzK12UjBPNtUfHcP_7EaAduU2WvmFVMssZl6EmZ0V4Q,5808
|
|
85
|
+
pycti-6.8.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
86
|
+
pycti-6.8.9.dist-info/top_level.txt,sha256=cqEpxitAhHP4VgSA6xmrak6Yk9MeBkwoMTB6k7d2ZnE,6
|
|
87
|
+
pycti-6.8.9.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|