Skip to content
This repository was archived by the owner on Dec 5, 2025. It is now read-only.

Commit 9f03745

Browse files
committed
[client] Fix export when nested relationships are in the container (#353)
1 parent e67bbc7 commit 9f03745

File tree

2 files changed

+150
-76
lines changed

2 files changed

+150
-76
lines changed

pycti/entities/opencti_stix_nested_ref_relationship.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,48 @@ def __init__(self, opencti):
1818
start_time
1919
stop_time
2020
from {
21-
... on StixCyberObservable {
21+
... on StixObject {
22+
id
23+
standard_id
24+
entity_type
25+
parent_types
26+
}
27+
... on StixCoreRelationship {
2228
id
2329
standard_id
2430
entity_type
2531
parent_types
32+
}
33+
... on StixSightingRelationship {
34+
id
35+
standard_id
36+
entity_type
37+
parent_types
38+
}
39+
... on StixCyberObservable {
2640
observable_value
2741
}
2842
}
2943
to {
30-
... on StixCyberObservable {
44+
... on StixObject {
45+
id
46+
standard_id
47+
entity_type
48+
parent_types
49+
}
50+
... on StixCoreRelationship {
3151
id
3252
standard_id
3353
entity_type
3454
parent_types
55+
}
56+
... on StixSightingRelationship {
57+
id
58+
standard_id
59+
entity_type
60+
parent_types
61+
}
62+
... on StixCyberObservable {
3563
observable_value
3664
}
3765
}

pycti/utils/opencti_stix2.py

Lines changed: 120 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1484,32 +1484,62 @@ def prepare_export(
14841484
entity["object_refs"] = []
14851485
objects_to_get = entity["objects"]
14861486
for entity_object in entity["objects"]:
1487-
if entity["type"] == "report" and entity_object["entity_type"] not in [
1488-
"Note",
1489-
"Report",
1490-
"Opinion",
1491-
]:
1487+
if (
1488+
entity["type"] == "report"
1489+
and entity_object["entity_type"]
1490+
not in [
1491+
"Note",
1492+
"Report",
1493+
"Opinion",
1494+
]
1495+
and "stix-ref-relationship" not in entity_object["parent_types"]
1496+
):
14921497
entity["object_refs"].append(entity_object["standard_id"])
1493-
elif entity["type"] == "note" and entity_object["entity_type"] not in [
1494-
"Note",
1495-
"Opinion",
1496-
]:
1498+
elif (
1499+
entity["type"] == "note"
1500+
and entity_object["entity_type"]
1501+
not in [
1502+
"Note",
1503+
"Opinion",
1504+
]
1505+
and "stix-ref-relationship" not in entity_object["parent_types"]
1506+
):
14971507
entity["object_refs"].append(entity_object["standard_id"])
1498-
elif entity["type"] == "opinion" and entity_object[
1499-
"entity_type"
1500-
] not in ["Opinion"]:
1508+
elif (
1509+
entity["type"] == "opinion"
1510+
and entity_object["entity_type"] not in ["Opinion"]
1511+
and "stix-ref-relationship" not in entity_object["parent_types"]
1512+
):
15011513
entity["object_refs"].append(entity_object["standard_id"])
1502-
elif entity["type"] == "observed-data":
1514+
elif (
1515+
entity["type"] == "observed-data"
1516+
and "stix-ref-relationship" not in entity_object["parent_types"]
1517+
):
15031518
entity["object_refs"].append(entity_object["standard_id"])
1504-
elif entity["type"] == "grouping":
1519+
elif (
1520+
entity["type"] == "grouping"
1521+
and "stix-ref-relationship" not in entity_object["parent_types"]
1522+
):
15051523
entity["object_refs"].append(entity_object["standard_id"])
1506-
elif entity["type"] == "case-incident":
1524+
elif (
1525+
entity["type"] == "case-incident"
1526+
and "stix-ref-relationship" not in entity_object["parent_types"]
1527+
):
15071528
entity["object_refs"].append(entity_object["standard_id"])
1508-
elif entity["type"] == "feedback":
1529+
elif (
1530+
entity["type"] == "feedback"
1531+
and "stix-ref-relationship" not in entity_object["parent_types"]
1532+
):
15091533
entity["object_refs"].append(entity_object["standard_id"])
1510-
elif entity["type"] == "case-rfi":
1534+
elif (
1535+
entity["type"] == "case-rfi"
1536+
and "stix-ref-relationship" not in entity_object["parent_types"]
1537+
):
15111538
entity["object_refs"].append(entity_object["standard_id"])
1512-
elif entity["type"] == "case-rft":
1539+
elif (
1540+
entity["type"] == "case-rft"
1541+
and "stix-ref-relationship" not in entity_object["parent_types"]
1542+
):
15131543
entity["object_refs"].append(entity_object["standard_id"])
15141544
if "objects" in entity:
15151545
del entity["objects"]
@@ -1578,40 +1608,36 @@ def prepare_export(
15781608
del entity["importFilesIds"]
15791609

15801610
# StixRefRelationship
1581-
if entity["type"] in STIX_CYBER_OBSERVABLE_MAPPING:
1582-
stix_nested_ref_relationships = (
1583-
self.opencti.stix_nested_ref_relationship.list(
1584-
fromId=entity["x_opencti_id"]
1585-
)
1586-
)
1587-
for stix_nested_ref_relationship in stix_nested_ref_relationships:
1588-
if "standard_id" in stix_nested_ref_relationship["to"]:
1589-
if MultipleRefRelationship.has_value(
1611+
stix_nested_ref_relationships = self.opencti.stix_nested_ref_relationship.list(
1612+
fromId=entity["x_opencti_id"]
1613+
)
1614+
for stix_nested_ref_relationship in stix_nested_ref_relationships:
1615+
if "standard_id" in stix_nested_ref_relationship["to"]:
1616+
if MultipleRefRelationship.has_value(
1617+
stix_nested_ref_relationship["relationship_type"]
1618+
):
1619+
key = (
15901620
stix_nested_ref_relationship["relationship_type"]
1591-
):
1592-
key = (
1593-
stix_nested_ref_relationship["relationship_type"]
1594-
.replace("obs_", "")
1595-
.replace("-", "_")
1596-
+ "_refs"
1621+
.replace("obs_", "")
1622+
.replace("-", "_")
1623+
+ "_refs"
1624+
)
1625+
if key in entity:
1626+
entity[key].append(
1627+
stix_nested_ref_relationship["to"]["standard_id"]
15971628
)
1598-
if key in entity:
1599-
entity[key].append(
1600-
stix_nested_ref_relationship["to"]["standard_id"]
1601-
)
1602-
else:
1603-
entity[key] = [
1604-
stix_nested_ref_relationship["to"]["standard_id"]
1605-
]
16061629
else:
1607-
key = (
1608-
stix_nested_ref_relationship["relationship_type"]
1609-
.replace("obs_", "")
1610-
.replace("-", "_")
1611-
+ "_ref"
1612-
)
1613-
entity[key] = stix_nested_ref_relationship["to"]["standard_id"]
1614-
1630+
entity[key] = [
1631+
stix_nested_ref_relationship["to"]["standard_id"]
1632+
]
1633+
else:
1634+
key = (
1635+
stix_nested_ref_relationship["relationship_type"]
1636+
.replace("obs_", "")
1637+
.replace("-", "_")
1638+
+ "_ref"
1639+
)
1640+
entity[key] = stix_nested_ref_relationship["to"]["standard_id"]
16151641
result.append(entity)
16161642

16171643
if mode == "simple":
@@ -1622,28 +1648,43 @@ def prepare_export(
16221648
uuids.append(x["id"])
16231649
# Get extra refs
16241650
for key in entity.keys():
1625-
if entity["type"] in STIX_CYBER_OBSERVABLE_MAPPING:
1626-
if key.endswith("_ref"):
1627-
type = entity[key].split("--")[0]
1651+
if key.endswith("_ref"):
1652+
type = entity[key].split("--")[0]
1653+
if type in STIX_CYBER_OBSERVABLE_MAPPING:
1654+
objects_to_get.append(
1655+
{
1656+
"id": entity[key],
1657+
"entity_type": "Stix-Cyber-Observable",
1658+
"parent_types": ["Stix-Cyber-Observable"],
1659+
}
1660+
)
1661+
else:
1662+
objects_to_get.append(
1663+
{
1664+
"id": entity[key],
1665+
"entity_type": "Stix-Domain-Object",
1666+
"parent_types": ["Stix-Domain-Object"],
1667+
}
1668+
)
1669+
elif key.endswith("_refs"):
1670+
for value in entity[key]:
1671+
type = value.split("--")[0]
16281672
if type in STIX_CYBER_OBSERVABLE_MAPPING:
16291673
objects_to_get.append(
16301674
{
1631-
"id": entity[key],
1675+
"id": value,
16321676
"entity_type": "Stix-Cyber-Observable",
1633-
"parent_types": ["Styx-Cyber-Observable"],
1677+
"parent_types": ["Stix-Cyber-Observable"],
1678+
}
1679+
)
1680+
else:
1681+
objects_to_get.append(
1682+
{
1683+
"id": value,
1684+
"entity_type": "Stix-Domain-Object",
1685+
"parent_types": ["Stix-Domain-Object"],
16341686
}
16351687
)
1636-
elif key.endswith("_refs"):
1637-
for value in entity[key]:
1638-
type = value.split("--")[0]
1639-
if type in STIX_CYBER_OBSERVABLE_MAPPING:
1640-
objects_to_get.append(
1641-
{
1642-
"id": value,
1643-
"entity_type": "Stix-Cyber-Observable",
1644-
"parent_types": ["Styx-Cyber-Observable"],
1645-
}
1646-
)
16471688
# Get extra relations (from)
16481689
stix_core_relationships = self.opencti.stix_core_relationship.list(
16491690
elementId=entity["x_opencti_id"]
@@ -1741,7 +1782,9 @@ def prepare_export(
17411782
"Tool": self.opencti.tool.read,
17421783
"Vulnerability": self.opencti.vulnerability.read,
17431784
"Incident": self.opencti.incident.read,
1785+
"Stix-Core-Object": self.opencti.stix_core_object.read,
17441786
"Stix-Cyber-Observable": self.opencti.stix_cyber_observable.read,
1787+
"Stix-Domain-Object": self.opencti.stix_domain_object.read,
17451788
"stix-core-relationship": self.opencti.stix_core_relationship.read,
17461789
"stix-sighting-relationship": self.opencti.stix_sighting_relationship.read,
17471790
}
@@ -1769,15 +1812,18 @@ def prepare_export(
17691812
),
17701813
)
17711814
entity_object_data = do_read(id=entity_object["id"])
1772-
stix_entity_object = self.prepare_export(
1773-
self.generate_export(entity_object_data),
1774-
"simple",
1775-
max_marking_definition_entity,
1776-
)
1777-
# Add to result
1778-
entity_object_bundle = self.filter_objects(uuids, stix_entity_object)
1779-
uuids = uuids + [x["id"] for x in entity_object_bundle]
1780-
result = result + entity_object_bundle
1815+
if entity_object_data is not None:
1816+
stix_entity_object = self.prepare_export(
1817+
self.generate_export(entity_object_data),
1818+
"simple",
1819+
max_marking_definition_entity,
1820+
)
1821+
# Add to result
1822+
entity_object_bundle = self.filter_objects(
1823+
uuids, stix_entity_object
1824+
)
1825+
uuids = uuids + [x["id"] for x in entity_object_bundle]
1826+
result = result + entity_object_bundle
17811827
for relation_object in relations_to_get:
17821828
relation_object_data = self.prepare_export(
17831829
self.opencti.stix_core_relationship.read(id=relation_object["id"])

0 commit comments

Comments
 (0)