pycti 6.0.9__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 +11 -1
- pycti/api/opencti_api_client.py +17 -5
- pycti/api/opencti_api_playbook.py +3 -2
- pycti/api/opencti_api_work.py +63 -54
- pycti/connector/opencti_connector_helper.py +145 -44
- pycti/entities/opencti_case_incident.py +1 -1
- pycti/entities/opencti_incident.py +4 -0
- pycti/entities/opencti_indicator.py +11 -0
- pycti/entities/opencti_intrusion_set.py +37 -4
- pycti/entities/opencti_malware_analysis.py +11 -0
- pycti/entities/opencti_report.py +13 -0
- pycti/entities/opencti_stix_core_object.py +38 -5
- pycti/entities/opencti_stix_cyber_observable.py +91 -13
- pycti/entities/opencti_stix_domain_object.py +25 -7
- pycti/entities/opencti_stix_object_or_stix_relationship.py +63 -4
- pycti/utils/constants.py +110 -1
- pycti/utils/opencti_stix2.py +268 -68
- pycti/utils/opencti_stix2_utils.py +12 -1
- {pycti-6.0.9.dist-info → pycti-6.1.0.dist-info}/METADATA +5 -5
- {pycti-6.0.9.dist-info → pycti-6.1.0.dist-info}/RECORD +23 -23
- {pycti-6.0.9.dist-info → pycti-6.1.0.dist-info}/LICENSE +0 -0
- {pycti-6.0.9.dist-info → pycti-6.1.0.dist-info}/WHEEL +0 -0
- {pycti-6.0.9.dist-info → pycti-6.1.0.dist-info}/top_level.txt +0 -0
|
@@ -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
|
|
@@ -363,6 +385,7 @@ class IntrusionSet:
|
|
|
363
385
|
secondary_motivations = kwargs.get("secondary_motivations", None)
|
|
364
386
|
x_opencti_stix_ids = kwargs.get("x_opencti_stix_ids", None)
|
|
365
387
|
granted_refs = kwargs.get("objectOrganization", None)
|
|
388
|
+
x_opencti_workflow_id = kwargs.get("x_opencti_workflow_id", None)
|
|
366
389
|
update = kwargs.get("update", False)
|
|
367
390
|
|
|
368
391
|
if name is not None:
|
|
@@ -402,6 +425,7 @@ class IntrusionSet:
|
|
|
402
425
|
"primary_motivation": primary_motivation,
|
|
403
426
|
"secondary_motivations": secondary_motivations,
|
|
404
427
|
"x_opencti_stix_ids": x_opencti_stix_ids,
|
|
428
|
+
"x_opencti_workflow_id": x_opencti_workflow_id,
|
|
405
429
|
"update": update,
|
|
406
430
|
}
|
|
407
431
|
},
|
|
@@ -435,7 +459,11 @@ class IntrusionSet:
|
|
|
435
459
|
stix_object["x_opencti_granted_refs"] = (
|
|
436
460
|
self.opencti.get_attribute_in_extension("granted_refs", stix_object)
|
|
437
461
|
)
|
|
438
|
-
|
|
462
|
+
if "x_opencti_workflow_id" not in stix_object:
|
|
463
|
+
stix_object["x_opencti_workflow_id"] = (
|
|
464
|
+
self.opencti.get_attribute_in_extension("workflow_id", stix_object)
|
|
465
|
+
)
|
|
466
|
+
7
|
|
439
467
|
return self.create(
|
|
440
468
|
stix_id=stix_object["id"],
|
|
441
469
|
createdBy=(
|
|
@@ -500,6 +528,11 @@ class IntrusionSet:
|
|
|
500
528
|
if "x_opencti_granted_refs" in stix_object
|
|
501
529
|
else None
|
|
502
530
|
),
|
|
531
|
+
x_opencti_workflow_id=(
|
|
532
|
+
stix_object["x_opencti_workflow_id"]
|
|
533
|
+
if "x_opencti_workflow_id" in stix_object
|
|
534
|
+
else None
|
|
535
|
+
),
|
|
503
536
|
update=update,
|
|
504
537
|
)
|
|
505
538
|
else:
|
|
@@ -401,6 +401,7 @@ class MalwareAnalysis:
|
|
|
401
401
|
analysisSco = kwargs.get("analysisSco", None)
|
|
402
402
|
x_opencti_stix_ids = kwargs.get("x_opencti_stix_ids", None)
|
|
403
403
|
granted_refs = kwargs.get("objectOrganization", None)
|
|
404
|
+
x_opencti_workflow_id = kwargs.get("x_opencti_workflow_id", None)
|
|
404
405
|
update = kwargs.get("update", False)
|
|
405
406
|
|
|
406
407
|
if product is not None and result_name is not None:
|
|
@@ -449,6 +450,7 @@ class MalwareAnalysis:
|
|
|
449
450
|
"analysisSample": sample,
|
|
450
451
|
"analysisSco": analysisSco,
|
|
451
452
|
"x_opencti_stix_ids": x_opencti_stix_ids,
|
|
453
|
+
"x_opencti_workflow_id": x_opencti_workflow_id,
|
|
452
454
|
"update": update,
|
|
453
455
|
}
|
|
454
456
|
},
|
|
@@ -482,6 +484,10 @@ class MalwareAnalysis:
|
|
|
482
484
|
stix_object["x_opencti_granted_refs"] = (
|
|
483
485
|
self.opencti.get_attribute_in_extension("granted_refs", stix_object)
|
|
484
486
|
)
|
|
487
|
+
if "x_opencti_workflow_id" not in stix_object:
|
|
488
|
+
stix_object["x_opencti_workflow_id"] = (
|
|
489
|
+
self.opencti.get_attribute_in_extension("workflow_id", stix_object)
|
|
490
|
+
)
|
|
485
491
|
|
|
486
492
|
return self.create(
|
|
487
493
|
stix_id=stix_object["id"],
|
|
@@ -574,6 +580,11 @@ class MalwareAnalysis:
|
|
|
574
580
|
if "x_opencti_granted_refs" in stix_object
|
|
575
581
|
else None
|
|
576
582
|
),
|
|
583
|
+
x_opencti_workflow_id=(
|
|
584
|
+
stix_object["x_opencti_workflow_id"]
|
|
585
|
+
if "x_opencti_workflow_id" in stix_object
|
|
586
|
+
else None
|
|
587
|
+
),
|
|
577
588
|
update=update,
|
|
578
589
|
)
|
|
579
590
|
else:
|
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
|
|
@@ -615,6 +624,12 @@ class StixCoreObject:
|
|
|
615
624
|
... on PhoneNumber {
|
|
616
625
|
value
|
|
617
626
|
}
|
|
627
|
+
... on TrackingNumber {
|
|
628
|
+
value
|
|
629
|
+
}
|
|
630
|
+
... on Credential {
|
|
631
|
+
value
|
|
632
|
+
}
|
|
618
633
|
... on PaymentCard {
|
|
619
634
|
card_number
|
|
620
635
|
expiration_date
|
|
@@ -1084,9 +1099,18 @@ class StixCoreObject:
|
|
|
1084
1099
|
}
|
|
1085
1100
|
}
|
|
1086
1101
|
}
|
|
1087
|
-
}
|
|
1102
|
+
}
|
|
1088
1103
|
... on StixCyberObservable {
|
|
1089
1104
|
observable_value
|
|
1105
|
+
indicators {
|
|
1106
|
+
edges {
|
|
1107
|
+
node {
|
|
1108
|
+
id
|
|
1109
|
+
pattern
|
|
1110
|
+
pattern_type
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1090
1114
|
}
|
|
1091
1115
|
... on AutonomousSystem {
|
|
1092
1116
|
number
|
|
@@ -1453,13 +1477,21 @@ class StixCoreObject:
|
|
|
1453
1477
|
return entity["importFiles"]
|
|
1454
1478
|
|
|
1455
1479
|
def push_list_export(
|
|
1456
|
-
self,
|
|
1480
|
+
self,
|
|
1481
|
+
entity_id,
|
|
1482
|
+
entity_type,
|
|
1483
|
+
file_name,
|
|
1484
|
+
file_markings,
|
|
1485
|
+
data,
|
|
1486
|
+
list_filters="",
|
|
1487
|
+
mime_type=None,
|
|
1457
1488
|
):
|
|
1458
1489
|
query = """
|
|
1459
|
-
mutation StixCoreObjectsExportPush($entity_id: String, $entity_type: String!, $file: Upload!, $listFilters: String) {
|
|
1460
|
-
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)
|
|
1461
1492
|
}
|
|
1462
1493
|
"""
|
|
1494
|
+
|
|
1463
1495
|
if mime_type is None:
|
|
1464
1496
|
file = self.file(file_name, data)
|
|
1465
1497
|
else:
|
|
@@ -1470,6 +1502,7 @@ class StixCoreObject:
|
|
|
1470
1502
|
"entity_id": entity_id,
|
|
1471
1503
|
"entity_type": entity_type,
|
|
1472
1504
|
"file": file,
|
|
1505
|
+
"file_markings": file_markings,
|
|
1473
1506
|
"listFilters": list_filters,
|
|
1474
1507
|
},
|
|
1475
1508
|
)
|
|
@@ -282,6 +282,12 @@ class StixCyberObservable:
|
|
|
282
282
|
... on PhoneNumber {
|
|
283
283
|
value
|
|
284
284
|
}
|
|
285
|
+
... on TrackingNumber {
|
|
286
|
+
value
|
|
287
|
+
}
|
|
288
|
+
... on Credential {
|
|
289
|
+
value
|
|
290
|
+
}
|
|
285
291
|
... on PaymentCard {
|
|
286
292
|
card_number
|
|
287
293
|
expiration_date
|
|
@@ -576,6 +582,12 @@ class StixCyberObservable:
|
|
|
576
582
|
... on PhoneNumber {
|
|
577
583
|
value
|
|
578
584
|
}
|
|
585
|
+
... on TrackingNumber {
|
|
586
|
+
value
|
|
587
|
+
}
|
|
588
|
+
... on Credential {
|
|
589
|
+
value
|
|
590
|
+
}
|
|
579
591
|
... on PaymentCard {
|
|
580
592
|
card_number
|
|
581
593
|
expiration_date
|
|
@@ -857,6 +869,15 @@ class StixCyberObservable:
|
|
|
857
869
|
type = "IPv6-Addr"
|
|
858
870
|
elif type.lower() == "hostname" or type.lower() == "x-opencti-hostname":
|
|
859
871
|
type = "Hostname"
|
|
872
|
+
elif type.lower() == "payment-card" or type.lower() == "x-opencti-payment-card":
|
|
873
|
+
type = "Payment-Card"
|
|
874
|
+
elif type.lower() == "credential" or type.lower() == "x-opencti-credential":
|
|
875
|
+
type = "Credential"
|
|
876
|
+
elif (
|
|
877
|
+
type.lower() == "tracking-number"
|
|
878
|
+
or type.lower() == "x-opencti-tracking-number"
|
|
879
|
+
):
|
|
880
|
+
type = "Tracking-Number"
|
|
860
881
|
elif (
|
|
861
882
|
type.lower() == "cryptocurrency-wallet"
|
|
862
883
|
or type.lower() == "x-opencti-cryptocurrency-wallet"
|
|
@@ -974,6 +995,8 @@ class StixCyberObservable:
|
|
|
974
995
|
$UserAgent: UserAgentAddInput
|
|
975
996
|
$BankAccount: BankAccountAddInput
|
|
976
997
|
$PhoneNumber: PhoneNumberAddInput
|
|
998
|
+
$Credential: CredentialAddInput
|
|
999
|
+
$TrackingNumber: TrackingNumberAddInput
|
|
977
1000
|
$PaymentCard: PaymentCardAddInput
|
|
978
1001
|
$MediaContent: MediaContentAddInput
|
|
979
1002
|
) {
|
|
@@ -1016,6 +1039,8 @@ class StixCyberObservable:
|
|
|
1016
1039
|
UserAgent: $UserAgent
|
|
1017
1040
|
BankAccount: $BankAccount
|
|
1018
1041
|
PhoneNumber: $PhoneNumber
|
|
1042
|
+
Credential: $Credential
|
|
1043
|
+
TrackingNumber: $TrackingNumber
|
|
1019
1044
|
PaymentCard: $PaymentCard
|
|
1020
1045
|
MediaContent: $MediaContent
|
|
1021
1046
|
) {
|
|
@@ -1508,15 +1533,6 @@ class StixCyberObservable:
|
|
|
1508
1533
|
observable_data["value"] if "value" in observable_data else None
|
|
1509
1534
|
),
|
|
1510
1535
|
}
|
|
1511
|
-
elif (
|
|
1512
|
-
type == "Cryptocurrency-Wallet"
|
|
1513
|
-
or type == "X-OpenCTI-Cryptocurrency-Wallet"
|
|
1514
|
-
):
|
|
1515
|
-
input_variables["CryptocurrencyWallet"] = {
|
|
1516
|
-
"value": (
|
|
1517
|
-
observable_data["value"] if "value" in observable_data else None
|
|
1518
|
-
),
|
|
1519
|
-
}
|
|
1520
1536
|
elif type == "Hostname":
|
|
1521
1537
|
input_variables["Hostname"] = {
|
|
1522
1538
|
"value": (
|
|
@@ -1588,8 +1604,50 @@ class StixCyberObservable:
|
|
|
1588
1604
|
else None
|
|
1589
1605
|
),
|
|
1590
1606
|
}
|
|
1607
|
+
elif type == "Payment-Card" or type.lower() == "x-opencti-payment-card":
|
|
1608
|
+
input_variables["PaymentCard"] = {
|
|
1609
|
+
"card_number": (
|
|
1610
|
+
observable_data["card_number"]
|
|
1611
|
+
if "card_number" in observable_data
|
|
1612
|
+
else None
|
|
1613
|
+
),
|
|
1614
|
+
"expiration_date": (
|
|
1615
|
+
observable_data["expiration_date"]
|
|
1616
|
+
if "expiration_date" in observable_data
|
|
1617
|
+
else None
|
|
1618
|
+
),
|
|
1619
|
+
"cvv": observable_data["cvv"] if "cvv" in observable_data else None,
|
|
1620
|
+
"holder_name": (
|
|
1621
|
+
observable_data["holder_name"]
|
|
1622
|
+
if "holder_name" in observable_data
|
|
1623
|
+
else None
|
|
1624
|
+
),
|
|
1625
|
+
}
|
|
1626
|
+
elif (
|
|
1627
|
+
type == "Cryptocurrency-Wallet"
|
|
1628
|
+
or type.lower() == "x-opencti-cryptocurrency-wallet"
|
|
1629
|
+
):
|
|
1630
|
+
input_variables["CryptocurrencyWallet"] = {
|
|
1631
|
+
"value": (
|
|
1632
|
+
observable_data["value"] if "value" in observable_data else None
|
|
1633
|
+
),
|
|
1634
|
+
}
|
|
1635
|
+
elif type == "Credential" or type.lower() == "x-opencti-credential":
|
|
1636
|
+
input_variables["Credential"] = {
|
|
1637
|
+
"value": (
|
|
1638
|
+
observable_data["value"] if "value" in observable_data else None
|
|
1639
|
+
),
|
|
1640
|
+
}
|
|
1641
|
+
elif (
|
|
1642
|
+
type == "Tracking-Number" or type.lower() == "x-opencti-tracking-number"
|
|
1643
|
+
):
|
|
1644
|
+
input_variables["TrackingNumber"] = {
|
|
1645
|
+
"value": (
|
|
1646
|
+
observable_data["value"] if "value" in observable_data else None
|
|
1647
|
+
),
|
|
1648
|
+
}
|
|
1591
1649
|
result = self.opencti.query(query, input_variables)
|
|
1592
|
-
if "payload_bin" in observable_data and "
|
|
1650
|
+
if "payload_bin" in observable_data and "mime_type" in observable_data:
|
|
1593
1651
|
self.add_file(
|
|
1594
1652
|
id=result["data"]["stixCyberObservableAdd"]["id"],
|
|
1595
1653
|
file_name=(
|
|
@@ -2258,11 +2316,30 @@ class StixCyberObservable:
|
|
|
2258
2316
|
return False
|
|
2259
2317
|
|
|
2260
2318
|
def push_list_export(
|
|
2261
|
-
self,
|
|
2319
|
+
self,
|
|
2320
|
+
entity_id,
|
|
2321
|
+
entity_type,
|
|
2322
|
+
file_name,
|
|
2323
|
+
file_markings,
|
|
2324
|
+
data,
|
|
2325
|
+
list_filters="",
|
|
2326
|
+
mime_type=None,
|
|
2262
2327
|
):
|
|
2263
2328
|
query = """
|
|
2264
|
-
mutation StixCyberObservablesExportPush(
|
|
2265
|
-
|
|
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
|
+
)
|
|
2266
2343
|
}
|
|
2267
2344
|
"""
|
|
2268
2345
|
if mime_type is None:
|
|
@@ -2275,6 +2352,7 @@ class StixCyberObservable:
|
|
|
2275
2352
|
"entity_id": entity_id,
|
|
2276
2353
|
"entity_type": entity_type,
|
|
2277
2354
|
"file": file,
|
|
2355
|
+
"file_markings": file_markings,
|
|
2278
2356
|
"listFilters": list_filters,
|
|
2279
2357
|
},
|
|
2280
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
|
@@ -42,6 +42,8 @@ class StixCyberObservableTypes(Enum):
|
|
|
42
42
|
USER_AGENT = "User-Agent"
|
|
43
43
|
BANK_ACCOUNT = "Bank-Account"
|
|
44
44
|
PHONE_NUMBER = "Phone-Number"
|
|
45
|
+
CREDENTIAL = "Credential"
|
|
46
|
+
TRACKING_NUMBER = "Tracking-Number"
|
|
45
47
|
PAYMENT_CARD = "Payment-Card"
|
|
46
48
|
MEDIA_CONTENT = "Media-Content"
|
|
47
49
|
SIMPLE_OBSERVABLE = "Simple-Observable"
|
|
@@ -66,6 +68,7 @@ class IdentityTypes(Enum):
|
|
|
66
68
|
|
|
67
69
|
class ThreatActorTypes(Enum):
|
|
68
70
|
THREAT_ACTOR_GROUP = "Threat-Actor-Group"
|
|
71
|
+
THREAT_ACTOR_INDIVIDUAL = "Threat-Actor-Individual"
|
|
69
72
|
|
|
70
73
|
@classmethod
|
|
71
74
|
def has_value(cls, value):
|
|
@@ -126,7 +129,6 @@ class MultipleRefRelationship(Enum):
|
|
|
126
129
|
CHILD = "child"
|
|
127
130
|
BODY_MULTIPART = "body-multipart"
|
|
128
131
|
VALUES = "values"
|
|
129
|
-
LINKED = "x_opencti_linked-to"
|
|
130
132
|
SERVICE_DDL = "service-dll"
|
|
131
133
|
INSTALLED_SOFTWARE = "installed-software"
|
|
132
134
|
RELATION_ANALYSIS_SCO = "analysis-sco"
|
|
@@ -263,6 +265,73 @@ class CustomObservableText:
|
|
|
263
265
|
pass
|
|
264
266
|
|
|
265
267
|
|
|
268
|
+
@CustomObservable(
|
|
269
|
+
"payment-card",
|
|
270
|
+
[
|
|
271
|
+
("value", StringProperty(required=True)),
|
|
272
|
+
("card_number", StringProperty(required=True)),
|
|
273
|
+
("expiration_date", StringProperty(required=False)),
|
|
274
|
+
("cvv", StringProperty(required=False)),
|
|
275
|
+
("holder_name", StringProperty(required=False)),
|
|
276
|
+
("spec_version", StringProperty(fixed="2.1")),
|
|
277
|
+
(
|
|
278
|
+
"object_marking_refs",
|
|
279
|
+
ListProperty(
|
|
280
|
+
ReferenceProperty(valid_types="marking-definition", spec_version="2.1")
|
|
281
|
+
),
|
|
282
|
+
),
|
|
283
|
+
],
|
|
284
|
+
["card_number"],
|
|
285
|
+
)
|
|
286
|
+
class CustomObservablePaymentCard:
|
|
287
|
+
"""Payment card observable."""
|
|
288
|
+
|
|
289
|
+
pass
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
@CustomObservable(
|
|
293
|
+
"bank-account",
|
|
294
|
+
[
|
|
295
|
+
("value", StringProperty(required=True)),
|
|
296
|
+
("iban", StringProperty(required=True)),
|
|
297
|
+
("bic", StringProperty(required=False)),
|
|
298
|
+
("account_number", StringProperty(required=False)),
|
|
299
|
+
("spec_version", StringProperty(fixed="2.1")),
|
|
300
|
+
(
|
|
301
|
+
"object_marking_refs",
|
|
302
|
+
ListProperty(
|
|
303
|
+
ReferenceProperty(valid_types="marking-definition", spec_version="2.1")
|
|
304
|
+
),
|
|
305
|
+
),
|
|
306
|
+
],
|
|
307
|
+
["iban"],
|
|
308
|
+
)
|
|
309
|
+
class CustomObservableBankAccount:
|
|
310
|
+
"""Bank Account observable."""
|
|
311
|
+
|
|
312
|
+
pass
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
@CustomObservable(
|
|
316
|
+
"credential",
|
|
317
|
+
[
|
|
318
|
+
("value", StringProperty(required=True)),
|
|
319
|
+
("spec_version", StringProperty(fixed="2.1")),
|
|
320
|
+
(
|
|
321
|
+
"object_marking_refs",
|
|
322
|
+
ListProperty(
|
|
323
|
+
ReferenceProperty(valid_types="marking-definition", spec_version="2.1")
|
|
324
|
+
),
|
|
325
|
+
),
|
|
326
|
+
],
|
|
327
|
+
["value"],
|
|
328
|
+
)
|
|
329
|
+
class CustomObservableCredential:
|
|
330
|
+
"""Credential observable."""
|
|
331
|
+
|
|
332
|
+
pass
|
|
333
|
+
|
|
334
|
+
|
|
266
335
|
@CustomObservable(
|
|
267
336
|
"cryptocurrency-wallet",
|
|
268
337
|
[
|
|
@@ -283,6 +352,46 @@ class CustomObservableCryptocurrencyWallet:
|
|
|
283
352
|
pass
|
|
284
353
|
|
|
285
354
|
|
|
355
|
+
@CustomObservable(
|
|
356
|
+
"phone-number",
|
|
357
|
+
[
|
|
358
|
+
("value", StringProperty(required=True)),
|
|
359
|
+
("spec_version", StringProperty(fixed="2.1")),
|
|
360
|
+
(
|
|
361
|
+
"object_marking_refs",
|
|
362
|
+
ListProperty(
|
|
363
|
+
ReferenceProperty(valid_types="marking-definition", spec_version="2.1")
|
|
364
|
+
),
|
|
365
|
+
),
|
|
366
|
+
],
|
|
367
|
+
["value"],
|
|
368
|
+
)
|
|
369
|
+
class CustomObservablePhoneNumber:
|
|
370
|
+
"""Phone number observable."""
|
|
371
|
+
|
|
372
|
+
pass
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
@CustomObservable(
|
|
376
|
+
"tracking-number",
|
|
377
|
+
[
|
|
378
|
+
("value", StringProperty(required=True)),
|
|
379
|
+
("spec_version", StringProperty(fixed="2.1")),
|
|
380
|
+
(
|
|
381
|
+
"object_marking_refs",
|
|
382
|
+
ListProperty(
|
|
383
|
+
ReferenceProperty(valid_types="marking-definition", spec_version="2.1")
|
|
384
|
+
),
|
|
385
|
+
),
|
|
386
|
+
],
|
|
387
|
+
["value"],
|
|
388
|
+
)
|
|
389
|
+
class CustomObservableTrackingNumber:
|
|
390
|
+
"""Tracking number observable."""
|
|
391
|
+
|
|
392
|
+
pass
|
|
393
|
+
|
|
394
|
+
|
|
286
395
|
@CustomObservable(
|
|
287
396
|
"user-agent",
|
|
288
397
|
[
|