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
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,
|
|
@@ -835,6 +880,21 @@ class OpenCTIStix2:
|
|
|
835
880
|
"Vulnerability": self.opencti.vulnerability.read,
|
|
836
881
|
}
|
|
837
882
|
|
|
883
|
+
def get_reader(self, entity_type: str):
|
|
884
|
+
# Map types
|
|
885
|
+
if entity_type == "StixFile":
|
|
886
|
+
entity_type = "File"
|
|
887
|
+
if IdentityTypes.has_value(entity_type):
|
|
888
|
+
entity_type = "Identity"
|
|
889
|
+
if LocationTypes.has_value(entity_type):
|
|
890
|
+
entity_type = "Location"
|
|
891
|
+
if StixCyberObservableTypes.has_value(entity_type):
|
|
892
|
+
entity_type = "Stix-Cyber-Observable"
|
|
893
|
+
readers = self.get_readers()
|
|
894
|
+
return readers.get(
|
|
895
|
+
entity_type, lambda **kwargs: self.unknown_type({"type": entity_type})
|
|
896
|
+
)
|
|
897
|
+
|
|
838
898
|
# endregion
|
|
839
899
|
|
|
840
900
|
# region import
|
|
@@ -1497,7 +1557,7 @@ class OpenCTIStix2:
|
|
|
1497
1557
|
if "tasks" in entity:
|
|
1498
1558
|
del entity["tasks"]
|
|
1499
1559
|
|
|
1500
|
-
if "status" in entity:
|
|
1560
|
+
if "status" in entity and entity["status"] is not None:
|
|
1501
1561
|
entity["x_opencti_workflow_id"] = entity["status"].get("id")
|
|
1502
1562
|
if "status" in entity:
|
|
1503
1563
|
del entity["status"]
|
|
@@ -1599,28 +1659,90 @@ class OpenCTIStix2:
|
|
|
1599
1659
|
|
|
1600
1660
|
return {k: v for k, v in entity.items() if self.opencti.not_empty(v)}
|
|
1601
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
|
+
|
|
1602
1699
|
def prepare_export(
|
|
1603
1700
|
self,
|
|
1604
1701
|
entity: Dict,
|
|
1605
1702
|
mode: str = "simple",
|
|
1606
1703
|
max_marking_definition_entity: Dict = None,
|
|
1704
|
+
main_filter: Dict = None,
|
|
1705
|
+
access_filter: Dict = None,
|
|
1607
1706
|
no_custom_attributes: bool = False,
|
|
1608
1707
|
) -> List:
|
|
1609
|
-
if (
|
|
1610
|
-
self.check_max_marking_definition(
|
|
1611
|
-
max_marking_definition_entity,
|
|
1612
|
-
entity["objectMarking"] if "objectMarking" in entity else [],
|
|
1613
|
-
)
|
|
1614
|
-
is False
|
|
1615
|
-
):
|
|
1616
|
-
self.opencti.app_logger.info(
|
|
1617
|
-
"Marking definitions are less than max definition, not exporting.",
|
|
1618
|
-
{"type": entity["type"]},
|
|
1619
|
-
)
|
|
1620
|
-
return []
|
|
1621
1708
|
result = []
|
|
1622
1709
|
objects_to_get = []
|
|
1623
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
|
+
|
|
1624
1746
|
# CreatedByRef
|
|
1625
1747
|
if (
|
|
1626
1748
|
not no_custom_attributes
|
|
@@ -1732,7 +1854,7 @@ class OpenCTIStix2:
|
|
|
1732
1854
|
and len(entity["objects"]) > 0
|
|
1733
1855
|
):
|
|
1734
1856
|
entity["object_refs"] = []
|
|
1735
|
-
objects_to_get = entity["objects"]
|
|
1857
|
+
objects_to_get = entity["objects"] # To do differently
|
|
1736
1858
|
for entity_object in entity["objects"]:
|
|
1737
1859
|
if (
|
|
1738
1860
|
entity["type"] == "report"
|
|
@@ -1804,22 +1926,62 @@ class OpenCTIStix2:
|
|
|
1804
1926
|
entity["type"] = "sighting"
|
|
1805
1927
|
entity["count"] = entity["attribute_count"]
|
|
1806
1928
|
del entity["attribute_count"]
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
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
|
+
|
|
1811
1954
|
del entity["from"]
|
|
1812
1955
|
del entity["to"]
|
|
1813
1956
|
# Stix Core Relationship
|
|
1814
1957
|
if "from" in entity or "to" in entity:
|
|
1815
1958
|
entity["type"] = "relationship"
|
|
1816
1959
|
if "from" in entity:
|
|
1817
|
-
|
|
1818
|
-
|
|
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 ?
|
|
1819
1973
|
del entity["from"]
|
|
1820
1974
|
if "to" in entity:
|
|
1821
|
-
|
|
1822
|
-
|
|
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"])
|
|
1823
1985
|
del entity["to"]
|
|
1824
1986
|
# Stix Domain Object
|
|
1825
1987
|
if "attribute_abstract" in entity:
|
|
@@ -1862,7 +2024,7 @@ class OpenCTIStix2:
|
|
|
1862
2024
|
|
|
1863
2025
|
# StixRefRelationship
|
|
1864
2026
|
stix_nested_ref_relationships = self.opencti.stix_nested_ref_relationship.list(
|
|
1865
|
-
fromId=entity["x_opencti_id"]
|
|
2027
|
+
fromId=entity["x_opencti_id"], filters=access_filter
|
|
1866
2028
|
)
|
|
1867
2029
|
for stix_nested_ref_relationship in stix_nested_ref_relationships:
|
|
1868
2030
|
if "standard_id" in stix_nested_ref_relationship["to"]:
|
|
@@ -1906,8 +2068,8 @@ class OpenCTIStix2:
|
|
|
1906
2068
|
return result
|
|
1907
2069
|
elif mode == "full":
|
|
1908
2070
|
uuids = [entity["id"]]
|
|
1909
|
-
for
|
|
1910
|
-
uuids.append(
|
|
2071
|
+
for y in result:
|
|
2072
|
+
uuids.append(y["id"])
|
|
1911
2073
|
# Get extra refs
|
|
1912
2074
|
for key in entity.keys():
|
|
1913
2075
|
if key.endswith("_ref"):
|
|
@@ -1949,7 +2111,7 @@ class OpenCTIStix2:
|
|
|
1949
2111
|
)
|
|
1950
2112
|
# Get extra relations (from AND to)
|
|
1951
2113
|
stix_core_relationships = self.opencti.stix_core_relationship.list(
|
|
1952
|
-
fromOrToId=entity["x_opencti_id"], getAll=True
|
|
2114
|
+
fromOrToId=entity["x_opencti_id"], getAll=True, filters=access_filter
|
|
1953
2115
|
)
|
|
1954
2116
|
for stix_core_relationship in stix_core_relationships:
|
|
1955
2117
|
if self.check_max_marking_definition(
|
|
@@ -1965,10 +2127,14 @@ class OpenCTIStix2:
|
|
|
1965
2127
|
if stix_core_relationship["to"]["id"] != entity["x_opencti_id"]
|
|
1966
2128
|
else stix_core_relationship["from"]
|
|
1967
2129
|
)
|
|
1968
|
-
relation_object_data =
|
|
1969
|
-
self.
|
|
1970
|
-
|
|
1971
|
-
|
|
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
|
+
)
|
|
1972
2138
|
)
|
|
1973
2139
|
relation_object_bundle = self.filter_objects(
|
|
1974
2140
|
uuids, relation_object_data
|
|
@@ -1986,8 +2152,7 @@ class OpenCTIStix2:
|
|
|
1986
2152
|
)
|
|
1987
2153
|
# Get sighting
|
|
1988
2154
|
stix_sighting_relationships = self.opencti.stix_sighting_relationship.list(
|
|
1989
|
-
fromOrToId=entity["x_opencti_id"],
|
|
1990
|
-
getAll=True,
|
|
2155
|
+
fromOrToId=entity["x_opencti_id"], getAll=True, filters=access_filter
|
|
1991
2156
|
)
|
|
1992
2157
|
for stix_sighting_relationship in stix_sighting_relationships:
|
|
1993
2158
|
if self.check_max_marking_definition(
|
|
@@ -2004,10 +2169,14 @@ class OpenCTIStix2:
|
|
|
2004
2169
|
!= entity["x_opencti_id"]
|
|
2005
2170
|
else stix_sighting_relationship["from"]
|
|
2006
2171
|
)
|
|
2007
|
-
relation_object_data =
|
|
2008
|
-
self.
|
|
2009
|
-
|
|
2010
|
-
|
|
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
|
+
)
|
|
2011
2180
|
)
|
|
2012
2181
|
relation_object_bundle = self.filter_objects(
|
|
2013
2182
|
uuids, relation_object_data
|
|
@@ -2050,12 +2219,16 @@ class OpenCTIStix2:
|
|
|
2050
2219
|
{"type": entity_object["entity_type"]}
|
|
2051
2220
|
),
|
|
2052
2221
|
)
|
|
2053
|
-
entity_object_data = do_read(
|
|
2222
|
+
entity_object_data = do_read(
|
|
2223
|
+
id=entity_object["id"], filters=access_filter
|
|
2224
|
+
)
|
|
2054
2225
|
if entity_object_data is not None:
|
|
2055
2226
|
stix_entity_object = self.prepare_export(
|
|
2056
2227
|
self.generate_export(entity_object_data),
|
|
2057
2228
|
"simple",
|
|
2058
2229
|
max_marking_definition_entity,
|
|
2230
|
+
main_filter,
|
|
2231
|
+
access_filter,
|
|
2059
2232
|
)
|
|
2060
2233
|
# Add to result
|
|
2061
2234
|
entity_object_bundle = self.filter_objects(
|
|
@@ -2063,9 +2236,18 @@ class OpenCTIStix2:
|
|
|
2063
2236
|
)
|
|
2064
2237
|
uuids = uuids + [x["id"] for x in entity_object_bundle]
|
|
2065
2238
|
result = result + entity_object_bundle
|
|
2066
|
-
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
|
+
|
|
2067
2246
|
relation_object_data = self.prepare_export(
|
|
2068
|
-
|
|
2247
|
+
filter(
|
|
2248
|
+
find_relation_object_data,
|
|
2249
|
+
self.opencti.stix_core_relationship.list(filters=access_filter),
|
|
2250
|
+
)
|
|
2069
2251
|
)
|
|
2070
2252
|
relation_object_bundle = self.filter_objects(
|
|
2071
2253
|
uuids, relation_object_data
|
|
@@ -2135,15 +2317,12 @@ class OpenCTIStix2:
|
|
|
2135
2317
|
entity_type: str,
|
|
2136
2318
|
entity_id: str,
|
|
2137
2319
|
mode: str = "simple",
|
|
2320
|
+
main_filter: Dict = None,
|
|
2321
|
+
access_filter: Dict = None,
|
|
2138
2322
|
max_marking_definition: Dict = None,
|
|
2139
2323
|
no_custom_attributes: bool = False,
|
|
2140
2324
|
only_entity: bool = False,
|
|
2141
2325
|
) -> Dict:
|
|
2142
|
-
max_marking_definition_entity = (
|
|
2143
|
-
self.opencti.marking_definition.read(id=max_marking_definition)
|
|
2144
|
-
if max_marking_definition is not None
|
|
2145
|
-
else None
|
|
2146
|
-
)
|
|
2147
2326
|
bundle = {
|
|
2148
2327
|
"type": "bundle",
|
|
2149
2328
|
"id": "bundle--" + str(uuid.uuid4()),
|
|
@@ -2159,14 +2338,12 @@ class OpenCTIStix2:
|
|
|
2159
2338
|
if LocationTypes.has_value(entity_type):
|
|
2160
2339
|
entity_type = "Location"
|
|
2161
2340
|
|
|
2162
|
-
#
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
entity_type = "Stix-Cyber-Observable"
|
|
2166
|
-
do_read = reader.get(
|
|
2341
|
+
# Lister
|
|
2342
|
+
listers = self.get_listers()
|
|
2343
|
+
do_list = listers.get(
|
|
2167
2344
|
entity_type, lambda **kwargs: self.unknown_type({"type": entity_type})
|
|
2168
2345
|
)
|
|
2169
|
-
entity =
|
|
2346
|
+
entity = do_list(filters=main_filter)[0]
|
|
2170
2347
|
if entity is None:
|
|
2171
2348
|
self.opencti.app_logger.error(
|
|
2172
2349
|
"Cannot export entity (not found)", {"id": entity_id}
|
|
@@ -2176,7 +2353,9 @@ class OpenCTIStix2:
|
|
|
2176
2353
|
stix_objects = self.prepare_export(
|
|
2177
2354
|
self.generate_export(entity, no_custom_attributes),
|
|
2178
2355
|
mode,
|
|
2179
|
-
|
|
2356
|
+
None,
|
|
2357
|
+
main_filter,
|
|
2358
|
+
access_filter,
|
|
2180
2359
|
no_custom_attributes,
|
|
2181
2360
|
)
|
|
2182
2361
|
if stix_objects is not None:
|
|
@@ -2191,7 +2370,7 @@ class OpenCTIStix2:
|
|
|
2191
2370
|
self,
|
|
2192
2371
|
entity_type: str,
|
|
2193
2372
|
search: Dict = None,
|
|
2194
|
-
filters:
|
|
2373
|
+
filters: Dict = None,
|
|
2195
2374
|
orderBy: str = None,
|
|
2196
2375
|
orderMode: str = None,
|
|
2197
2376
|
getAll: bool = True,
|
|
@@ -2264,26 +2443,32 @@ class OpenCTIStix2:
|
|
|
2264
2443
|
self,
|
|
2265
2444
|
entity_type: str,
|
|
2266
2445
|
search: Dict = None,
|
|
2267
|
-
filters:
|
|
2446
|
+
filters: Dict = None,
|
|
2268
2447
|
order_by: str = None,
|
|
2269
2448
|
order_mode: str = None,
|
|
2270
2449
|
mode: str = "simple",
|
|
2271
|
-
|
|
2450
|
+
main_filter: Dict = None,
|
|
2451
|
+
access_filter: Dict = None,
|
|
2272
2452
|
) -> Dict:
|
|
2273
|
-
max_marking_definition_entity = (
|
|
2274
|
-
self.opencti.marking_definition.read(id=max_marking_definition)
|
|
2275
|
-
if max_marking_definition is not None
|
|
2276
|
-
else None
|
|
2277
|
-
)
|
|
2278
2453
|
bundle = {
|
|
2279
2454
|
"type": "bundle",
|
|
2280
2455
|
"id": "bundle--" + str(uuid.uuid4()),
|
|
2281
2456
|
"objects": [],
|
|
2282
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
|
+
}
|
|
2283
2468
|
entities_list = self.export_entities_list(
|
|
2284
2469
|
entity_type=entity_type,
|
|
2285
2470
|
search=search,
|
|
2286
|
-
filters=
|
|
2471
|
+
filters=export_query_filter,
|
|
2287
2472
|
orderBy=order_by,
|
|
2288
2473
|
orderMode=order_mode,
|
|
2289
2474
|
getAll=True,
|
|
@@ -2294,7 +2479,9 @@ class OpenCTIStix2:
|
|
|
2294
2479
|
entity_bundle = self.prepare_export(
|
|
2295
2480
|
self.generate_export(entity),
|
|
2296
2481
|
mode,
|
|
2297
|
-
|
|
2482
|
+
None,
|
|
2483
|
+
main_filter,
|
|
2484
|
+
access_filter,
|
|
2298
2485
|
)
|
|
2299
2486
|
if entity_bundle is not None:
|
|
2300
2487
|
entity_bundle_filtered = self.filter_objects(uuids, entity_bundle)
|
|
@@ -2307,31 +2494,44 @@ class OpenCTIStix2:
|
|
|
2307
2494
|
self,
|
|
2308
2495
|
entities_list: [str],
|
|
2309
2496
|
mode: str = "simple",
|
|
2310
|
-
|
|
2497
|
+
main_filter: Dict = None,
|
|
2498
|
+
access_filter: Dict = None,
|
|
2311
2499
|
) -> Dict:
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
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
|
|
2316
2510
|
)
|
|
2317
2511
|
bundle = {
|
|
2318
2512
|
"type": "bundle",
|
|
2319
2513
|
"id": "bundle--" + str(uuid.uuid4()),
|
|
2320
2514
|
"objects": [],
|
|
2321
2515
|
}
|
|
2516
|
+
|
|
2322
2517
|
if entities_list is not None:
|
|
2323
2518
|
uuids = []
|
|
2324
2519
|
for entity in entities_list:
|
|
2325
2520
|
entity_bundle = self.prepare_export(
|
|
2326
2521
|
self.generate_export(entity),
|
|
2327
2522
|
mode,
|
|
2328
|
-
|
|
2523
|
+
None,
|
|
2524
|
+
main_filter,
|
|
2525
|
+
access_filter,
|
|
2329
2526
|
)
|
|
2330
2527
|
if entity_bundle is not None:
|
|
2331
2528
|
entity_bundle_filtered = self.filter_objects(uuids, entity_bundle)
|
|
2332
2529
|
for x in entity_bundle_filtered:
|
|
2333
2530
|
uuids.append(x["id"])
|
|
2334
|
-
bundle["objects"] =
|
|
2531
|
+
bundle["objects"] = (
|
|
2532
|
+
bundle["objects"] + entity_bundle_filtered
|
|
2533
|
+
) # unsupported operand type(s) for +: 'dict' and 'list'
|
|
2534
|
+
|
|
2335
2535
|
return bundle
|
|
2336
2536
|
|
|
2337
2537
|
def import_bundle(
|
|
@@ -7,8 +7,11 @@ STIX_CYBER_OBSERVABLE_MAPPING = {
|
|
|
7
7
|
"directory": "Directory",
|
|
8
8
|
"domain-name": "Domain-Name",
|
|
9
9
|
"email-addr": "Email-Addr",
|
|
10
|
-
"file": "StixFile",
|
|
11
10
|
"email-message": "Email-Message",
|
|
11
|
+
"email-mime-part-type": "Email-Mime-Part-Type",
|
|
12
|
+
"artifact": "Artifact",
|
|
13
|
+
"file": "StixFile",
|
|
14
|
+
"x509-certificate": "X509-Certificate",
|
|
12
15
|
"ipv4-addr": "IPv4-Addr",
|
|
13
16
|
"ipv6-addr": "IPv6-Addr",
|
|
14
17
|
"mac-addr": "Mac-Addr",
|
|
@@ -21,8 +24,14 @@ STIX_CYBER_OBSERVABLE_MAPPING = {
|
|
|
21
24
|
"windows-registry-key": "Windows-Registry-Key",
|
|
22
25
|
"windows-registry-value-type": "Windows-Registry-Value-Type",
|
|
23
26
|
"hostname": "Hostname",
|
|
27
|
+
"cryptographic-key": "Cryptographic-Key",
|
|
28
|
+
"cryptocurrency-wallet": "Cryptocurrency-Wallet",
|
|
29
|
+
"text": "Text",
|
|
30
|
+
"user-agent": "User-Agent",
|
|
24
31
|
"bank-account": "Bank-Account",
|
|
25
32
|
"phone-number": "Phone-Number",
|
|
33
|
+
"credential": "Credential",
|
|
34
|
+
"tracking-number": "Tracking-Number",
|
|
26
35
|
"payment-card": "Payment-Card",
|
|
27
36
|
"media-content": "Media-Content",
|
|
28
37
|
}
|
|
@@ -54,6 +63,8 @@ PATTERN_MAPPING = {
|
|
|
54
63
|
"Bank-Account": ["iban"],
|
|
55
64
|
"Phone-Number": ["value"],
|
|
56
65
|
"Payment-Card": ["card_number"],
|
|
66
|
+
"Tracking-Number": ["value"],
|
|
67
|
+
"Credential": ["value"],
|
|
57
68
|
"Media-Content": ["url"],
|
|
58
69
|
}
|
|
59
70
|
|
|
@@ -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
|
|
@@ -27,14 +27,14 @@ Requires-Dist: prometheus-client ~=0.20.0
|
|
|
27
27
|
Requires-Dist: python-json-logger ~=2.0.4
|
|
28
28
|
Requires-Dist: pyyaml ~=6.0
|
|
29
29
|
Requires-Dist: requests ~=2.31.0
|
|
30
|
-
Requires-Dist: setuptools ~=69.
|
|
30
|
+
Requires-Dist: setuptools ~=69.5.1
|
|
31
31
|
Requires-Dist: filigran-sseclient ~=1.0.0
|
|
32
32
|
Requires-Dist: stix2 ~=3.0.1
|
|
33
33
|
Requires-Dist: cachetools ~=5.3.0
|
|
34
34
|
Requires-Dist: python-magic ~=0.4.27 ; sys_platform == "linux" or sys_platform == "darwin"
|
|
35
35
|
Requires-Dist: python-magic-bin ~=0.4.14 ; sys_platform == "win32"
|
|
36
36
|
Provides-Extra: dev
|
|
37
|
-
Requires-Dist: black ~=24.
|
|
37
|
+
Requires-Dist: black ~=24.4.0 ; extra == 'dev'
|
|
38
38
|
Requires-Dist: build ~=1.2.1 ; extra == 'dev'
|
|
39
39
|
Requires-Dist: isort ~=5.13.0 ; extra == 'dev'
|
|
40
40
|
Requires-Dist: types-pytz ~=2024.1.0.20240203 ; extra == 'dev'
|
|
@@ -42,12 +42,12 @@ 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
|
|
49
49
|
Requires-Dist: autoapi ~=2.0.1 ; extra == 'doc'
|
|
50
|
-
Requires-Dist: sphinx-autodoc-typehints ~=2.
|
|
50
|
+
Requires-Dist: sphinx-autodoc-typehints ~=2.1.0 ; extra == 'doc'
|
|
51
51
|
Requires-Dist: sphinx-rtd-theme ~=2.0.0 ; extra == 'doc'
|
|
52
52
|
|
|
53
53
|
# OpenCTI client for Python
|