pycti 6.0.10__py3-none-any.whl → 6.1.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/api/opencti_api_client.py +15 -5
- pycti/api/opencti_api_playbook.py +3 -2
- pycti/connector/opencti_connector_helper.py +6 -4
- pycti/entities/opencti_case_incident.py +1 -1
- pycti/entities/opencti_intrusion_set.py +25 -3
- 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 +25 -7
- pycti/entities/opencti_stix_object_or_stix_relationship.py +63 -4
- pycti/utils/constants.py +0 -1
- pycti/utils/opencti_stix2.py +253 -68
- {pycti-6.0.10.dist-info → pycti-6.1.0.dist-info}/METADATA +2 -2
- {pycti-6.0.10.dist-info → pycti-6.1.0.dist-info}/RECORD +18 -18
- {pycti-6.0.10.dist-info → pycti-6.1.0.dist-info}/LICENSE +0 -0
- {pycti-6.0.10.dist-info → pycti-6.1.0.dist-info}/WHEEL +0 -0
- {pycti-6.0.10.dist-info → pycti-6.1.0.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,
|
|
@@ -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,
|
|
@@ -286,9 +286,31 @@ class IntrusionSet:
|
|
|
286
286
|
"orderMode": order_mode,
|
|
287
287
|
},
|
|
288
288
|
)
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
289
|
+
if get_all:
|
|
290
|
+
final_data = []
|
|
291
|
+
data = self.opencti.process_multiple(result["data"]["intrusionSets"])
|
|
292
|
+
final_data = final_data + data
|
|
293
|
+
while result["data"]["intrusionSets"]["pageInfo"]["hasNextPage"]:
|
|
294
|
+
after = result["data"]["intrusionSets"]["pageInfo"]["endCursor"]
|
|
295
|
+
self.opencti.app_logger.info("Listing Intrusion-Sets", {"after": after})
|
|
296
|
+
result = self.opencti.query(
|
|
297
|
+
query,
|
|
298
|
+
{
|
|
299
|
+
"filters": filters,
|
|
300
|
+
"search": search,
|
|
301
|
+
"first": first,
|
|
302
|
+
"after": after,
|
|
303
|
+
"orderBy": order_by,
|
|
304
|
+
"orderMode": order_mode,
|
|
305
|
+
},
|
|
306
|
+
)
|
|
307
|
+
data = self.opencti.process_multiple(result["data"]["intrusionSets"])
|
|
308
|
+
final_data = final_data + data
|
|
309
|
+
return final_data
|
|
310
|
+
else:
|
|
311
|
+
return self.opencti.process_multiple(
|
|
312
|
+
result["data"]["intrusionSets"], with_pagination
|
|
313
|
+
)
|
|
292
314
|
|
|
293
315
|
"""
|
|
294
316
|
Read a Intrusion-Set object
|
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,24 @@ class StixDomainObject:
|
|
|
1342
1349
|
"entity_id": entity_id,
|
|
1343
1350
|
"entity_type": entity_type,
|
|
1344
1351
|
"file": file,
|
|
1352
|
+
"file_markings": file_markings,
|
|
1345
1353
|
"listFilters": list_filters,
|
|
1346
1354
|
},
|
|
1347
1355
|
)
|
|
1348
1356
|
|
|
1349
|
-
def push_entity_export(
|
|
1357
|
+
def push_entity_export(
|
|
1358
|
+
self, entity_id, file_name, data, file_markings, mime_type=None
|
|
1359
|
+
):
|
|
1350
1360
|
query = """
|
|
1351
|
-
mutation StixDomainObjectEdit(
|
|
1361
|
+
mutation StixDomainObjectEdit(
|
|
1362
|
+
$id: ID!, $file: Upload!,
|
|
1363
|
+
$file_markings: [String]!
|
|
1364
|
+
) {
|
|
1352
1365
|
stixDomainObjectEdit(id: $id) {
|
|
1353
|
-
exportPush(
|
|
1366
|
+
exportPush(
|
|
1367
|
+
file: $file,
|
|
1368
|
+
file_markings: $file_markings
|
|
1369
|
+
)
|
|
1354
1370
|
}
|
|
1355
1371
|
}
|
|
1356
1372
|
"""
|
|
@@ -1358,7 +1374,9 @@ class StixDomainObject:
|
|
|
1358
1374
|
file = self.file(file_name, data)
|
|
1359
1375
|
else:
|
|
1360
1376
|
file = self.file(file_name, data, mime_type)
|
|
1361
|
-
self.opencti.query(
|
|
1377
|
+
self.opencti.query(
|
|
1378
|
+
query, {"id": entity_id, "file": file, "file_markings": file_markings}
|
|
1379
|
+
)
|
|
1362
1380
|
|
|
1363
1381
|
"""
|
|
1364
1382
|
Update the Identity author of a Stix-Domain-Object object (created_by)
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
|
|
1
4
|
class StixObjectOrStixRelationship:
|
|
2
5
|
def __init__(self, opencti):
|
|
3
6
|
self.opencti = opencti
|
|
@@ -329,11 +332,15 @@ class StixObjectOrStixRelationship:
|
|
|
329
332
|
}
|
|
330
333
|
... on Case {
|
|
331
334
|
name
|
|
332
|
-
}
|
|
335
|
+
}
|
|
333
336
|
... on StixCyberObservable {
|
|
334
337
|
observable_value
|
|
335
338
|
}
|
|
336
339
|
... on StixCoreRelationship {
|
|
340
|
+
id
|
|
341
|
+
standard_id
|
|
342
|
+
entity_type
|
|
343
|
+
parent_types
|
|
337
344
|
createdBy {
|
|
338
345
|
... on Identity {
|
|
339
346
|
id
|
|
@@ -396,6 +403,10 @@ class StixObjectOrStixRelationship:
|
|
|
396
403
|
stop_time
|
|
397
404
|
}
|
|
398
405
|
... on StixSightingRelationship {
|
|
406
|
+
id
|
|
407
|
+
standard_id
|
|
408
|
+
entity_type
|
|
409
|
+
parent_types
|
|
399
410
|
createdBy {
|
|
400
411
|
... on Identity {
|
|
401
412
|
id
|
|
@@ -476,9 +487,9 @@ class StixObjectOrStixRelationship:
|
|
|
476
487
|
)
|
|
477
488
|
query = (
|
|
478
489
|
"""
|
|
479
|
-
|
|
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,51 @@ class StixObjectOrStixRelationship:
|
|
|
496
507
|
else:
|
|
497
508
|
self.opencti.app_logger.error("Missing parameters: id")
|
|
498
509
|
return None
|
|
510
|
+
|
|
511
|
+
def list(self, **kwargs):
|
|
512
|
+
filters = kwargs.get("filters", None)
|
|
513
|
+
search = kwargs.get("search", None)
|
|
514
|
+
first = kwargs.get("first", 100)
|
|
515
|
+
after = kwargs.get("after", None)
|
|
516
|
+
with_pagination = kwargs.get("with_pagination", False)
|
|
517
|
+
custom_attributes = kwargs.get("customAttributes", None)
|
|
518
|
+
|
|
519
|
+
self.opencti.app_logger.info(
|
|
520
|
+
"Listing StixObjectOrStixRelationships with filters",
|
|
521
|
+
{"filters": json.dumps(filters)},
|
|
522
|
+
)
|
|
523
|
+
query = (
|
|
524
|
+
"""
|
|
525
|
+
query StixObjectOrStixRelationships($filters: FilterGroup, $search: String, $first: Int, $after: ID) {
|
|
526
|
+
stixObjectOrStixRelationships(filters: $filters, search: $search, first: $first, after: $after) {
|
|
527
|
+
edges {
|
|
528
|
+
node {
|
|
529
|
+
"""
|
|
530
|
+
+ (custom_attributes if custom_attributes is not None else self.properties)
|
|
531
|
+
+ """
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
pageInfo {
|
|
535
|
+
startCursor
|
|
536
|
+
endCursor
|
|
537
|
+
hasNextPage
|
|
538
|
+
hasPreviousPage
|
|
539
|
+
globalCount
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
"""
|
|
544
|
+
)
|
|
545
|
+
result = self.opencti.query(
|
|
546
|
+
query,
|
|
547
|
+
{
|
|
548
|
+
"filters": filters,
|
|
549
|
+
"search": search,
|
|
550
|
+
"first": first,
|
|
551
|
+
"after": after,
|
|
552
|
+
},
|
|
553
|
+
)
|
|
554
|
+
|
|
555
|
+
return self.opencti.process_multiple(
|
|
556
|
+
result["data"]["stixObjectOrStixRelationships"], with_pagination
|
|
557
|
+
)
|
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
|
@@ -680,6 +680,9 @@ class OpenCTIStix2:
|
|
|
680
680
|
|
|
681
681
|
author = self.resolve_author(title)
|
|
682
682
|
report = self.opencti.report.create(
|
|
683
|
+
id=self.opencti.report.generate_fixed_fake_id(
|
|
684
|
+
title, published
|
|
685
|
+
),
|
|
683
686
|
name=title,
|
|
684
687
|
createdBy=author["id"] if author is not None else None,
|
|
685
688
|
objectMarking=[object_marking_ref_result["id"]],
|
|
@@ -788,6 +791,48 @@ class OpenCTIStix2:
|
|
|
788
791
|
"reports": reports,
|
|
789
792
|
}
|
|
790
793
|
|
|
794
|
+
def get_listers(self):
|
|
795
|
+
return {
|
|
796
|
+
"Stix-Core-Object": self.opencti.stix_core_object.list,
|
|
797
|
+
"Stix-Domain-Object": self.opencti.stix_domain_object.list,
|
|
798
|
+
"Administrative-Area": self.opencti.location.list,
|
|
799
|
+
"Attack-Pattern": self.opencti.attack_pattern.list,
|
|
800
|
+
"Campaign": self.opencti.campaign.list,
|
|
801
|
+
"Channel": self.opencti.channel.list,
|
|
802
|
+
"Event": self.opencti.event.list,
|
|
803
|
+
"Note": self.opencti.note.list,
|
|
804
|
+
"Observed-Data": self.opencti.observed_data.list,
|
|
805
|
+
"Opinion": self.opencti.opinion.list,
|
|
806
|
+
"Report": self.opencti.report.list,
|
|
807
|
+
"Grouping": self.opencti.grouping.list,
|
|
808
|
+
"Case-Incident": self.opencti.case_incident.list,
|
|
809
|
+
"Feedback": self.opencti.feedback.list,
|
|
810
|
+
"Case-Rfi": self.opencti.case_rfi.list,
|
|
811
|
+
"Case-Rft": self.opencti.case_rft.list,
|
|
812
|
+
"Task": self.opencti.task.list,
|
|
813
|
+
"Course-Of-Action": self.opencti.course_of_action.list,
|
|
814
|
+
"Data-Component": self.opencti.data_component.list,
|
|
815
|
+
"Data-Source": self.opencti.data_source.list,
|
|
816
|
+
"Identity": self.opencti.identity.list,
|
|
817
|
+
"Indicator": self.opencti.indicator.list,
|
|
818
|
+
"Infrastructure": self.opencti.infrastructure.list,
|
|
819
|
+
"Intrusion-Set": self.opencti.intrusion_set.list,
|
|
820
|
+
"Location": self.opencti.location.list,
|
|
821
|
+
"Language": self.opencti.language.list,
|
|
822
|
+
"Malware": self.opencti.malware.list,
|
|
823
|
+
"Malware-Analysis": self.opencti.malware_analysis.list,
|
|
824
|
+
"Threat-Actor": self.opencti.threat_actor_group.list,
|
|
825
|
+
"Threat-Actor-Group": self.opencti.threat_actor_group.list,
|
|
826
|
+
"Threat-Actor-Individual": self.opencti.threat_actor_individual.list,
|
|
827
|
+
"Tool": self.opencti.tool.list,
|
|
828
|
+
"Narrative": self.opencti.narrative.list,
|
|
829
|
+
"Vulnerability": self.opencti.vulnerability.list,
|
|
830
|
+
"Incident": self.opencti.incident.list,
|
|
831
|
+
"Stix-Cyber-Observable": self.opencti.stix_cyber_observable.list,
|
|
832
|
+
"stix-sighting-relationship": self.opencti.stix_sighting_relationship.list,
|
|
833
|
+
"stix-core-relationship": self.opencti.stix_core_relationship.list,
|
|
834
|
+
}
|
|
835
|
+
|
|
791
836
|
def get_readers(self):
|
|
792
837
|
return {
|
|
793
838
|
"Attack-Pattern": self.opencti.attack_pattern.read,
|
|
@@ -1512,7 +1557,7 @@ class OpenCTIStix2:
|
|
|
1512
1557
|
if "tasks" in entity:
|
|
1513
1558
|
del entity["tasks"]
|
|
1514
1559
|
|
|
1515
|
-
if "status" in entity:
|
|
1560
|
+
if "status" in entity and entity["status"] is not None:
|
|
1516
1561
|
entity["x_opencti_workflow_id"] = entity["status"].get("id")
|
|
1517
1562
|
if "status" in entity:
|
|
1518
1563
|
del entity["status"]
|
|
@@ -1614,28 +1659,90 @@ class OpenCTIStix2:
|
|
|
1614
1659
|
|
|
1615
1660
|
return {k: v for k, v in entity.items() if self.opencti.not_empty(v)}
|
|
1616
1661
|
|
|
1662
|
+
def prepare_filters_export(self, id: str, access_filter: Dict = None) -> Dict:
|
|
1663
|
+
if access_filter is not None:
|
|
1664
|
+
return {
|
|
1665
|
+
"mode": "and",
|
|
1666
|
+
"filterGroups": [
|
|
1667
|
+
{
|
|
1668
|
+
"mode": "or",
|
|
1669
|
+
"filters": [
|
|
1670
|
+
{
|
|
1671
|
+
"key": "id",
|
|
1672
|
+
"values": [id],
|
|
1673
|
+
}
|
|
1674
|
+
],
|
|
1675
|
+
"filterGroups": [],
|
|
1676
|
+
},
|
|
1677
|
+
access_filter,
|
|
1678
|
+
],
|
|
1679
|
+
"filters": [],
|
|
1680
|
+
}
|
|
1681
|
+
else:
|
|
1682
|
+
return {
|
|
1683
|
+
"mode": "and",
|
|
1684
|
+
"filterGroups": [
|
|
1685
|
+
{
|
|
1686
|
+
"mode": "or",
|
|
1687
|
+
"filters": [
|
|
1688
|
+
{
|
|
1689
|
+
"key": "id",
|
|
1690
|
+
"values": [id],
|
|
1691
|
+
}
|
|
1692
|
+
],
|
|
1693
|
+
"filterGroups": [],
|
|
1694
|
+
},
|
|
1695
|
+
],
|
|
1696
|
+
"filters": [],
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1617
1699
|
def prepare_export(
|
|
1618
1700
|
self,
|
|
1619
1701
|
entity: Dict,
|
|
1620
1702
|
mode: str = "simple",
|
|
1621
1703
|
max_marking_definition_entity: Dict = None,
|
|
1704
|
+
main_filter: Dict = None,
|
|
1705
|
+
access_filter: Dict = None,
|
|
1622
1706
|
no_custom_attributes: bool = False,
|
|
1623
1707
|
) -> List:
|
|
1624
|
-
if (
|
|
1625
|
-
self.check_max_marking_definition(
|
|
1626
|
-
max_marking_definition_entity,
|
|
1627
|
-
entity["objectMarking"] if "objectMarking" in entity else [],
|
|
1628
|
-
)
|
|
1629
|
-
is False
|
|
1630
|
-
):
|
|
1631
|
-
self.opencti.app_logger.info(
|
|
1632
|
-
"Marking definitions are less than max definition, not exporting.",
|
|
1633
|
-
{"type": entity["type"]},
|
|
1634
|
-
)
|
|
1635
|
-
return []
|
|
1636
1708
|
result = []
|
|
1637
1709
|
objects_to_get = []
|
|
1638
1710
|
relations_to_get = []
|
|
1711
|
+
|
|
1712
|
+
# Container
|
|
1713
|
+
if "objects" in entity and len(entity["objects"]) > 0:
|
|
1714
|
+
del entity["objects"]
|
|
1715
|
+
regarding_of_filter = {
|
|
1716
|
+
"mode": "and",
|
|
1717
|
+
"filterGroups": [],
|
|
1718
|
+
"filters": [
|
|
1719
|
+
{
|
|
1720
|
+
"key": "regardingOf",
|
|
1721
|
+
"mode": "and",
|
|
1722
|
+
"operator": "eq",
|
|
1723
|
+
"values": [
|
|
1724
|
+
{"key": "id", "values": [entity["x_opencti_id"]]},
|
|
1725
|
+
{"key": "relationship_type", "values": ["object"]},
|
|
1726
|
+
],
|
|
1727
|
+
}
|
|
1728
|
+
],
|
|
1729
|
+
}
|
|
1730
|
+
filter_groups = []
|
|
1731
|
+
if regarding_of_filter is not None:
|
|
1732
|
+
filter_groups.append(regarding_of_filter)
|
|
1733
|
+
if access_filter is not None:
|
|
1734
|
+
filter_groups.append(access_filter)
|
|
1735
|
+
export_query_filter = {
|
|
1736
|
+
"mode": "and",
|
|
1737
|
+
"filterGroups": filter_groups,
|
|
1738
|
+
"filters": [],
|
|
1739
|
+
}
|
|
1740
|
+
entity["objects"] = (
|
|
1741
|
+
self.opencti.opencti_stix_object_or_stix_relationship.list(
|
|
1742
|
+
filters=export_query_filter
|
|
1743
|
+
)
|
|
1744
|
+
)
|
|
1745
|
+
|
|
1639
1746
|
# CreatedByRef
|
|
1640
1747
|
if (
|
|
1641
1748
|
not no_custom_attributes
|
|
@@ -1747,7 +1854,7 @@ class OpenCTIStix2:
|
|
|
1747
1854
|
and len(entity["objects"]) > 0
|
|
1748
1855
|
):
|
|
1749
1856
|
entity["object_refs"] = []
|
|
1750
|
-
objects_to_get = entity["objects"]
|
|
1857
|
+
objects_to_get = entity["objects"] # To do differently
|
|
1751
1858
|
for entity_object in entity["objects"]:
|
|
1752
1859
|
if (
|
|
1753
1860
|
entity["type"] == "report"
|
|
@@ -1819,22 +1926,62 @@ class OpenCTIStix2:
|
|
|
1819
1926
|
entity["type"] = "sighting"
|
|
1820
1927
|
entity["count"] = entity["attribute_count"]
|
|
1821
1928
|
del entity["attribute_count"]
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1929
|
+
from_to_check = entity["from"]["id"]
|
|
1930
|
+
relationships_from_filter = self.prepare_filters_export(
|
|
1931
|
+
id=from_to_check, access_filter=access_filter
|
|
1932
|
+
)
|
|
1933
|
+
x = self.opencti.opencti_stix_object_or_stix_relationship.list(
|
|
1934
|
+
filters=relationships_from_filter
|
|
1935
|
+
)
|
|
1936
|
+
if len(x) > 0:
|
|
1937
|
+
entity["sighting_of_ref"] = entity["from"]["id"]
|
|
1938
|
+
# handle from and to separately like Stix Core Relationship and call 2 requests
|
|
1939
|
+
objects_to_get.append(
|
|
1940
|
+
entity["from"]
|
|
1941
|
+
) # what happen with unauthorized objects ?
|
|
1942
|
+
|
|
1943
|
+
to_to_check = [entity["to"]["id"]]
|
|
1944
|
+
relationships_to_filter = self.prepare_filters_export(
|
|
1945
|
+
id=to_to_check, access_filter=access_filter
|
|
1946
|
+
)
|
|
1947
|
+
y = self.opencti.opencti_stix_object_or_stix_relationship.list(
|
|
1948
|
+
filters=relationships_to_filter
|
|
1949
|
+
)
|
|
1950
|
+
if len(y) > 0:
|
|
1951
|
+
entity["where_sighted_refs"] = [entity["to"]["id"]]
|
|
1952
|
+
objects_to_get.append(entity["to"])
|
|
1953
|
+
|
|
1826
1954
|
del entity["from"]
|
|
1827
1955
|
del entity["to"]
|
|
1828
1956
|
# Stix Core Relationship
|
|
1829
1957
|
if "from" in entity or "to" in entity:
|
|
1830
1958
|
entity["type"] = "relationship"
|
|
1831
1959
|
if "from" in entity:
|
|
1832
|
-
|
|
1833
|
-
|
|
1960
|
+
from_to_check = entity["from"]["id"]
|
|
1961
|
+
relationships_from_filter = self.prepare_filters_export(
|
|
1962
|
+
id=from_to_check, access_filter=access_filter
|
|
1963
|
+
)
|
|
1964
|
+
x = self.opencti.opencti_stix_object_or_stix_relationship.list(
|
|
1965
|
+
filters=relationships_from_filter
|
|
1966
|
+
)
|
|
1967
|
+
if len(x) > 0:
|
|
1968
|
+
entity["source_ref"] = entity["from"]["id"]
|
|
1969
|
+
# handle from and to separately like Stix Core Relationship and call 2 requests
|
|
1970
|
+
objects_to_get.append(
|
|
1971
|
+
entity["from"]
|
|
1972
|
+
) # what happen with unauthorized objects ?
|
|
1834
1973
|
del entity["from"]
|
|
1835
1974
|
if "to" in entity:
|
|
1836
|
-
|
|
1837
|
-
|
|
1975
|
+
to_to_check = [entity["to"]["id"]]
|
|
1976
|
+
relationships_to_filter = self.prepare_filters_export(
|
|
1977
|
+
id=to_to_check, access_filter=access_filter
|
|
1978
|
+
)
|
|
1979
|
+
y = self.opencti.opencti_stix_object_or_stix_relationship.list(
|
|
1980
|
+
filters=relationships_to_filter
|
|
1981
|
+
)
|
|
1982
|
+
if len(y) > 0:
|
|
1983
|
+
entity["target_ref"] = entity["to"]["id"]
|
|
1984
|
+
objects_to_get.append(entity["to"])
|
|
1838
1985
|
del entity["to"]
|
|
1839
1986
|
# Stix Domain Object
|
|
1840
1987
|
if "attribute_abstract" in entity:
|
|
@@ -1877,7 +2024,7 @@ class OpenCTIStix2:
|
|
|
1877
2024
|
|
|
1878
2025
|
# StixRefRelationship
|
|
1879
2026
|
stix_nested_ref_relationships = self.opencti.stix_nested_ref_relationship.list(
|
|
1880
|
-
fromId=entity["x_opencti_id"]
|
|
2027
|
+
fromId=entity["x_opencti_id"], filters=access_filter
|
|
1881
2028
|
)
|
|
1882
2029
|
for stix_nested_ref_relationship in stix_nested_ref_relationships:
|
|
1883
2030
|
if "standard_id" in stix_nested_ref_relationship["to"]:
|
|
@@ -1921,8 +2068,8 @@ class OpenCTIStix2:
|
|
|
1921
2068
|
return result
|
|
1922
2069
|
elif mode == "full":
|
|
1923
2070
|
uuids = [entity["id"]]
|
|
1924
|
-
for
|
|
1925
|
-
uuids.append(
|
|
2071
|
+
for y in result:
|
|
2072
|
+
uuids.append(y["id"])
|
|
1926
2073
|
# Get extra refs
|
|
1927
2074
|
for key in entity.keys():
|
|
1928
2075
|
if key.endswith("_ref"):
|
|
@@ -1964,7 +2111,7 @@ class OpenCTIStix2:
|
|
|
1964
2111
|
)
|
|
1965
2112
|
# Get extra relations (from AND to)
|
|
1966
2113
|
stix_core_relationships = self.opencti.stix_core_relationship.list(
|
|
1967
|
-
fromOrToId=entity["x_opencti_id"], getAll=True
|
|
2114
|
+
fromOrToId=entity["x_opencti_id"], getAll=True, filters=access_filter
|
|
1968
2115
|
)
|
|
1969
2116
|
for stix_core_relationship in stix_core_relationships:
|
|
1970
2117
|
if self.check_max_marking_definition(
|
|
@@ -1980,10 +2127,14 @@ class OpenCTIStix2:
|
|
|
1980
2127
|
if stix_core_relationship["to"]["id"] != entity["x_opencti_id"]
|
|
1981
2128
|
else stix_core_relationship["from"]
|
|
1982
2129
|
)
|
|
1983
|
-
relation_object_data =
|
|
1984
|
-
self.
|
|
1985
|
-
|
|
1986
|
-
|
|
2130
|
+
relation_object_data = (
|
|
2131
|
+
self.prepare_export( # ICI -> remove max marking ?
|
|
2132
|
+
self.generate_export(stix_core_relationship),
|
|
2133
|
+
"simple",
|
|
2134
|
+
max_marking_definition_entity,
|
|
2135
|
+
main_filter,
|
|
2136
|
+
access_filter,
|
|
2137
|
+
)
|
|
1987
2138
|
)
|
|
1988
2139
|
relation_object_bundle = self.filter_objects(
|
|
1989
2140
|
uuids, relation_object_data
|
|
@@ -2001,8 +2152,7 @@ class OpenCTIStix2:
|
|
|
2001
2152
|
)
|
|
2002
2153
|
# Get sighting
|
|
2003
2154
|
stix_sighting_relationships = self.opencti.stix_sighting_relationship.list(
|
|
2004
|
-
fromOrToId=entity["x_opencti_id"],
|
|
2005
|
-
getAll=True,
|
|
2155
|
+
fromOrToId=entity["x_opencti_id"], getAll=True, filters=access_filter
|
|
2006
2156
|
)
|
|
2007
2157
|
for stix_sighting_relationship in stix_sighting_relationships:
|
|
2008
2158
|
if self.check_max_marking_definition(
|
|
@@ -2019,10 +2169,14 @@ class OpenCTIStix2:
|
|
|
2019
2169
|
!= entity["x_opencti_id"]
|
|
2020
2170
|
else stix_sighting_relationship["from"]
|
|
2021
2171
|
)
|
|
2022
|
-
relation_object_data =
|
|
2023
|
-
self.
|
|
2024
|
-
|
|
2025
|
-
|
|
2172
|
+
relation_object_data = (
|
|
2173
|
+
self.prepare_export( # ICI -> remove max marking ?
|
|
2174
|
+
self.generate_export(stix_sighting_relationship),
|
|
2175
|
+
"simple",
|
|
2176
|
+
max_marking_definition_entity,
|
|
2177
|
+
main_filter,
|
|
2178
|
+
access_filter,
|
|
2179
|
+
)
|
|
2026
2180
|
)
|
|
2027
2181
|
relation_object_bundle = self.filter_objects(
|
|
2028
2182
|
uuids, relation_object_data
|
|
@@ -2065,12 +2219,16 @@ class OpenCTIStix2:
|
|
|
2065
2219
|
{"type": entity_object["entity_type"]}
|
|
2066
2220
|
),
|
|
2067
2221
|
)
|
|
2068
|
-
entity_object_data = do_read(
|
|
2222
|
+
entity_object_data = do_read(
|
|
2223
|
+
id=entity_object["id"], filters=access_filter
|
|
2224
|
+
)
|
|
2069
2225
|
if entity_object_data is not None:
|
|
2070
2226
|
stix_entity_object = self.prepare_export(
|
|
2071
2227
|
self.generate_export(entity_object_data),
|
|
2072
2228
|
"simple",
|
|
2073
2229
|
max_marking_definition_entity,
|
|
2230
|
+
main_filter,
|
|
2231
|
+
access_filter,
|
|
2074
2232
|
)
|
|
2075
2233
|
# Add to result
|
|
2076
2234
|
entity_object_bundle = self.filter_objects(
|
|
@@ -2078,9 +2236,18 @@ class OpenCTIStix2:
|
|
|
2078
2236
|
)
|
|
2079
2237
|
uuids = uuids + [x["id"] for x in entity_object_bundle]
|
|
2080
2238
|
result = result + entity_object_bundle
|
|
2081
|
-
for
|
|
2239
|
+
for (
|
|
2240
|
+
relation_object
|
|
2241
|
+
) in relations_to_get: # never appended after initialization
|
|
2242
|
+
|
|
2243
|
+
def find_relation_object_data(current_relation_object):
|
|
2244
|
+
return current_relation_object.id == relation_object["id"]
|
|
2245
|
+
|
|
2082
2246
|
relation_object_data = self.prepare_export(
|
|
2083
|
-
|
|
2247
|
+
filter(
|
|
2248
|
+
find_relation_object_data,
|
|
2249
|
+
self.opencti.stix_core_relationship.list(filters=access_filter),
|
|
2250
|
+
)
|
|
2084
2251
|
)
|
|
2085
2252
|
relation_object_bundle = self.filter_objects(
|
|
2086
2253
|
uuids, relation_object_data
|
|
@@ -2150,15 +2317,12 @@ class OpenCTIStix2:
|
|
|
2150
2317
|
entity_type: str,
|
|
2151
2318
|
entity_id: str,
|
|
2152
2319
|
mode: str = "simple",
|
|
2320
|
+
main_filter: Dict = None,
|
|
2321
|
+
access_filter: Dict = None,
|
|
2153
2322
|
max_marking_definition: Dict = None,
|
|
2154
2323
|
no_custom_attributes: bool = False,
|
|
2155
2324
|
only_entity: bool = False,
|
|
2156
2325
|
) -> Dict:
|
|
2157
|
-
max_marking_definition_entity = (
|
|
2158
|
-
self.opencti.marking_definition.read(id=max_marking_definition)
|
|
2159
|
-
if max_marking_definition is not None
|
|
2160
|
-
else None
|
|
2161
|
-
)
|
|
2162
2326
|
bundle = {
|
|
2163
2327
|
"type": "bundle",
|
|
2164
2328
|
"id": "bundle--" + str(uuid.uuid4()),
|
|
@@ -2174,14 +2338,12 @@ class OpenCTIStix2:
|
|
|
2174
2338
|
if LocationTypes.has_value(entity_type):
|
|
2175
2339
|
entity_type = "Location"
|
|
2176
2340
|
|
|
2177
|
-
#
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
entity_type = "Stix-Cyber-Observable"
|
|
2181
|
-
do_read = reader.get(
|
|
2341
|
+
# Lister
|
|
2342
|
+
listers = self.get_listers()
|
|
2343
|
+
do_list = listers.get(
|
|
2182
2344
|
entity_type, lambda **kwargs: self.unknown_type({"type": entity_type})
|
|
2183
2345
|
)
|
|
2184
|
-
entity =
|
|
2346
|
+
entity = do_list(filters=main_filter)[0]
|
|
2185
2347
|
if entity is None:
|
|
2186
2348
|
self.opencti.app_logger.error(
|
|
2187
2349
|
"Cannot export entity (not found)", {"id": entity_id}
|
|
@@ -2191,7 +2353,9 @@ class OpenCTIStix2:
|
|
|
2191
2353
|
stix_objects = self.prepare_export(
|
|
2192
2354
|
self.generate_export(entity, no_custom_attributes),
|
|
2193
2355
|
mode,
|
|
2194
|
-
|
|
2356
|
+
None,
|
|
2357
|
+
main_filter,
|
|
2358
|
+
access_filter,
|
|
2195
2359
|
no_custom_attributes,
|
|
2196
2360
|
)
|
|
2197
2361
|
if stix_objects is not None:
|
|
@@ -2206,7 +2370,7 @@ class OpenCTIStix2:
|
|
|
2206
2370
|
self,
|
|
2207
2371
|
entity_type: str,
|
|
2208
2372
|
search: Dict = None,
|
|
2209
|
-
filters:
|
|
2373
|
+
filters: Dict = None,
|
|
2210
2374
|
orderBy: str = None,
|
|
2211
2375
|
orderMode: str = None,
|
|
2212
2376
|
getAll: bool = True,
|
|
@@ -2279,26 +2443,32 @@ class OpenCTIStix2:
|
|
|
2279
2443
|
self,
|
|
2280
2444
|
entity_type: str,
|
|
2281
2445
|
search: Dict = None,
|
|
2282
|
-
filters:
|
|
2446
|
+
filters: Dict = None,
|
|
2283
2447
|
order_by: str = None,
|
|
2284
2448
|
order_mode: str = None,
|
|
2285
2449
|
mode: str = "simple",
|
|
2286
|
-
|
|
2450
|
+
main_filter: Dict = None,
|
|
2451
|
+
access_filter: Dict = None,
|
|
2287
2452
|
) -> Dict:
|
|
2288
|
-
max_marking_definition_entity = (
|
|
2289
|
-
self.opencti.marking_definition.read(id=max_marking_definition)
|
|
2290
|
-
if max_marking_definition is not None
|
|
2291
|
-
else None
|
|
2292
|
-
)
|
|
2293
2453
|
bundle = {
|
|
2294
2454
|
"type": "bundle",
|
|
2295
2455
|
"id": "bundle--" + str(uuid.uuid4()),
|
|
2296
2456
|
"objects": [],
|
|
2297
2457
|
}
|
|
2458
|
+
filterGroups = []
|
|
2459
|
+
if filters is not None:
|
|
2460
|
+
filterGroups.append(filters)
|
|
2461
|
+
if access_filter is not None:
|
|
2462
|
+
filterGroups.append(access_filter)
|
|
2463
|
+
export_query_filter = {
|
|
2464
|
+
"mode": "and",
|
|
2465
|
+
"filterGroups": filterGroups,
|
|
2466
|
+
"filters": [],
|
|
2467
|
+
}
|
|
2298
2468
|
entities_list = self.export_entities_list(
|
|
2299
2469
|
entity_type=entity_type,
|
|
2300
2470
|
search=search,
|
|
2301
|
-
filters=
|
|
2471
|
+
filters=export_query_filter,
|
|
2302
2472
|
orderBy=order_by,
|
|
2303
2473
|
orderMode=order_mode,
|
|
2304
2474
|
getAll=True,
|
|
@@ -2309,7 +2479,9 @@ class OpenCTIStix2:
|
|
|
2309
2479
|
entity_bundle = self.prepare_export(
|
|
2310
2480
|
self.generate_export(entity),
|
|
2311
2481
|
mode,
|
|
2312
|
-
|
|
2482
|
+
None,
|
|
2483
|
+
main_filter,
|
|
2484
|
+
access_filter,
|
|
2313
2485
|
)
|
|
2314
2486
|
if entity_bundle is not None:
|
|
2315
2487
|
entity_bundle_filtered = self.filter_objects(uuids, entity_bundle)
|
|
@@ -2322,31 +2494,44 @@ class OpenCTIStix2:
|
|
|
2322
2494
|
self,
|
|
2323
2495
|
entities_list: [str],
|
|
2324
2496
|
mode: str = "simple",
|
|
2325
|
-
|
|
2497
|
+
main_filter: Dict = None,
|
|
2498
|
+
access_filter: Dict = None,
|
|
2326
2499
|
) -> Dict:
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2500
|
+
|
|
2501
|
+
entity_data_sdo = self.opencti.stix_domain_object.list(filters=main_filter)
|
|
2502
|
+
entity_data_sco = self.opencti.stix_cyber_observable.list(filters=main_filter)
|
|
2503
|
+
entity_data_scr = self.opencti.stix_core_relationship.list(filters=main_filter)
|
|
2504
|
+
entity_data_ssr = self.opencti.stix_sighting_relationship.list(
|
|
2505
|
+
filters=main_filter
|
|
2506
|
+
)
|
|
2507
|
+
|
|
2508
|
+
entities_list = (
|
|
2509
|
+
entity_data_sdo + entity_data_sco + entity_data_scr + entity_data_ssr
|
|
2331
2510
|
)
|
|
2332
2511
|
bundle = {
|
|
2333
2512
|
"type": "bundle",
|
|
2334
2513
|
"id": "bundle--" + str(uuid.uuid4()),
|
|
2335
2514
|
"objects": [],
|
|
2336
2515
|
}
|
|
2516
|
+
|
|
2337
2517
|
if entities_list is not None:
|
|
2338
2518
|
uuids = []
|
|
2339
2519
|
for entity in entities_list:
|
|
2340
2520
|
entity_bundle = self.prepare_export(
|
|
2341
2521
|
self.generate_export(entity),
|
|
2342
2522
|
mode,
|
|
2343
|
-
|
|
2523
|
+
None,
|
|
2524
|
+
main_filter,
|
|
2525
|
+
access_filter,
|
|
2344
2526
|
)
|
|
2345
2527
|
if entity_bundle is not None:
|
|
2346
2528
|
entity_bundle_filtered = self.filter_objects(uuids, entity_bundle)
|
|
2347
2529
|
for x in entity_bundle_filtered:
|
|
2348
2530
|
uuids.append(x["id"])
|
|
2349
|
-
bundle["objects"] =
|
|
2531
|
+
bundle["objects"] = (
|
|
2532
|
+
bundle["objects"] + entity_bundle_filtered
|
|
2533
|
+
) # unsupported operand type(s) for +: 'dict' and 'list'
|
|
2534
|
+
|
|
2350
2535
|
return bundle
|
|
2351
2536
|
|
|
2352
2537
|
def import_bundle(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pycti
|
|
3
|
-
Version: 6.0
|
|
3
|
+
Version: 6.1.0
|
|
4
4
|
Summary: Python API client for OpenCTI.
|
|
5
5
|
Home-page: https://github.com/OpenCTI-Platform/client-python
|
|
6
6
|
Author: Filigran
|
|
@@ -42,7 +42,7 @@ Requires-Dist: pre-commit ~=3.7.0 ; extra == 'dev'
|
|
|
42
42
|
Requires-Dist: pytest-cases ~=3.8.0 ; extra == 'dev'
|
|
43
43
|
Requires-Dist: pytest-cov ~=5.0.0 ; extra == 'dev'
|
|
44
44
|
Requires-Dist: pytest-randomly ~=3.15.0 ; extra == 'dev'
|
|
45
|
-
Requires-Dist: pytest ~=8.
|
|
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=HQqVqFiZZZa5NpzDEjMSMgEJPyeMkLHR02MwFttdMVw,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=9yzhnD53Zybjv8HSLja-YaGYrLPvTXtP_1wCvRu5LYU,60538
|
|
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=0bUKvZlZwQ_o0hRwuZZ3nJGYQX2grQ-lJqmDM9tNHZo,18990
|
|
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=nsqtJ_cKPhjv6iYGc8Gt3W6xVsHIFO-r8-nT6jmXZZg,78434
|
|
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=TpUJ-sekIAVYxPR7GJ-rU4uQuSo3MGkaAnqBQNxMsF8,16641
|
|
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=jKKIGStmOwemvTvSP38_RTkn58FPN3Y_XBBIQY2asTA,120458
|
|
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.0.
|
|
65
|
-
pycti-6.0.
|
|
66
|
-
pycti-6.0.
|
|
67
|
-
pycti-6.0.
|
|
68
|
-
pycti-6.0.
|
|
64
|
+
pycti-6.1.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
65
|
+
pycti-6.1.0.dist-info/METADATA,sha256=5vOAg0R4vmqFWt_bFutwhqDuHjj_PL9g07pty2khFF0,5313
|
|
66
|
+
pycti-6.1.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
67
|
+
pycti-6.1.0.dist-info/top_level.txt,sha256=cqEpxitAhHP4VgSA6xmrak6Yk9MeBkwoMTB6k7d2ZnE,6
|
|
68
|
+
pycti-6.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|