pycti 6.0.10__py3-none-any.whl → 6.1.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 +1 -1
- pycti/api/opencti_api_client.py +15 -5
- pycti/api/opencti_api_playbook.py +3 -2
- pycti/connector/opencti_connector_helper.py +10 -6
- pycti/entities/opencti_case_incident.py +1 -1
- pycti/entities/opencti_intrusion_set.py +34 -14
- pycti/entities/opencti_report.py +13 -0
- pycti/entities/opencti_stix_core_object.py +32 -5
- pycti/entities/opencti_stix_cyber_observable.py +23 -3
- pycti/entities/opencti_stix_domain_object.py +27 -7
- pycti/entities/opencti_stix_object_or_stix_relationship.py +88 -4
- pycti/utils/constants.py +0 -1
- pycti/utils/opencti_stix2.py +269 -187
- {pycti-6.0.10.dist-info → pycti-6.1.1.dist-info}/METADATA +2 -2
- {pycti-6.0.10.dist-info → pycti-6.1.1.dist-info}/RECORD +18 -18
- {pycti-6.0.10.dist-info → pycti-6.1.1.dist-info}/LICENSE +0 -0
- {pycti-6.0.10.dist-info → pycti-6.1.1.dist-info}/WHEEL +0 -0
- {pycti-6.0.10.dist-info → pycti-6.1.1.dist-info}/top_level.txt +0 -0
pycti/__init__.py
CHANGED
pycti/api/opencti_api_client.py
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
288
|
-
|
|
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,
|
|
@@ -312,7 +314,9 @@ class ListenQueue(threading.Thread):
|
|
|
312
314
|
# If not playbook but enrichment, compute object on enrichment_entity
|
|
313
315
|
opencti_entity = event_data["enrichment_entity"]
|
|
314
316
|
stix_objects = self.helper.api.stix2.prepare_export(
|
|
315
|
-
self.helper.api.stix2.generate_export(
|
|
317
|
+
entity=self.helper.api.stix2.generate_export(
|
|
318
|
+
copy.copy(opencti_entity)
|
|
319
|
+
)
|
|
316
320
|
)
|
|
317
321
|
stix_entity = [
|
|
318
322
|
e
|
|
@@ -1565,7 +1569,7 @@ class OpenCTIConnectorHelper: # pylint: disable=too-many-public-methods
|
|
|
1565
1569
|
if bundle is None:
|
|
1566
1570
|
# Generate bundle
|
|
1567
1571
|
stix_objects = self.api.stix2.prepare_export(
|
|
1568
|
-
self.api.stix2.generate_export(copy.copy(opencti_entity))
|
|
1572
|
+
entity=self.api.stix2.generate_export(copy.copy(opencti_entity))
|
|
1569
1573
|
)
|
|
1570
1574
|
else:
|
|
1571
1575
|
stix_objects = bundle["objects"]
|
|
@@ -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["
|
|
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,
|
|
@@ -275,20 +275,40 @@ class IntrusionSet:
|
|
|
275
275
|
}
|
|
276
276
|
"""
|
|
277
277
|
)
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
278
|
+
variables = {
|
|
279
|
+
"filters": filters,
|
|
280
|
+
"search": search,
|
|
281
|
+
"first": first,
|
|
282
|
+
"after": after,
|
|
283
|
+
"orderBy": order_by,
|
|
284
|
+
"orderMode": order_mode,
|
|
285
|
+
}
|
|
286
|
+
result = self.opencti.query(query, variables)
|
|
287
|
+
if get_all:
|
|
288
|
+
final_data = []
|
|
289
|
+
data = self.opencti.process_multiple(result["data"]["intrusionSets"])
|
|
290
|
+
final_data = final_data + data
|
|
291
|
+
while result["data"]["intrusionSets"]["pageInfo"]["hasNextPage"]:
|
|
292
|
+
after = result["data"]["intrusionSets"]["pageInfo"]["endCursor"]
|
|
293
|
+
self.opencti.app_logger.info("Listing Intrusion-Sets", {"after": after})
|
|
294
|
+
result = self.opencti.query(
|
|
295
|
+
query,
|
|
296
|
+
{
|
|
297
|
+
"filters": filters,
|
|
298
|
+
"search": search,
|
|
299
|
+
"first": first,
|
|
300
|
+
"after": after,
|
|
301
|
+
"orderBy": order_by,
|
|
302
|
+
"orderMode": order_mode,
|
|
303
|
+
},
|
|
304
|
+
)
|
|
305
|
+
data = self.opencti.process_multiple(result["data"]["intrusionSets"])
|
|
306
|
+
final_data = final_data + data
|
|
307
|
+
return final_data
|
|
308
|
+
else:
|
|
309
|
+
return self.opencti.process_multiple(
|
|
310
|
+
result["data"]["intrusionSets"], with_pagination
|
|
311
|
+
)
|
|
292
312
|
|
|
293
313
|
"""
|
|
294
314
|
Read a Intrusion-Set object
|
pycti/entities/opencti_report.py
CHANGED
|
@@ -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,
|
|
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,
|
|
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(
|
|
2323
|
-
|
|
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,
|
|
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,26 @@ 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(
|
|
1357
|
+
def push_entity_export(
|
|
1358
|
+
self, entity_id, file_name, data, file_markings=None, mime_type=None
|
|
1359
|
+
):
|
|
1360
|
+
if file_markings is None:
|
|
1361
|
+
file_markings = []
|
|
1350
1362
|
query = """
|
|
1351
|
-
mutation StixDomainObjectEdit(
|
|
1363
|
+
mutation StixDomainObjectEdit(
|
|
1364
|
+
$id: ID!, $file: Upload!,
|
|
1365
|
+
$file_markings: [String]!
|
|
1366
|
+
) {
|
|
1352
1367
|
stixDomainObjectEdit(id: $id) {
|
|
1353
|
-
exportPush(
|
|
1368
|
+
exportPush(
|
|
1369
|
+
file: $file,
|
|
1370
|
+
file_markings: $file_markings
|
|
1371
|
+
)
|
|
1354
1372
|
}
|
|
1355
1373
|
}
|
|
1356
1374
|
"""
|
|
@@ -1358,7 +1376,9 @@ class StixDomainObject:
|
|
|
1358
1376
|
file = self.file(file_name, data)
|
|
1359
1377
|
else:
|
|
1360
1378
|
file = self.file(file_name, data, mime_type)
|
|
1361
|
-
self.opencti.query(
|
|
1379
|
+
self.opencti.query(
|
|
1380
|
+
query, {"id": entity_id, "file": file, "file_markings": file_markings}
|
|
1381
|
+
)
|
|
1362
1382
|
|
|
1363
1383
|
"""
|
|
1364
1384
|
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
|
-
|
|
480
|
-
|
|
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,76 @@ 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
|
+
get_all = kwargs.get("getAll", False)
|
|
517
|
+
with_pagination = kwargs.get("with_pagination", False)
|
|
518
|
+
custom_attributes = kwargs.get("customAttributes", None)
|
|
519
|
+
|
|
520
|
+
self.opencti.app_logger.info(
|
|
521
|
+
"Listing StixObjectOrStixRelationships with filters",
|
|
522
|
+
{"filters": json.dumps(filters)},
|
|
523
|
+
)
|
|
524
|
+
query = (
|
|
525
|
+
"""
|
|
526
|
+
query StixObjectOrStixRelationships($filters: FilterGroup, $search: String, $first: Int, $after: ID) {
|
|
527
|
+
stixObjectOrStixRelationships(filters: $filters, search: $search, first: $first, after: $after) {
|
|
528
|
+
edges {
|
|
529
|
+
node {
|
|
530
|
+
"""
|
|
531
|
+
+ (custom_attributes if custom_attributes is not None else self.properties)
|
|
532
|
+
+ """
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
pageInfo {
|
|
536
|
+
startCursor
|
|
537
|
+
endCursor
|
|
538
|
+
hasNextPage
|
|
539
|
+
hasPreviousPage
|
|
540
|
+
globalCount
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
"""
|
|
545
|
+
)
|
|
546
|
+
variables = {
|
|
547
|
+
"filters": filters,
|
|
548
|
+
"search": search,
|
|
549
|
+
"first": first,
|
|
550
|
+
"after": after,
|
|
551
|
+
}
|
|
552
|
+
result = self.opencti.query(
|
|
553
|
+
query,
|
|
554
|
+
variables,
|
|
555
|
+
)
|
|
556
|
+
|
|
557
|
+
if get_all:
|
|
558
|
+
final_data = []
|
|
559
|
+
data = self.opencti.process_multiple(
|
|
560
|
+
result["data"]["stixObjectOrStixRelationships"]
|
|
561
|
+
)
|
|
562
|
+
final_data = final_data + data
|
|
563
|
+
while result["data"]["stixObjectOrStixRelationships"]["pageInfo"][
|
|
564
|
+
"hasNextPage"
|
|
565
|
+
]:
|
|
566
|
+
after = result["data"]["stixObjectOrStixRelationships"]["pageInfo"][
|
|
567
|
+
"endCursor"
|
|
568
|
+
]
|
|
569
|
+
self.opencti.app_logger.info(
|
|
570
|
+
"Listing stixObjectOrStixRelationships", {"after": after}
|
|
571
|
+
)
|
|
572
|
+
after_variables = {**variables, **{"after": after}}
|
|
573
|
+
result = self.opencti.query(query, after_variables)
|
|
574
|
+
data = self.opencti.process_multiple(
|
|
575
|
+
result["data"]["stixObjectOrStixRelationships"]
|
|
576
|
+
)
|
|
577
|
+
final_data = final_data + data
|
|
578
|
+
return final_data
|
|
579
|
+
else:
|
|
580
|
+
return self.opencti.process_multiple(
|
|
581
|
+
result["data"]["stixObjectOrStixRelationships"], with_pagination
|
|
582
|
+
)
|
pycti/utils/constants.py
CHANGED
|
@@ -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"
|
pycti/utils/opencti_stix2.py
CHANGED
|
@@ -135,43 +135,6 @@ class OpenCTIStix2:
|
|
|
135
135
|
return stix_object["aliases"]
|
|
136
136
|
return None
|
|
137
137
|
|
|
138
|
-
def check_max_marking_definition(
|
|
139
|
-
self, max_marking_definition_entity: Dict, entity_marking_definitions: List
|
|
140
|
-
) -> bool:
|
|
141
|
-
"""checks if a list of marking definitions conforms with a given max level
|
|
142
|
-
|
|
143
|
-
:param max_marking_definition_entity: the maximum allowed marking definition level
|
|
144
|
-
:type max_marking_definition_entity: str, optional
|
|
145
|
-
:param entity_marking_definitions: list of entities to check
|
|
146
|
-
:type entity_marking_definitions: list
|
|
147
|
-
:return: `True` if the list conforms with max marking definition
|
|
148
|
-
:rtype: bool
|
|
149
|
-
"""
|
|
150
|
-
|
|
151
|
-
# Max is not set, return True
|
|
152
|
-
if max_marking_definition_entity is None:
|
|
153
|
-
return True
|
|
154
|
-
# Filter entity markings definition to the max_marking_definition type
|
|
155
|
-
typed_entity_marking_definitions = []
|
|
156
|
-
for entity_marking_definition in entity_marking_definitions:
|
|
157
|
-
if (
|
|
158
|
-
entity_marking_definition["definition_type"]
|
|
159
|
-
== max_marking_definition_entity["definition_type"]
|
|
160
|
-
):
|
|
161
|
-
typed_entity_marking_definitions.append(entity_marking_definition)
|
|
162
|
-
# No entity marking defintions of the max_marking_definition type
|
|
163
|
-
if len(typed_entity_marking_definitions) == 0:
|
|
164
|
-
return True
|
|
165
|
-
|
|
166
|
-
# Check if level is less or equal to max
|
|
167
|
-
for typed_entity_marking_definition in typed_entity_marking_definitions:
|
|
168
|
-
if (
|
|
169
|
-
typed_entity_marking_definition["x_opencti_order"]
|
|
170
|
-
<= max_marking_definition_entity["x_opencti_order"]
|
|
171
|
-
):
|
|
172
|
-
return True
|
|
173
|
-
return False
|
|
174
|
-
|
|
175
138
|
def import_bundle_from_file(
|
|
176
139
|
self, file_path: str, update: bool = False, types: List = None
|
|
177
140
|
) -> Optional[List]:
|
|
@@ -680,6 +643,9 @@ class OpenCTIStix2:
|
|
|
680
643
|
|
|
681
644
|
author = self.resolve_author(title)
|
|
682
645
|
report = self.opencti.report.create(
|
|
646
|
+
id=self.opencti.report.generate_fixed_fake_id(
|
|
647
|
+
title, published
|
|
648
|
+
),
|
|
683
649
|
name=title,
|
|
684
650
|
createdBy=author["id"] if author is not None else None,
|
|
685
651
|
objectMarking=[object_marking_ref_result["id"]],
|
|
@@ -788,6 +754,48 @@ class OpenCTIStix2:
|
|
|
788
754
|
"reports": reports,
|
|
789
755
|
}
|
|
790
756
|
|
|
757
|
+
def get_listers(self):
|
|
758
|
+
return {
|
|
759
|
+
"Stix-Core-Object": self.opencti.stix_core_object.list,
|
|
760
|
+
"Stix-Domain-Object": self.opencti.stix_domain_object.list,
|
|
761
|
+
"Administrative-Area": self.opencti.location.list,
|
|
762
|
+
"Attack-Pattern": self.opencti.attack_pattern.list,
|
|
763
|
+
"Campaign": self.opencti.campaign.list,
|
|
764
|
+
"Channel": self.opencti.channel.list,
|
|
765
|
+
"Event": self.opencti.event.list,
|
|
766
|
+
"Note": self.opencti.note.list,
|
|
767
|
+
"Observed-Data": self.opencti.observed_data.list,
|
|
768
|
+
"Opinion": self.opencti.opinion.list,
|
|
769
|
+
"Report": self.opencti.report.list,
|
|
770
|
+
"Grouping": self.opencti.grouping.list,
|
|
771
|
+
"Case-Incident": self.opencti.case_incident.list,
|
|
772
|
+
"Feedback": self.opencti.feedback.list,
|
|
773
|
+
"Case-Rfi": self.opencti.case_rfi.list,
|
|
774
|
+
"Case-Rft": self.opencti.case_rft.list,
|
|
775
|
+
"Task": self.opencti.task.list,
|
|
776
|
+
"Course-Of-Action": self.opencti.course_of_action.list,
|
|
777
|
+
"Data-Component": self.opencti.data_component.list,
|
|
778
|
+
"Data-Source": self.opencti.data_source.list,
|
|
779
|
+
"Identity": self.opencti.identity.list,
|
|
780
|
+
"Indicator": self.opencti.indicator.list,
|
|
781
|
+
"Infrastructure": self.opencti.infrastructure.list,
|
|
782
|
+
"Intrusion-Set": self.opencti.intrusion_set.list,
|
|
783
|
+
"Location": self.opencti.location.list,
|
|
784
|
+
"Language": self.opencti.language.list,
|
|
785
|
+
"Malware": self.opencti.malware.list,
|
|
786
|
+
"Malware-Analysis": self.opencti.malware_analysis.list,
|
|
787
|
+
"Threat-Actor": self.opencti.threat_actor_group.list,
|
|
788
|
+
"Threat-Actor-Group": self.opencti.threat_actor_group.list,
|
|
789
|
+
"Threat-Actor-Individual": self.opencti.threat_actor_individual.list,
|
|
790
|
+
"Tool": self.opencti.tool.list,
|
|
791
|
+
"Narrative": self.opencti.narrative.list,
|
|
792
|
+
"Vulnerability": self.opencti.vulnerability.list,
|
|
793
|
+
"Incident": self.opencti.incident.list,
|
|
794
|
+
"Stix-Cyber-Observable": self.opencti.stix_cyber_observable.list,
|
|
795
|
+
"stix-sighting-relationship": self.opencti.stix_sighting_relationship.list,
|
|
796
|
+
"stix-core-relationship": self.opencti.stix_core_relationship.list,
|
|
797
|
+
}
|
|
798
|
+
|
|
791
799
|
def get_readers(self):
|
|
792
800
|
return {
|
|
793
801
|
"Attack-Pattern": self.opencti.attack_pattern.read,
|
|
@@ -1512,7 +1520,7 @@ class OpenCTIStix2:
|
|
|
1512
1520
|
if "tasks" in entity:
|
|
1513
1521
|
del entity["tasks"]
|
|
1514
1522
|
|
|
1515
|
-
if "status" in entity:
|
|
1523
|
+
if "status" in entity and entity["status"] is not None:
|
|
1516
1524
|
entity["x_opencti_workflow_id"] = entity["status"].get("id")
|
|
1517
1525
|
if "status" in entity:
|
|
1518
1526
|
del entity["status"]
|
|
@@ -1614,35 +1622,72 @@ class OpenCTIStix2:
|
|
|
1614
1622
|
|
|
1615
1623
|
return {k: v for k, v in entity.items() if self.opencti.not_empty(v)}
|
|
1616
1624
|
|
|
1625
|
+
@staticmethod
|
|
1626
|
+
def prepare_id_filters_export(
|
|
1627
|
+
id: Union[str, List[str]], access_filter: Dict = None
|
|
1628
|
+
) -> Dict:
|
|
1629
|
+
if access_filter is not None:
|
|
1630
|
+
return {
|
|
1631
|
+
"mode": "and",
|
|
1632
|
+
"filterGroups": [
|
|
1633
|
+
{
|
|
1634
|
+
"mode": "or",
|
|
1635
|
+
"filters": [
|
|
1636
|
+
{
|
|
1637
|
+
"key": "ids",
|
|
1638
|
+
"values": id if isinstance(id, list) else [id],
|
|
1639
|
+
}
|
|
1640
|
+
],
|
|
1641
|
+
"filterGroups": [],
|
|
1642
|
+
},
|
|
1643
|
+
access_filter,
|
|
1644
|
+
],
|
|
1645
|
+
"filters": [],
|
|
1646
|
+
}
|
|
1647
|
+
else:
|
|
1648
|
+
return {
|
|
1649
|
+
"mode": "and",
|
|
1650
|
+
"filterGroups": [],
|
|
1651
|
+
"filters": [
|
|
1652
|
+
{
|
|
1653
|
+
"key": "ids",
|
|
1654
|
+
"mode": "or",
|
|
1655
|
+
"values": id if isinstance(id, list) else [id],
|
|
1656
|
+
}
|
|
1657
|
+
],
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1617
1660
|
def prepare_export(
|
|
1618
1661
|
self,
|
|
1619
1662
|
entity: Dict,
|
|
1620
1663
|
mode: str = "simple",
|
|
1621
|
-
|
|
1664
|
+
access_filter: Dict = None,
|
|
1622
1665
|
no_custom_attributes: bool = False,
|
|
1623
1666
|
) -> 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
1667
|
result = []
|
|
1637
1668
|
objects_to_get = []
|
|
1638
1669
|
relations_to_get = []
|
|
1670
|
+
|
|
1671
|
+
# Container
|
|
1672
|
+
if "objects" in entity and len(entity["objects"]) > 0:
|
|
1673
|
+
object_ids = list(map(lambda e: e["standard_id"], entity["objects"]))
|
|
1674
|
+
export_query_filter = self.prepare_id_filters_export(
|
|
1675
|
+
id=object_ids, access_filter=access_filter
|
|
1676
|
+
)
|
|
1677
|
+
filtered_objects = (
|
|
1678
|
+
self.opencti.opencti_stix_object_or_stix_relationship.list(
|
|
1679
|
+
filters=export_query_filter, getAll=True
|
|
1680
|
+
)
|
|
1681
|
+
)
|
|
1682
|
+
entity["objects"] = filtered_objects
|
|
1683
|
+
|
|
1639
1684
|
# CreatedByRef
|
|
1640
1685
|
if (
|
|
1641
1686
|
not no_custom_attributes
|
|
1642
1687
|
and "createdBy" in entity
|
|
1643
1688
|
and entity["createdBy"] is not None
|
|
1644
1689
|
):
|
|
1645
|
-
created_by = self.generate_export(entity["createdBy"])
|
|
1690
|
+
created_by = self.generate_export(entity=entity["createdBy"])
|
|
1646
1691
|
if entity["type"] in STIX_CYBER_OBSERVABLE_MAPPING:
|
|
1647
1692
|
entity["x_opencti_created_by_ref"] = created_by["id"]
|
|
1648
1693
|
else:
|
|
@@ -1747,7 +1792,7 @@ class OpenCTIStix2:
|
|
|
1747
1792
|
and len(entity["objects"]) > 0
|
|
1748
1793
|
):
|
|
1749
1794
|
entity["object_refs"] = []
|
|
1750
|
-
objects_to_get = entity["objects"]
|
|
1795
|
+
objects_to_get = entity["objects"] # To do differently
|
|
1751
1796
|
for entity_object in entity["objects"]:
|
|
1752
1797
|
if (
|
|
1753
1798
|
entity["type"] == "report"
|
|
@@ -1819,22 +1864,62 @@ class OpenCTIStix2:
|
|
|
1819
1864
|
entity["type"] = "sighting"
|
|
1820
1865
|
entity["count"] = entity["attribute_count"]
|
|
1821
1866
|
del entity["attribute_count"]
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1867
|
+
from_to_check = entity["from"]["id"]
|
|
1868
|
+
relationships_from_filter = self.prepare_id_filters_export(
|
|
1869
|
+
id=from_to_check, access_filter=access_filter
|
|
1870
|
+
)
|
|
1871
|
+
x = self.opencti.opencti_stix_object_or_stix_relationship.list(
|
|
1872
|
+
filters=relationships_from_filter
|
|
1873
|
+
)
|
|
1874
|
+
if len(x) > 0:
|
|
1875
|
+
entity["sighting_of_ref"] = entity["from"]["id"]
|
|
1876
|
+
# handle from and to separately like Stix Core Relationship and call 2 requests
|
|
1877
|
+
objects_to_get.append(
|
|
1878
|
+
entity["from"]
|
|
1879
|
+
) # what happen with unauthorized objects ?
|
|
1880
|
+
|
|
1881
|
+
to_to_check = [entity["to"]["id"]]
|
|
1882
|
+
relationships_to_filter = self.prepare_id_filters_export(
|
|
1883
|
+
id=to_to_check, access_filter=access_filter
|
|
1884
|
+
)
|
|
1885
|
+
y = self.opencti.opencti_stix_object_or_stix_relationship.list(
|
|
1886
|
+
filters=relationships_to_filter
|
|
1887
|
+
)
|
|
1888
|
+
if len(y) > 0:
|
|
1889
|
+
entity["where_sighted_refs"] = [entity["to"]["id"]]
|
|
1890
|
+
objects_to_get.append(entity["to"])
|
|
1891
|
+
|
|
1826
1892
|
del entity["from"]
|
|
1827
1893
|
del entity["to"]
|
|
1828
1894
|
# Stix Core Relationship
|
|
1829
1895
|
if "from" in entity or "to" in entity:
|
|
1830
1896
|
entity["type"] = "relationship"
|
|
1831
1897
|
if "from" in entity:
|
|
1832
|
-
|
|
1833
|
-
|
|
1898
|
+
from_to_check = entity["from"]["id"]
|
|
1899
|
+
relationships_from_filter = self.prepare_id_filters_export(
|
|
1900
|
+
id=from_to_check, access_filter=access_filter
|
|
1901
|
+
)
|
|
1902
|
+
x = self.opencti.opencti_stix_object_or_stix_relationship.list(
|
|
1903
|
+
filters=relationships_from_filter
|
|
1904
|
+
)
|
|
1905
|
+
if len(x) > 0:
|
|
1906
|
+
entity["source_ref"] = entity["from"]["id"]
|
|
1907
|
+
# handle from and to separately like Stix Core Relationship and call 2 requests
|
|
1908
|
+
objects_to_get.append(
|
|
1909
|
+
entity["from"]
|
|
1910
|
+
) # what happen with unauthorized objects ?
|
|
1834
1911
|
del entity["from"]
|
|
1835
1912
|
if "to" in entity:
|
|
1836
|
-
|
|
1837
|
-
|
|
1913
|
+
to_to_check = [entity["to"]["id"]]
|
|
1914
|
+
relationships_to_filter = self.prepare_id_filters_export(
|
|
1915
|
+
id=to_to_check, access_filter=access_filter
|
|
1916
|
+
)
|
|
1917
|
+
y = self.opencti.opencti_stix_object_or_stix_relationship.list(
|
|
1918
|
+
filters=relationships_to_filter
|
|
1919
|
+
)
|
|
1920
|
+
if len(y) > 0:
|
|
1921
|
+
entity["target_ref"] = entity["to"]["id"]
|
|
1922
|
+
objects_to_get.append(entity["to"])
|
|
1838
1923
|
del entity["to"]
|
|
1839
1924
|
# Stix Domain Object
|
|
1840
1925
|
if "attribute_abstract" in entity:
|
|
@@ -1877,7 +1962,7 @@ class OpenCTIStix2:
|
|
|
1877
1962
|
|
|
1878
1963
|
# StixRefRelationship
|
|
1879
1964
|
stix_nested_ref_relationships = self.opencti.stix_nested_ref_relationship.list(
|
|
1880
|
-
fromId=entity["x_opencti_id"]
|
|
1965
|
+
fromId=entity["x_opencti_id"], filters=access_filter
|
|
1881
1966
|
)
|
|
1882
1967
|
for stix_nested_ref_relationship in stix_nested_ref_relationships:
|
|
1883
1968
|
if "standard_id" in stix_nested_ref_relationship["to"]:
|
|
@@ -1921,8 +2006,8 @@ class OpenCTIStix2:
|
|
|
1921
2006
|
return result
|
|
1922
2007
|
elif mode == "full":
|
|
1923
2008
|
uuids = [entity["id"]]
|
|
1924
|
-
for
|
|
1925
|
-
uuids.append(
|
|
2009
|
+
for y in result:
|
|
2010
|
+
uuids.append(y["id"])
|
|
1926
2011
|
# Get extra refs
|
|
1927
2012
|
for key in entity.keys():
|
|
1928
2013
|
if key.endswith("_ref"):
|
|
@@ -1964,80 +2049,50 @@ class OpenCTIStix2:
|
|
|
1964
2049
|
)
|
|
1965
2050
|
# Get extra relations (from AND to)
|
|
1966
2051
|
stix_core_relationships = self.opencti.stix_core_relationship.list(
|
|
1967
|
-
fromOrToId=entity["x_opencti_id"], getAll=True
|
|
2052
|
+
fromOrToId=entity["x_opencti_id"], getAll=True, filters=access_filter
|
|
1968
2053
|
)
|
|
1969
2054
|
for stix_core_relationship in stix_core_relationships:
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
if stix_core_relationship["to"]["id"] != entity["x_opencti_id"]
|
|
1981
|
-
else stix_core_relationship["from"]
|
|
1982
|
-
)
|
|
1983
|
-
relation_object_data = self.prepare_export(
|
|
1984
|
-
self.generate_export(stix_core_relationship),
|
|
1985
|
-
"simple",
|
|
1986
|
-
max_marking_definition_entity,
|
|
1987
|
-
)
|
|
1988
|
-
relation_object_bundle = self.filter_objects(
|
|
1989
|
-
uuids, relation_object_data
|
|
1990
|
-
)
|
|
1991
|
-
uuids = uuids + [x["id"] for x in relation_object_bundle]
|
|
1992
|
-
result = result + relation_object_bundle
|
|
1993
|
-
else:
|
|
1994
|
-
self.opencti.app_logger.info(
|
|
1995
|
-
"Marking definitions are less than max definition, "
|
|
1996
|
-
"not exporting the relation AND the target entity.",
|
|
1997
|
-
{
|
|
1998
|
-
"type": stix_core_relationship["entity_type"],
|
|
1999
|
-
"id": stix_core_relationship["id"],
|
|
2000
|
-
},
|
|
2055
|
+
objects_to_get.append(
|
|
2056
|
+
stix_core_relationship["to"]
|
|
2057
|
+
if stix_core_relationship["to"]["id"] != entity["x_opencti_id"]
|
|
2058
|
+
else stix_core_relationship["from"]
|
|
2059
|
+
)
|
|
2060
|
+
relation_object_data = (
|
|
2061
|
+
self.prepare_export( # ICI -> remove max marking ?
|
|
2062
|
+
entity=self.generate_export(stix_core_relationship),
|
|
2063
|
+
mode="simple",
|
|
2064
|
+
access_filter=access_filter,
|
|
2001
2065
|
)
|
|
2066
|
+
)
|
|
2067
|
+
relation_object_bundle = self.filter_objects(
|
|
2068
|
+
uuids, relation_object_data
|
|
2069
|
+
)
|
|
2070
|
+
uuids = uuids + [x["id"] for x in relation_object_bundle]
|
|
2071
|
+
result = result + relation_object_bundle
|
|
2072
|
+
|
|
2002
2073
|
# Get sighting
|
|
2003
2074
|
stix_sighting_relationships = self.opencti.stix_sighting_relationship.list(
|
|
2004
|
-
fromOrToId=entity["x_opencti_id"],
|
|
2005
|
-
getAll=True,
|
|
2075
|
+
fromOrToId=entity["x_opencti_id"], getAll=True, filters=access_filter
|
|
2006
2076
|
)
|
|
2007
2077
|
for stix_sighting_relationship in stix_sighting_relationships:
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
if stix_sighting_relationship["to"]["id"]
|
|
2019
|
-
!= entity["x_opencti_id"]
|
|
2020
|
-
else stix_sighting_relationship["from"]
|
|
2021
|
-
)
|
|
2022
|
-
relation_object_data = self.prepare_export(
|
|
2023
|
-
self.generate_export(stix_sighting_relationship),
|
|
2024
|
-
"simple",
|
|
2025
|
-
max_marking_definition_entity,
|
|
2026
|
-
)
|
|
2027
|
-
relation_object_bundle = self.filter_objects(
|
|
2028
|
-
uuids, relation_object_data
|
|
2029
|
-
)
|
|
2030
|
-
uuids = uuids + [x["id"] for x in relation_object_bundle]
|
|
2031
|
-
result = result + relation_object_bundle
|
|
2032
|
-
else:
|
|
2033
|
-
self.opencti.app_logger.info(
|
|
2034
|
-
"Marking definitions are less than max definition, "
|
|
2035
|
-
"not exporting the relation AND the target entity.",
|
|
2036
|
-
{
|
|
2037
|
-
"type": stix_sighting_relationship["entity_type"],
|
|
2038
|
-
"id": stix_sighting_relationship["id"],
|
|
2039
|
-
},
|
|
2078
|
+
objects_to_get.append(
|
|
2079
|
+
stix_sighting_relationship["to"]
|
|
2080
|
+
if stix_sighting_relationship["to"]["id"] != entity["x_opencti_id"]
|
|
2081
|
+
else stix_sighting_relationship["from"]
|
|
2082
|
+
)
|
|
2083
|
+
relation_object_data = (
|
|
2084
|
+
self.prepare_export( # ICI -> remove max marking ?
|
|
2085
|
+
entity=self.generate_export(stix_sighting_relationship),
|
|
2086
|
+
mode="simple",
|
|
2087
|
+
access_filter=access_filter,
|
|
2040
2088
|
)
|
|
2089
|
+
)
|
|
2090
|
+
relation_object_bundle = self.filter_objects(
|
|
2091
|
+
uuids, relation_object_data
|
|
2092
|
+
)
|
|
2093
|
+
uuids = uuids + [x["id"] for x in relation_object_bundle]
|
|
2094
|
+
result = result + relation_object_bundle
|
|
2095
|
+
|
|
2041
2096
|
if no_custom_attributes:
|
|
2042
2097
|
del entity["x_opencti_id"]
|
|
2043
2098
|
# Export
|
|
@@ -2065,12 +2120,16 @@ class OpenCTIStix2:
|
|
|
2065
2120
|
{"type": entity_object["entity_type"]}
|
|
2066
2121
|
),
|
|
2067
2122
|
)
|
|
2068
|
-
|
|
2123
|
+
|
|
2124
|
+
query_filters = self.prepare_id_filters_export(
|
|
2125
|
+
entity_object["id"], access_filter
|
|
2126
|
+
)
|
|
2127
|
+
entity_object_data = do_read(filters=query_filters)
|
|
2069
2128
|
if entity_object_data is not None:
|
|
2070
2129
|
stix_entity_object = self.prepare_export(
|
|
2071
|
-
self.generate_export(entity_object_data),
|
|
2072
|
-
"simple",
|
|
2073
|
-
|
|
2130
|
+
entity=self.generate_export(entity_object_data),
|
|
2131
|
+
mode="simple",
|
|
2132
|
+
access_filter=access_filter,
|
|
2074
2133
|
)
|
|
2075
2134
|
# Add to result
|
|
2076
2135
|
entity_object_bundle = self.filter_objects(
|
|
@@ -2078,9 +2137,18 @@ class OpenCTIStix2:
|
|
|
2078
2137
|
)
|
|
2079
2138
|
uuids = uuids + [x["id"] for x in entity_object_bundle]
|
|
2080
2139
|
result = result + entity_object_bundle
|
|
2081
|
-
for
|
|
2140
|
+
for (
|
|
2141
|
+
relation_object
|
|
2142
|
+
) in relations_to_get: # never appended after initialization
|
|
2143
|
+
|
|
2144
|
+
def find_relation_object_data(current_relation_object):
|
|
2145
|
+
return current_relation_object.id == relation_object["id"]
|
|
2146
|
+
|
|
2082
2147
|
relation_object_data = self.prepare_export(
|
|
2083
|
-
|
|
2148
|
+
entity=filter(
|
|
2149
|
+
find_relation_object_data,
|
|
2150
|
+
self.opencti.stix_core_relationship.list(filters=access_filter),
|
|
2151
|
+
)
|
|
2084
2152
|
)
|
|
2085
2153
|
relation_object_bundle = self.filter_objects(
|
|
2086
2154
|
uuids, relation_object_data
|
|
@@ -2097,7 +2165,6 @@ class OpenCTIStix2:
|
|
|
2097
2165
|
report_object_data = self.opencti.report.to_stix2(
|
|
2098
2166
|
entity=report,
|
|
2099
2167
|
mode="simple",
|
|
2100
|
-
max_marking_definition_entity=max_marking_definition_entity,
|
|
2101
2168
|
)
|
|
2102
2169
|
report_object_bundle = self.filter_objects(
|
|
2103
2170
|
uuids, report_object_data
|
|
@@ -2116,7 +2183,6 @@ class OpenCTIStix2:
|
|
|
2116
2183
|
# note_object_data = self.opencti.note.to_stix2(
|
|
2117
2184
|
# entity=note,
|
|
2118
2185
|
# mode="simple",
|
|
2119
|
-
# max_marking_definition_entity=max_marking_definition_entity,
|
|
2120
2186
|
# )
|
|
2121
2187
|
# note_object_bundle = self.filter_objects(
|
|
2122
2188
|
# uuids, note_object_data
|
|
@@ -2145,20 +2211,15 @@ class OpenCTIStix2:
|
|
|
2145
2211
|
else:
|
|
2146
2212
|
return []
|
|
2147
2213
|
|
|
2148
|
-
def
|
|
2214
|
+
def get_stix_bundle_or_object_from_entity_id(
|
|
2149
2215
|
self,
|
|
2150
2216
|
entity_type: str,
|
|
2151
2217
|
entity_id: str,
|
|
2152
2218
|
mode: str = "simple",
|
|
2153
|
-
|
|
2219
|
+
access_filter: Dict = None,
|
|
2154
2220
|
no_custom_attributes: bool = False,
|
|
2155
2221
|
only_entity: bool = False,
|
|
2156
2222
|
) -> 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
2223
|
bundle = {
|
|
2163
2224
|
"type": "bundle",
|
|
2164
2225
|
"id": "bundle--" + str(uuid.uuid4()),
|
|
@@ -2174,11 +2235,8 @@ class OpenCTIStix2:
|
|
|
2174
2235
|
if LocationTypes.has_value(entity_type):
|
|
2175
2236
|
entity_type = "Location"
|
|
2176
2237
|
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
if StixCyberObservableTypes.has_value(entity_type):
|
|
2180
|
-
entity_type = "Stix-Cyber-Observable"
|
|
2181
|
-
do_read = reader.get(
|
|
2238
|
+
readers = self.get_readers()
|
|
2239
|
+
do_read = readers.get(
|
|
2182
2240
|
entity_type, lambda **kwargs: self.unknown_type({"type": entity_type})
|
|
2183
2241
|
)
|
|
2184
2242
|
entity = do_read(id=entity_id)
|
|
@@ -2189,10 +2247,10 @@ class OpenCTIStix2:
|
|
|
2189
2247
|
return bundle
|
|
2190
2248
|
entity_standard_id = entity["standard_id"]
|
|
2191
2249
|
stix_objects = self.prepare_export(
|
|
2192
|
-
self.generate_export(entity, no_custom_attributes),
|
|
2193
|
-
mode,
|
|
2194
|
-
|
|
2195
|
-
no_custom_attributes,
|
|
2250
|
+
entity=self.generate_export(entity, no_custom_attributes),
|
|
2251
|
+
mode=mode,
|
|
2252
|
+
access_filter=access_filter,
|
|
2253
|
+
no_custom_attributes=no_custom_attributes,
|
|
2196
2254
|
)
|
|
2197
2255
|
if stix_objects is not None:
|
|
2198
2256
|
bundle["objects"].extend(stix_objects)
|
|
@@ -2202,15 +2260,35 @@ class OpenCTIStix2:
|
|
|
2202
2260
|
]
|
|
2203
2261
|
return bundle
|
|
2204
2262
|
|
|
2263
|
+
# Please use get_stix_bundle_or_object_from_entity_id instead
|
|
2264
|
+
@DeprecationWarning
|
|
2265
|
+
def export_entity(
|
|
2266
|
+
self,
|
|
2267
|
+
entity_type: str,
|
|
2268
|
+
entity_id: str,
|
|
2269
|
+
mode: str = "simple",
|
|
2270
|
+
access_filter: Dict = None,
|
|
2271
|
+
no_custom_attributes: bool = False,
|
|
2272
|
+
only_entity: bool = False,
|
|
2273
|
+
) -> Dict:
|
|
2274
|
+
return self.get_stix_bundle_or_object_from_entity_id(
|
|
2275
|
+
entity_type=entity_type,
|
|
2276
|
+
entity_id=entity_id,
|
|
2277
|
+
mode=mode,
|
|
2278
|
+
access_filter=access_filter,
|
|
2279
|
+
no_custom_attributes=no_custom_attributes,
|
|
2280
|
+
only_entity=only_entity,
|
|
2281
|
+
)
|
|
2282
|
+
|
|
2205
2283
|
def export_entities_list(
|
|
2206
2284
|
self,
|
|
2207
2285
|
entity_type: str,
|
|
2208
2286
|
search: Dict = None,
|
|
2209
|
-
filters:
|
|
2287
|
+
filters: Dict = None,
|
|
2210
2288
|
orderBy: str = None,
|
|
2211
2289
|
orderMode: str = None,
|
|
2212
2290
|
getAll: bool = True,
|
|
2213
|
-
) -> Dict:
|
|
2291
|
+
) -> [Dict]:
|
|
2214
2292
|
if IdentityTypes.has_value(entity_type):
|
|
2215
2293
|
entity_type = "Identity"
|
|
2216
2294
|
|
|
@@ -2279,26 +2357,31 @@ class OpenCTIStix2:
|
|
|
2279
2357
|
self,
|
|
2280
2358
|
entity_type: str,
|
|
2281
2359
|
search: Dict = None,
|
|
2282
|
-
filters:
|
|
2360
|
+
filters: Dict = None,
|
|
2283
2361
|
order_by: str = None,
|
|
2284
2362
|
order_mode: str = None,
|
|
2285
2363
|
mode: str = "simple",
|
|
2286
|
-
|
|
2364
|
+
access_filter: Dict = None,
|
|
2287
2365
|
) -> 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
2366
|
bundle = {
|
|
2294
2367
|
"type": "bundle",
|
|
2295
2368
|
"id": "bundle--" + str(uuid.uuid4()),
|
|
2296
2369
|
"objects": [],
|
|
2297
2370
|
}
|
|
2371
|
+
filter_groups = []
|
|
2372
|
+
if filters is not None:
|
|
2373
|
+
filter_groups.append(filters)
|
|
2374
|
+
if access_filter is not None:
|
|
2375
|
+
filter_groups.append(access_filter)
|
|
2376
|
+
export_query_filter = {
|
|
2377
|
+
"mode": "and",
|
|
2378
|
+
"filterGroups": filter_groups,
|
|
2379
|
+
"filters": [],
|
|
2380
|
+
}
|
|
2298
2381
|
entities_list = self.export_entities_list(
|
|
2299
2382
|
entity_type=entity_type,
|
|
2300
2383
|
search=search,
|
|
2301
|
-
filters=
|
|
2384
|
+
filters=export_query_filter,
|
|
2302
2385
|
orderBy=order_by,
|
|
2303
2386
|
orderMode=order_mode,
|
|
2304
2387
|
getAll=True,
|
|
@@ -2307,9 +2390,9 @@ class OpenCTIStix2:
|
|
|
2307
2390
|
uuids = []
|
|
2308
2391
|
for entity in entities_list:
|
|
2309
2392
|
entity_bundle = self.prepare_export(
|
|
2310
|
-
self.generate_export(entity),
|
|
2311
|
-
mode,
|
|
2312
|
-
|
|
2393
|
+
entity=self.generate_export(entity),
|
|
2394
|
+
mode=mode,
|
|
2395
|
+
access_filter=access_filter,
|
|
2313
2396
|
)
|
|
2314
2397
|
if entity_bundle is not None:
|
|
2315
2398
|
entity_bundle_filtered = self.filter_objects(uuids, entity_bundle)
|
|
@@ -2320,33 +2403,32 @@ class OpenCTIStix2:
|
|
|
2320
2403
|
|
|
2321
2404
|
def export_selected(
|
|
2322
2405
|
self,
|
|
2323
|
-
entities_list: [
|
|
2406
|
+
entities_list: [dict],
|
|
2324
2407
|
mode: str = "simple",
|
|
2325
|
-
|
|
2408
|
+
access_filter: Dict = None,
|
|
2326
2409
|
) -> Dict:
|
|
2327
|
-
|
|
2328
|
-
self.opencti.marking_definition.read(id=max_marking_definition)
|
|
2329
|
-
if max_marking_definition is not None
|
|
2330
|
-
else None
|
|
2331
|
-
)
|
|
2410
|
+
|
|
2332
2411
|
bundle = {
|
|
2333
2412
|
"type": "bundle",
|
|
2334
2413
|
"id": "bundle--" + str(uuid.uuid4()),
|
|
2335
2414
|
"objects": [],
|
|
2336
2415
|
}
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2416
|
+
|
|
2417
|
+
uuids = []
|
|
2418
|
+
for entity in entities_list:
|
|
2419
|
+
entity_bundle = self.prepare_export(
|
|
2420
|
+
entity=self.generate_export(entity),
|
|
2421
|
+
mode=mode,
|
|
2422
|
+
access_filter=access_filter,
|
|
2423
|
+
)
|
|
2424
|
+
if entity_bundle is not None:
|
|
2425
|
+
entity_bundle_filtered = self.filter_objects(uuids, entity_bundle)
|
|
2426
|
+
for x in entity_bundle_filtered:
|
|
2427
|
+
uuids.append(x["id"])
|
|
2428
|
+
bundle["objects"] = (
|
|
2429
|
+
bundle["objects"] + entity_bundle_filtered
|
|
2430
|
+
) # unsupported operand type(s) for +: 'dict' and 'list'
|
|
2431
|
+
|
|
2350
2432
|
return bundle
|
|
2351
2433
|
|
|
2352
2434
|
def import_bundle(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pycti
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.1.1
|
|
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.
|
|
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,17 +1,17 @@
|
|
|
1
|
-
pycti/__init__.py,sha256=
|
|
1
|
+
pycti/__init__.py,sha256=ef2UbUNokMidzoypuzd5uAVwhY5q-cU73jsqRdYXVEA,5035
|
|
2
2
|
pycti/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
pycti/api/opencti_api_client.py,sha256=
|
|
3
|
+
pycti/api/opencti_api_client.py,sha256=fDeVJjExlsrTNYRf28LYhifz901JkdOZueCdvvko36Y,29575
|
|
4
4
|
pycti/api/opencti_api_connector.py,sha256=fYF0Jy9KIMFNt1RC_A1rpWomVJ-oj5HiSsBem4W0J5U,3549
|
|
5
|
-
pycti/api/opencti_api_playbook.py,sha256=
|
|
5
|
+
pycti/api/opencti_api_playbook.py,sha256=OkqDawpnMYIHz5sD4djlJ_KgORkfvQ7YbJwttxE-ea8,1470
|
|
6
6
|
pycti/api/opencti_api_work.py,sha256=JLfl7oy6Cq9IrYW_kUrqwzN46FoVzyIn1JJQKyK0h_w,7615
|
|
7
7
|
pycti/connector/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
8
|
pycti/connector/opencti_connector.py,sha256=0vrZ8Y8ecbxegAP1YhpX6ybOZahYjjOkcId51D1oBi4,2449
|
|
9
|
-
pycti/connector/opencti_connector_helper.py,sha256=
|
|
9
|
+
pycti/connector/opencti_connector_helper.py,sha256=knJ4fWDTMouVcD_o00UfjHr_jVerrzudl9Aqhu1BigM,60606
|
|
10
10
|
pycti/connector/opencti_metric_handler.py,sha256=4jXHeJflomtHjuQ_YU0b36TG7o26vOWbY_jvU8Ezobs,3725
|
|
11
11
|
pycti/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
12
|
pycti/entities/opencti_attack_pattern.py,sha256=ycAR0cReJ1dd_edQPAL6qBrFvvTx10GJFMTezyK91cg,21471
|
|
13
13
|
pycti/entities/opencti_campaign.py,sha256=YHEN7hdY-E-1uVNyaZHCv9QPLALvOY08ErOzUKcvr6c,17107
|
|
14
|
-
pycti/entities/opencti_case_incident.py,sha256=
|
|
14
|
+
pycti/entities/opencti_case_incident.py,sha256=BEP22Itt7-ZxMBwMNMHO7sbS8XfNSfiy0Y7chuOgWJ4,33699
|
|
15
15
|
pycti/entities/opencti_case_rfi.py,sha256=wboFfQQnE7qjnqnLsw2nxmGAjH1eYjVgayKKAk7a8pI,31876
|
|
16
16
|
pycti/entities/opencti_case_rft.py,sha256=RIefvKibRZ_Qrk4uybEGxnwJ2SAquPXYm4-uJ8RUskg,32760
|
|
17
17
|
pycti/entities/opencti_channel.py,sha256=cA8ltYJpB43rUSKvCPyLUJvtdb_RSJ4tuuUdi_EMF2Q,16608
|
|
@@ -26,7 +26,7 @@ pycti/entities/opencti_identity.py,sha256=YKTQugOSwyxSoMRWSdMWZkagidTbYQzi-Q1aEW
|
|
|
26
26
|
pycti/entities/opencti_incident.py,sha256=KAaqn0mnlyIKJ2whtbK0Eg8AbfQfxKvppS9hyfn_04s,18553
|
|
27
27
|
pycti/entities/opencti_indicator.py,sha256=Kcy1BQQ1-P5OcsFHSzqHHDk0KGM6MhjzPwJiPCRShO0,27581
|
|
28
28
|
pycti/entities/opencti_infrastructure.py,sha256=hpzlSP8yQCSjYyOvX_oynBJq0YMp-Uq7PRhP_L6j9wk,19353
|
|
29
|
-
pycti/entities/opencti_intrusion_set.py,sha256=
|
|
29
|
+
pycti/entities/opencti_intrusion_set.py,sha256=MXubQhDZ6LE69z1Wj8agAZNOrGeKiXU4IZs_9B0Expg,18957
|
|
30
30
|
pycti/entities/opencti_kill_chain_phase.py,sha256=a509rFeIchPRlO5rMHPVxrxfUuTbV4znh6e_NJHC66I,8062
|
|
31
31
|
pycti/entities/opencti_label.py,sha256=6RZJPIa_dXf_YNNU4xXKghfBnpNjhU5YXOaSIcB4YrM,8800
|
|
32
32
|
pycti/entities/opencti_language.py,sha256=eHB7qzf_l2Mno_Wy9kF0QUdcBktWgr4kRHhb9AxT0c0,16176
|
|
@@ -38,14 +38,14 @@ pycti/entities/opencti_narrative.py,sha256=qiuFQub04pvArYf5hHJEgZtneR7p-VQq5Yywi
|
|
|
38
38
|
pycti/entities/opencti_note.py,sha256=tGxOzSJiiHYZNrCpiVnvwY_qiBYURQ0G5wgL9dSWmhE,29938
|
|
39
39
|
pycti/entities/opencti_observed_data.py,sha256=1WFOJLxOh3k-3cWvnyIiEk0hF92tpk5ohvPHeR2zVG4,30550
|
|
40
40
|
pycti/entities/opencti_opinion.py,sha256=SPcY8-0zRJCMle-eDLka-CFPyAqU3CnVVBtfVYhzyJE,21837
|
|
41
|
-
pycti/entities/opencti_report.py,sha256=
|
|
41
|
+
pycti/entities/opencti_report.py,sha256=zKoq3Kpo3afvFsw0QCBOaeVm9J_xRMBOZfJC7ZPRaRg,33580
|
|
42
42
|
pycti/entities/opencti_stix.py,sha256=uMheSg8i1f2Ozx2Mk0iShWzHHjj6MMWDtV5nDjVxKEE,2275
|
|
43
|
-
pycti/entities/opencti_stix_core_object.py,sha256=
|
|
43
|
+
pycti/entities/opencti_stix_core_object.py,sha256=3jABOB_-vm2CSB6LU3ylxpSj_oixRCcfU3T10n2_MFU,49559
|
|
44
44
|
pycti/entities/opencti_stix_core_relationship.py,sha256=cD825areOn2quv06M28YGE7A3bTQ8_Pxx1QW6JyoQBs,42895
|
|
45
|
-
pycti/entities/opencti_stix_cyber_observable.py,sha256=
|
|
46
|
-
pycti/entities/opencti_stix_domain_object.py,sha256=
|
|
45
|
+
pycti/entities/opencti_stix_cyber_observable.py,sha256=EOJuXeSmFcm4oI2rPOqxZ8QZq_ej_CTkYgCTtUkZwsk,106785
|
|
46
|
+
pycti/entities/opencti_stix_domain_object.py,sha256=QI6uBbefNC_PQSwl0O5KpG4cWqa-15mIju8dwREzooU,78504
|
|
47
47
|
pycti/entities/opencti_stix_nested_ref_relationship.py,sha256=2r1i7cUl-WWictlnC_MJrm9sTIt_yJe2uqTpQm-yo6o,12330
|
|
48
|
-
pycti/entities/opencti_stix_object_or_stix_relationship.py,sha256=
|
|
48
|
+
pycti/entities/opencti_stix_object_or_stix_relationship.py,sha256=x0LWqMqaqqIPgQnLgw7Q2qPoXK4fZix8-KsQnmZaIOw,17696
|
|
49
49
|
pycti/entities/opencti_stix_sighting_relationship.py,sha256=AmX1LBS8cW5a_dlik_sx-nBDvUcqb193gs4m3pB9C5U,27584
|
|
50
50
|
pycti/entities/opencti_task.py,sha256=y4Q2vC-eLccX-yna85GnnCFEKWFJAWQcflNbkr9BClo,24668
|
|
51
51
|
pycti/entities/opencti_threat_actor.py,sha256=lRdPhXX_HsNSE5rTwkke_U5T_FAPGD22ow2-YeZdaYc,9950
|
|
@@ -55,14 +55,14 @@ pycti/entities/opencti_tool.py,sha256=RJrBywXI7TfWvgga6M9hH4YBl32dsvro2z42V_EgzG
|
|
|
55
55
|
pycti/entities/opencti_vocabulary.py,sha256=6JfOByggvSxvkfIXk1b60T7fyWOhxZ6YFkGbSeV8F-4,5988
|
|
56
56
|
pycti/entities/opencti_vulnerability.py,sha256=dzJ0fZB2XrkPwT-cANr6atzYOWXF5nk0al86X7o2ZTo,20094
|
|
57
57
|
pycti/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
58
|
-
pycti/utils/constants.py,sha256=
|
|
58
|
+
pycti/utils/constants.py,sha256=Gj0fz94p0ApjCUCUqBQpFTfNslT021HS2w6M8azqXBY,10601
|
|
59
59
|
pycti/utils/opencti_logger.py,sha256=0dvB75V0SuPFGxL539dAQrxTt1N5Acx0A3Ogwl5WMJ8,2199
|
|
60
|
-
pycti/utils/opencti_stix2.py,sha256=
|
|
60
|
+
pycti/utils/opencti_stix2.py,sha256=DB48oDbAKyEwwowHU7_0_p9Y74hXRMaA0IkJ-eschYU,115786
|
|
61
61
|
pycti/utils/opencti_stix2_splitter.py,sha256=Ht9Mp-W3gbwxIKEr7i_5NYpcDr3TA2gYdC4TzOz0G4c,4496
|
|
62
62
|
pycti/utils/opencti_stix2_update.py,sha256=CnMyqkeVA0jgyxEcgqna8sABU4YPMjkEJ228GVurIn4,14658
|
|
63
63
|
pycti/utils/opencti_stix2_utils.py,sha256=4r9qglN3AIN8JH1B9Ts2o20Qn3K203M4c5-lIPzRpZ4,4138
|
|
64
|
-
pycti-6.
|
|
65
|
-
pycti-6.
|
|
66
|
-
pycti-6.
|
|
67
|
-
pycti-6.
|
|
68
|
-
pycti-6.
|
|
64
|
+
pycti-6.1.1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
65
|
+
pycti-6.1.1.dist-info/METADATA,sha256=HiieXOK5ea_MGzOWNessuVTMkCCMbk9H4mUz9YDfED4,5313
|
|
66
|
+
pycti-6.1.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
67
|
+
pycti-6.1.1.dist-info/top_level.txt,sha256=cqEpxitAhHP4VgSA6xmrak6Yk9MeBkwoMTB6k7d2ZnE,6
|
|
68
|
+
pycti-6.1.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|