pycti 6.2.18__py3-none-any.whl → 6.3.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 +33 -0
- pycti/connector/opencti_connector_helper.py +64 -43
- pycti/entities/opencti_stix_core_object.py +31 -0
- pycti/entities/opencti_stix_cyber_observable.py +17 -0
- pycti/entities/stix_cyber_observable/opencti_stix_cyber_observable_properties.py +8 -0
- pycti/utils/constants.py +1 -0
- pycti/utils/opencti_stix2.py +38 -55
- {pycti-6.2.18.dist-info → pycti-6.3.0.dist-info}/METADATA +1 -1
- {pycti-6.2.18.dist-info → pycti-6.3.0.dist-info}/RECORD +13 -13
- {pycti-6.2.18.dist-info → pycti-6.3.0.dist-info}/WHEEL +1 -1
- {pycti-6.2.18.dist-info → pycti-6.3.0.dist-info}/LICENSE +0 -0
- {pycti-6.2.18.dist-info → pycti-6.3.0.dist-info}/top_level.txt +0 -0
pycti/__init__.py
CHANGED
pycti/api/opencti_api_client.py
CHANGED
|
@@ -330,6 +330,7 @@ class OpenCTIApiClient:
|
|
|
330
330
|
verify=self.ssl_verify,
|
|
331
331
|
cert=self.cert,
|
|
332
332
|
proxies=self.proxies,
|
|
333
|
+
timeout=300,
|
|
333
334
|
)
|
|
334
335
|
# If no
|
|
335
336
|
else:
|
|
@@ -340,6 +341,7 @@ class OpenCTIApiClient:
|
|
|
340
341
|
verify=self.ssl_verify,
|
|
341
342
|
cert=self.cert,
|
|
342
343
|
proxies=self.proxies,
|
|
344
|
+
timeout=300,
|
|
343
345
|
)
|
|
344
346
|
# Build response
|
|
345
347
|
if r.status_code == 200:
|
|
@@ -383,6 +385,7 @@ class OpenCTIApiClient:
|
|
|
383
385
|
verify=self.ssl_verify,
|
|
384
386
|
cert=self.cert,
|
|
385
387
|
proxies=self.proxies,
|
|
388
|
+
timeout=300,
|
|
386
389
|
)
|
|
387
390
|
if binary:
|
|
388
391
|
if serialize:
|
|
@@ -700,6 +703,36 @@ class OpenCTIApiClient:
|
|
|
700
703
|
self.app_logger.error("[upload] Missing parameter: file_name")
|
|
701
704
|
return None
|
|
702
705
|
|
|
706
|
+
def send_bundle_to_api(self, **kwargs):
|
|
707
|
+
"""Push a bundle to a queue through OpenCTI API
|
|
708
|
+
|
|
709
|
+
:param `**kwargs`: arguments for bundle push (required: `connectorId` and `bundle`)
|
|
710
|
+
:return: returns the query response for the bundle push
|
|
711
|
+
:rtype: dict
|
|
712
|
+
"""
|
|
713
|
+
|
|
714
|
+
connector_id = kwargs.get("connector_id", None)
|
|
715
|
+
bundle = kwargs.get("bundle", None)
|
|
716
|
+
|
|
717
|
+
if connector_id is not None and bundle is not None:
|
|
718
|
+
self.app_logger.info(
|
|
719
|
+
"Pushing a bundle to queue through API", {connector_id}
|
|
720
|
+
)
|
|
721
|
+
mutation = """
|
|
722
|
+
mutation StixBundlePush($connectorId: String!, $bundle: String!) {
|
|
723
|
+
stixBundlePush(connectorId: $connectorId, bundle: $bundle)
|
|
724
|
+
}
|
|
725
|
+
"""
|
|
726
|
+
return self.query(
|
|
727
|
+
mutation,
|
|
728
|
+
{"connectorId": connector_id, "bundle": bundle},
|
|
729
|
+
)
|
|
730
|
+
else:
|
|
731
|
+
self.app_logger.error(
|
|
732
|
+
"[bundle push] Missing parameter: connector_id or bundle"
|
|
733
|
+
)
|
|
734
|
+
return None
|
|
735
|
+
|
|
703
736
|
def get_stix_content(self, id):
|
|
704
737
|
"""get the STIX content of any entity
|
|
705
738
|
|
|
@@ -375,6 +375,8 @@ class ListenQueue(threading.Thread):
|
|
|
375
375
|
# Connect the broker
|
|
376
376
|
self.pika_credentials = pika.PlainCredentials(self.user, self.password)
|
|
377
377
|
self.pika_parameters = pika.ConnectionParameters(
|
|
378
|
+
heartbeat=10,
|
|
379
|
+
blocked_connection_timeout=10,
|
|
378
380
|
host=self.host,
|
|
379
381
|
port=self.port,
|
|
380
382
|
virtual_host=self.vhost,
|
|
@@ -466,6 +468,7 @@ class PingAlive(threading.Thread):
|
|
|
466
468
|
"Connector state has been remotely reset",
|
|
467
469
|
{"state": self.get_state()},
|
|
468
470
|
)
|
|
471
|
+
|
|
469
472
|
if self.in_error:
|
|
470
473
|
self.in_error = False
|
|
471
474
|
self.connector_logger.info("API Ping back to normal")
|
|
@@ -668,8 +671,8 @@ class ConnectorInfo:
|
|
|
668
671
|
self,
|
|
669
672
|
run_and_terminate: bool = False,
|
|
670
673
|
buffering: bool = False,
|
|
671
|
-
queue_threshold: float = 500,
|
|
672
|
-
queue_messages_size: float = 0,
|
|
674
|
+
queue_threshold: float = 500.0,
|
|
675
|
+
queue_messages_size: float = 0.0,
|
|
673
676
|
next_run_datetime: datetime = None,
|
|
674
677
|
last_run_datetime: datetime = None,
|
|
675
678
|
):
|
|
@@ -776,6 +779,9 @@ class OpenCTIConnectorHelper: # pylint: disable=too-many-public-methods
|
|
|
776
779
|
self.connect_id = get_config_variable(
|
|
777
780
|
"CONNECTOR_ID", ["connector", "id"], config
|
|
778
781
|
)
|
|
782
|
+
self.queue_protocol = get_config_variable(
|
|
783
|
+
"QUEUE_PROTOCOL", ["connector", "queue_protocol"], config, default="amqp"
|
|
784
|
+
)
|
|
779
785
|
self.connect_type = get_config_variable(
|
|
780
786
|
"CONNECTOR_TYPE", ["connector", "type"], config
|
|
781
787
|
)
|
|
@@ -994,7 +1000,6 @@ class OpenCTIConnectorHelper: # pylint: disable=too-many-public-methods
|
|
|
994
1000
|
|
|
995
1001
|
# Start ping thread
|
|
996
1002
|
if not self.connect_run_and_terminate:
|
|
997
|
-
|
|
998
1003
|
is_run_and_terminate = False
|
|
999
1004
|
if self.connect_duration_period == 0:
|
|
1000
1005
|
is_run_and_terminate = True
|
|
@@ -1186,7 +1191,7 @@ class OpenCTIConnectorHelper: # pylint: disable=too-many-public-methods
|
|
|
1186
1191
|
connector_queue_details = connector_details["connector_queue_details"]
|
|
1187
1192
|
|
|
1188
1193
|
queue_messages_size_byte = connector_queue_details["messages_size"]
|
|
1189
|
-
queue_threshold = self.connect_queue_threshold
|
|
1194
|
+
queue_threshold = float(self.connect_queue_threshold)
|
|
1190
1195
|
|
|
1191
1196
|
# Convert queue_messages_size to Mo (decimal)
|
|
1192
1197
|
queue_messages_size_mo = queue_messages_size_byte / 1000000
|
|
@@ -1205,7 +1210,7 @@ class OpenCTIConnectorHelper: # pylint: disable=too-many-public-methods
|
|
|
1205
1210
|
self.connector_info.queue_messages_size = queue_messages_size_mo
|
|
1206
1211
|
self.connector_info.queue_threshold = queue_threshold
|
|
1207
1212
|
|
|
1208
|
-
if
|
|
1213
|
+
if queue_messages_size_mo < queue_threshold:
|
|
1209
1214
|
# Set buffering
|
|
1210
1215
|
self.connector_info.buffering = False
|
|
1211
1216
|
return False
|
|
@@ -1422,6 +1427,7 @@ class OpenCTIConnectorHelper: # pylint: disable=too-many-public-methods
|
|
|
1422
1427
|
message_callback,
|
|
1423
1428
|
)
|
|
1424
1429
|
self.listen_queue.start()
|
|
1430
|
+
self.listen_queue.join()
|
|
1425
1431
|
|
|
1426
1432
|
def listen_stream(
|
|
1427
1433
|
self,
|
|
@@ -1689,10 +1695,11 @@ class OpenCTIConnectorHelper: # pylint: disable=too-many-public-methods
|
|
|
1689
1695
|
expectations_number = len(json.loads(bundle)["objects"])
|
|
1690
1696
|
else:
|
|
1691
1697
|
stix2_splitter = OpenCTIStix2Splitter()
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1698
|
+
(
|
|
1699
|
+
expectations_number,
|
|
1700
|
+
bundles,
|
|
1701
|
+
) = stix2_splitter.split_bundle_with_expectations(
|
|
1702
|
+
bundle, True, event_version
|
|
1696
1703
|
)
|
|
1697
1704
|
|
|
1698
1705
|
if len(bundles) == 0:
|
|
@@ -1704,42 +1711,55 @@ class OpenCTIConnectorHelper: # pylint: disable=too-many-public-methods
|
|
|
1704
1711
|
self.api.work.add_expectations(work_id, expectations_number)
|
|
1705
1712
|
if entities_types is None:
|
|
1706
1713
|
entities_types = []
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1714
|
+
if self.queue_protocol == "amqp":
|
|
1715
|
+
pika_credentials = pika.PlainCredentials(
|
|
1716
|
+
self.connector_config["connection"]["user"],
|
|
1717
|
+
self.connector_config["connection"]["pass"],
|
|
1718
|
+
)
|
|
1719
|
+
pika_parameters = pika.ConnectionParameters(
|
|
1720
|
+
heartbeat=10,
|
|
1721
|
+
blocked_connection_timeout=10,
|
|
1722
|
+
host=self.connector_config["connection"]["host"],
|
|
1723
|
+
port=self.connector_config["connection"]["port"],
|
|
1724
|
+
virtual_host=self.connector_config["connection"]["vhost"],
|
|
1725
|
+
credentials=pika_credentials,
|
|
1726
|
+
ssl_options=(
|
|
1727
|
+
pika.SSLOptions(
|
|
1728
|
+
create_mq_ssl_context(self.config),
|
|
1729
|
+
self.connector_config["connection"]["host"],
|
|
1730
|
+
)
|
|
1731
|
+
if self.connector_config["connection"]["use_ssl"]
|
|
1732
|
+
else None
|
|
1733
|
+
),
|
|
1734
|
+
)
|
|
1735
|
+
pika_connection = pika.BlockingConnection(pika_parameters)
|
|
1736
|
+
channel = pika_connection.channel()
|
|
1737
|
+
try:
|
|
1738
|
+
channel.confirm_delivery()
|
|
1739
|
+
except Exception as err: # pylint: disable=broad-except
|
|
1740
|
+
self.connector_logger.warning(str(err))
|
|
1741
|
+
self.connector_logger.info(
|
|
1742
|
+
self.connect_name + " sending bundle to queue"
|
|
1743
|
+
)
|
|
1744
|
+
for sequence, bundle in enumerate(bundles, start=1):
|
|
1745
|
+
self._send_bundle(
|
|
1746
|
+
channel,
|
|
1747
|
+
bundle,
|
|
1748
|
+
work_id=work_id,
|
|
1749
|
+
entities_types=entities_types,
|
|
1750
|
+
sequence=sequence,
|
|
1751
|
+
update=update,
|
|
1720
1752
|
)
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
self.connector_logger.warning(str(err))
|
|
1731
|
-
self.connector_logger.info(self.connect_name + " sending bundle to queue")
|
|
1732
|
-
for sequence, bundle in enumerate(bundles, start=1):
|
|
1733
|
-
self._send_bundle(
|
|
1734
|
-
channel,
|
|
1735
|
-
bundle,
|
|
1736
|
-
work_id=work_id,
|
|
1737
|
-
entities_types=entities_types,
|
|
1738
|
-
sequence=sequence,
|
|
1739
|
-
update=update,
|
|
1753
|
+
channel.close()
|
|
1754
|
+
pika_connection.close()
|
|
1755
|
+
elif self.queue_protocol == "api":
|
|
1756
|
+
self.api.send_bundle_to_api(
|
|
1757
|
+
connector_id=self.connector_id, bundle=bundle
|
|
1758
|
+
)
|
|
1759
|
+
else:
|
|
1760
|
+
raise ValueError(
|
|
1761
|
+
f"{self.queue_protocol}: this queue protocol is not supported"
|
|
1740
1762
|
)
|
|
1741
|
-
channel.close()
|
|
1742
|
-
pika_connection.close()
|
|
1743
1763
|
|
|
1744
1764
|
return bundles
|
|
1745
1765
|
|
|
@@ -1799,6 +1819,7 @@ class OpenCTIConnectorHelper: # pylint: disable=too-many-public-methods
|
|
|
1799
1819
|
except (UnroutableError, NackError):
|
|
1800
1820
|
self.connector_logger.error("Unable to send bundle, retry...")
|
|
1801
1821
|
self.metric.inc("error_count")
|
|
1822
|
+
time.sleep(10)
|
|
1802
1823
|
self._send_bundle(channel, bundle, **kwargs)
|
|
1803
1824
|
|
|
1804
1825
|
def stix2_get_embedded_objects(self, item) -> Dict:
|
|
@@ -639,6 +639,10 @@ class StixCoreObject:
|
|
|
639
639
|
cvv
|
|
640
640
|
holder_name
|
|
641
641
|
}
|
|
642
|
+
... on Persona {
|
|
643
|
+
persona_name
|
|
644
|
+
persona_type
|
|
645
|
+
}
|
|
642
646
|
... on MediaContent {
|
|
643
647
|
title
|
|
644
648
|
content_alt: content
|
|
@@ -1300,6 +1304,10 @@ class StixCoreObject:
|
|
|
1300
1304
|
cvv
|
|
1301
1305
|
holder_name
|
|
1302
1306
|
}
|
|
1307
|
+
... on Persona {
|
|
1308
|
+
persona_name
|
|
1309
|
+
persona_type
|
|
1310
|
+
}
|
|
1303
1311
|
... on MediaContent {
|
|
1304
1312
|
title
|
|
1305
1313
|
content_alt: content
|
|
@@ -1673,3 +1681,26 @@ class StixCoreObject:
|
|
|
1673
1681
|
else:
|
|
1674
1682
|
self.opencti.app_logger.error("Missing parameters: id")
|
|
1675
1683
|
return None
|
|
1684
|
+
|
|
1685
|
+
"""
|
|
1686
|
+
Delete a Stix-Core-Object object
|
|
1687
|
+
|
|
1688
|
+
:param id: the Stix-Core-Object id
|
|
1689
|
+
:return void
|
|
1690
|
+
"""
|
|
1691
|
+
|
|
1692
|
+
def delete(self, **kwargs):
|
|
1693
|
+
id = kwargs.get("id", None)
|
|
1694
|
+
if id is not None:
|
|
1695
|
+
self.opencti.app_logger.info("Deleting stix_core_object", {"id": id})
|
|
1696
|
+
query = """
|
|
1697
|
+
mutation StixCoreObjectEdit($id: ID!) {
|
|
1698
|
+
stixCoreObjectEdit(id: $id) {
|
|
1699
|
+
delete
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
"""
|
|
1703
|
+
self.opencti.query(query, {"id": id})
|
|
1704
|
+
else:
|
|
1705
|
+
self.opencti.app_logger.error("[stix_core_object] Missing parameters: id")
|
|
1706
|
+
return None
|
|
@@ -275,6 +275,8 @@ class StixCyberObservable(StixCyberObservableDeprecatedMixin):
|
|
|
275
275
|
type = "IPv4-Addr"
|
|
276
276
|
elif type.lower() == "ipv6-addr":
|
|
277
277
|
type = "IPv6-Addr"
|
|
278
|
+
elif type.lower() == "persona":
|
|
279
|
+
type = "Persona"
|
|
278
280
|
elif type.lower() == "hostname" or type.lower() == "x-opencti-hostname":
|
|
279
281
|
type = "Hostname"
|
|
280
282
|
elif type.lower() == "payment-card" or type.lower() == "x-opencti-payment-card":
|
|
@@ -406,6 +408,7 @@ class StixCyberObservable(StixCyberObservableDeprecatedMixin):
|
|
|
406
408
|
$Credential: CredentialAddInput
|
|
407
409
|
$TrackingNumber: TrackingNumberAddInput
|
|
408
410
|
$PaymentCard: PaymentCardAddInput
|
|
411
|
+
$Persona: PersonaAddInput
|
|
409
412
|
$MediaContent: MediaContentAddInput
|
|
410
413
|
) {
|
|
411
414
|
stixCyberObservableAdd(
|
|
@@ -450,6 +453,7 @@ class StixCyberObservable(StixCyberObservableDeprecatedMixin):
|
|
|
450
453
|
Credential: $Credential
|
|
451
454
|
TrackingNumber: $TrackingNumber
|
|
452
455
|
PaymentCard: $PaymentCard
|
|
456
|
+
Persona: $Persona
|
|
453
457
|
MediaContent: $MediaContent
|
|
454
458
|
) {
|
|
455
459
|
id
|
|
@@ -1012,6 +1016,19 @@ class StixCyberObservable(StixCyberObservableDeprecatedMixin):
|
|
|
1012
1016
|
else None
|
|
1013
1017
|
),
|
|
1014
1018
|
}
|
|
1019
|
+
elif type == "Persona":
|
|
1020
|
+
input_variables["Persona"] = {
|
|
1021
|
+
"persona_name": (
|
|
1022
|
+
observable_data["persona_name"]
|
|
1023
|
+
if "persona_name" in observable_data
|
|
1024
|
+
else None
|
|
1025
|
+
),
|
|
1026
|
+
"persona_type": (
|
|
1027
|
+
observable_data["persona_type"]
|
|
1028
|
+
if "persona_type" in observable_data
|
|
1029
|
+
else None
|
|
1030
|
+
),
|
|
1031
|
+
}
|
|
1015
1032
|
elif type == "Payment-Card" or type.lower() == "x-opencti-payment-card":
|
|
1016
1033
|
input_variables["PaymentCard"] = {
|
|
1017
1034
|
"card_number": (
|
|
@@ -281,6 +281,10 @@ SCO_PROPERTIES = """
|
|
|
281
281
|
cvv
|
|
282
282
|
holder_name
|
|
283
283
|
}
|
|
284
|
+
... on Persona {
|
|
285
|
+
persona_name
|
|
286
|
+
persona_type
|
|
287
|
+
}
|
|
284
288
|
... on MediaContent {
|
|
285
289
|
title
|
|
286
290
|
content
|
|
@@ -581,6 +585,10 @@ SCO_PROPERTIES_WITH_FILES = """
|
|
|
581
585
|
cvv
|
|
582
586
|
holder_name
|
|
583
587
|
}
|
|
588
|
+
... on Persona {
|
|
589
|
+
persona_name
|
|
590
|
+
persona_type
|
|
591
|
+
}
|
|
584
592
|
... on MediaContent {
|
|
585
593
|
title
|
|
586
594
|
content
|
pycti/utils/constants.py
CHANGED
pycti/utils/opencti_stix2.py
CHANGED
|
@@ -40,6 +40,7 @@ SPEC_VERSION = "2.1"
|
|
|
40
40
|
ERROR_TYPE_LOCK = "LOCK_ERROR"
|
|
41
41
|
ERROR_TYPE_MISSING_REFERENCE = "MISSING_REFERENCE_ERROR"
|
|
42
42
|
ERROR_TYPE_BAD_GATEWAY = "Bad Gateway"
|
|
43
|
+
ERROR_TYPE_TIMEOUT = "Request timed out"
|
|
43
44
|
|
|
44
45
|
# Extensions
|
|
45
46
|
STIX_EXT_OCTI = "extension-definition--ea279b3e-5c71-4632-ac08-831c66a786ba"
|
|
@@ -64,6 +65,10 @@ bundles_bad_gateway_error_counter = meter.create_counter(
|
|
|
64
65
|
name="opencti_bundles_bad_gateway_error_counter",
|
|
65
66
|
description="number of bundles in bad gateway error",
|
|
66
67
|
)
|
|
68
|
+
bundles_timed_out_error_counter = meter.create_counter(
|
|
69
|
+
name="opencti_bundles_timed_out_error_counter",
|
|
70
|
+
description="number of bundles in timed out error",
|
|
71
|
+
)
|
|
67
72
|
bundles_technical_error_counter = meter.create_counter(
|
|
68
73
|
name="opencti_bundles_technical_error_counter",
|
|
69
74
|
description="number of bundles in technical error",
|
|
@@ -1310,37 +1315,6 @@ class OpenCTIStix2:
|
|
|
1310
1315
|
|
|
1311
1316
|
# Create the sighting
|
|
1312
1317
|
|
|
1313
|
-
### Get the FROM
|
|
1314
|
-
if from_id in self.mapping_cache:
|
|
1315
|
-
final_from_id = self.mapping_cache[from_id]["id"]
|
|
1316
|
-
else:
|
|
1317
|
-
stix_object_result = (
|
|
1318
|
-
self.opencti.opencti_stix_object_or_stix_relationship.read(id=from_id)
|
|
1319
|
-
)
|
|
1320
|
-
if stix_object_result is not None:
|
|
1321
|
-
final_from_id = stix_object_result["id"]
|
|
1322
|
-
else:
|
|
1323
|
-
self.opencti.app_logger.error(
|
|
1324
|
-
"From ref of the sighting not found, doing nothing..."
|
|
1325
|
-
)
|
|
1326
|
-
return None
|
|
1327
|
-
|
|
1328
|
-
### Get the TO
|
|
1329
|
-
final_to_id = None
|
|
1330
|
-
if to_id:
|
|
1331
|
-
if to_id in self.mapping_cache:
|
|
1332
|
-
final_to_id = self.mapping_cache[to_id]["id"]
|
|
1333
|
-
else:
|
|
1334
|
-
stix_object_result = (
|
|
1335
|
-
self.opencti.opencti_stix_object_or_stix_relationship.read(id=to_id)
|
|
1336
|
-
)
|
|
1337
|
-
if stix_object_result is not None:
|
|
1338
|
-
final_to_id = stix_object_result["id"]
|
|
1339
|
-
else:
|
|
1340
|
-
self.opencti.app_logger.error(
|
|
1341
|
-
"To ref of the sighting not found, doing nothing..."
|
|
1342
|
-
)
|
|
1343
|
-
return None
|
|
1344
1318
|
if (
|
|
1345
1319
|
"x_opencti_negative" not in stix_sighting
|
|
1346
1320
|
and self.opencti.get_attribute_in_extension("negative", stix_sighting)
|
|
@@ -1354,8 +1328,8 @@ class OpenCTIStix2:
|
|
|
1354
1328
|
self.opencti.get_attribute_in_extension("workflow_id", stix_sighting)
|
|
1355
1329
|
)
|
|
1356
1330
|
stix_sighting_result = self.opencti.stix_sighting_relationship.create(
|
|
1357
|
-
fromId=
|
|
1358
|
-
toId=
|
|
1331
|
+
fromId=from_id,
|
|
1332
|
+
toId=to_id,
|
|
1359
1333
|
stix_id=stix_sighting["id"] if "id" in stix_sighting else None,
|
|
1360
1334
|
description=(
|
|
1361
1335
|
self.convert_markdown(stix_sighting["description"])
|
|
@@ -2420,39 +2394,36 @@ class OpenCTIStix2:
|
|
|
2420
2394
|
# Import relationship
|
|
2421
2395
|
self.import_relationship(item, update, types)
|
|
2422
2396
|
elif item["type"] == "sighting":
|
|
2423
|
-
# Resolve the to
|
|
2397
|
+
# region Resolve the to
|
|
2424
2398
|
to_ids = []
|
|
2425
|
-
if "
|
|
2399
|
+
if "x_opencti_where_sighted_refs" in item:
|
|
2400
|
+
for where_sighted_ref in item["_opencti_where_sighted_refs"]:
|
|
2401
|
+
to_ids.append(where_sighted_ref)
|
|
2402
|
+
elif "where_sighted_refs" in item:
|
|
2426
2403
|
for where_sighted_ref in item["where_sighted_refs"]:
|
|
2427
2404
|
to_ids.append(where_sighted_ref)
|
|
2428
|
-
#
|
|
2405
|
+
# endregion
|
|
2406
|
+
# region Resolve the from
|
|
2407
|
+
from_id = None
|
|
2429
2408
|
if "x_opencti_sighting_of_ref" in item:
|
|
2430
2409
|
from_id = item["x_opencti_sighting_of_ref"]
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
):
|
|
2438
|
-
from_id = self.opencti.get_attribute_in_extension(
|
|
2439
|
-
"sighting_of_ref", item
|
|
2440
|
-
)
|
|
2441
|
-
if len(to_ids) > 0:
|
|
2410
|
+
elif "sighting_of_ref" in item:
|
|
2411
|
+
from_id = item["sighting_of_ref"]
|
|
2412
|
+
# endregion
|
|
2413
|
+
# region create the sightings
|
|
2414
|
+
if len(to_ids) > 0:
|
|
2415
|
+
if from_id:
|
|
2442
2416
|
for to_id in to_ids:
|
|
2443
2417
|
self.import_sighting(item, from_id, to_id, update)
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
self.import_sighting(item, from_id, to_id, update)
|
|
2448
|
-
# Import observed_data_refs
|
|
2449
|
-
if "observed_data_refs" in item:
|
|
2450
|
-
for observed_data_ref in item["observed_data_refs"]:
|
|
2451
|
-
if len(to_ids) > 0:
|
|
2418
|
+
# Import observed_data_refs
|
|
2419
|
+
if "observed_data_refs" in item:
|
|
2420
|
+
for observed_data_ref in item["observed_data_refs"]:
|
|
2452
2421
|
for to_id in to_ids:
|
|
2453
2422
|
self.import_sighting(
|
|
2454
2423
|
item, observed_data_ref, to_id, update
|
|
2455
2424
|
)
|
|
2425
|
+
# endregion
|
|
2426
|
+
|
|
2456
2427
|
elif item["type"] == "label":
|
|
2457
2428
|
stix_ids = self.opencti.get_attribute_in_extension("stix_ids", item)
|
|
2458
2429
|
self.opencti.label.create(
|
|
@@ -2595,6 +2566,18 @@ class OpenCTIStix2:
|
|
|
2595
2566
|
return self.import_item(
|
|
2596
2567
|
item, update, types, processing_count + 1, work_id
|
|
2597
2568
|
)
|
|
2569
|
+
# Request timeout error occurs
|
|
2570
|
+
elif ERROR_TYPE_TIMEOUT in error_msg:
|
|
2571
|
+
worker_logger.error("A connection error occurred")
|
|
2572
|
+
worker_logger.info(
|
|
2573
|
+
"Message reprocess for request timed out",
|
|
2574
|
+
{"count": processing_count},
|
|
2575
|
+
)
|
|
2576
|
+
bundles_timed_out_error_counter.add(1)
|
|
2577
|
+
time.sleep(60)
|
|
2578
|
+
return self.import_item(
|
|
2579
|
+
item, update, types, processing_count + 1, work_id
|
|
2580
|
+
)
|
|
2598
2581
|
# Platform does not know what to do and raises an error:
|
|
2599
2582
|
# That also works for missing reference with too much execution
|
|
2600
2583
|
else:
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
pycti/__init__.py,sha256=
|
|
1
|
+
pycti/__init__.py,sha256=fgdgvN6RAYMan3BD5R61Xtkq0QzLc4bpDVgjw7qVPFg,5218
|
|
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=WpJs3GtEO0kV29KXmKY-2JmtiL6JSPD-746-FbnIcik,31027
|
|
4
4
|
pycti/api/opencti_api_connector.py,sha256=ubM_zPjTD8L33TEugCQgf_YF9zugDFg_7FgNubGlwJw,5447
|
|
5
5
|
pycti/api/opencti_api_playbook.py,sha256=456We78vESukfSOi_CctfZ9dbBJEi76EHClRc2f21Js,1628
|
|
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=5oVvS27KWhzRiofJAeQPDtba-EP83FziSistyEd5l-U,2561
|
|
9
|
-
pycti/connector/opencti_connector_helper.py,sha256=
|
|
9
|
+
pycti/connector/opencti_connector_helper.py,sha256=AVrVT-DVfPz3mL6fYtURo4hYMYB8MDOjlbNpx2gd9hY,79261
|
|
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=AP_lTsHk0NscvFsXdxjzXWLCpg0ZaHTUT-Yg2JyB4YU,22047
|
|
@@ -40,9 +40,9 @@ pycti/entities/opencti_observed_data.py,sha256=123sp3_Xbu1HVZW5-5_Tu8DYo_wBf6RVG
|
|
|
40
40
|
pycti/entities/opencti_opinion.py,sha256=SPcY8-0zRJCMle-eDLka-CFPyAqU3CnVVBtfVYhzyJE,21837
|
|
41
41
|
pycti/entities/opencti_report.py,sha256=y-in19XqQ1BN0MZjKfxiOWe_0Q4Wakrj2MLrqzFpokU,35224
|
|
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=Lc0-lytsEjQRWD9VkVTHPrWPgqOzqT99qwndOQIRYCw,51683
|
|
44
44
|
pycti/entities/opencti_stix_core_relationship.py,sha256=ldhS0rJ9L6LrY1wvX28f9TMpVD1rVxsK-GYhH06qJFo,43944
|
|
45
|
-
pycti/entities/opencti_stix_cyber_observable.py,sha256=
|
|
45
|
+
pycti/entities/opencti_stix_cyber_observable.py,sha256=JAo2xBwPfAznX4e2Cv1y8vKVBKpkFpG2D22yTMNKWk4,91932
|
|
46
46
|
pycti/entities/opencti_stix_domain_object.py,sha256=XAwPHe9tUjtGRZLu6BNdotXxYYjf5_AFIkHLeu6NzFo,78732
|
|
47
47
|
pycti/entities/opencti_stix_nested_ref_relationship.py,sha256=eGCF7yaEDqMsJbgvTDle0tVzRCF78CmEhE02jioUTCc,12605
|
|
48
48
|
pycti/entities/opencti_stix_object_or_stix_relationship.py,sha256=5qutzML6SyYzDhZ-QpI9Vh23hzLEs-xeFAAZOpGHZ2g,18049
|
|
@@ -58,16 +58,16 @@ pycti/entities/indicator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
58
58
|
pycti/entities/indicator/opencti_indicator_properties.py,sha256=2HJiBkBzbLe75Yu5AeSrTZCSKikPwwM_DeDgJCl7wm4,4953
|
|
59
59
|
pycti/entities/stix_cyber_observable/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
60
60
|
pycti/entities/stix_cyber_observable/opencti_stix_cyber_observable_deprecated.py,sha256=BH65h6xBz7naG61t5nvBdhnGYnobNuiUZf8CJC4-nnc,1847
|
|
61
|
-
pycti/entities/stix_cyber_observable/opencti_stix_cyber_observable_properties.py,sha256=
|
|
61
|
+
pycti/entities/stix_cyber_observable/opencti_stix_cyber_observable_properties.py,sha256=MN56CW8RWZwB0Pr8UiHZy_4nSzbgFbwdhSFKpsZ_d1Y,11293
|
|
62
62
|
pycti/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
63
|
-
pycti/utils/constants.py,sha256=
|
|
63
|
+
pycti/utils/constants.py,sha256=ZgOVxY5bnrHiNvPgOfZLWk16sSDnaE_tg8JVjZpw24Q,11831
|
|
64
64
|
pycti/utils/opencti_logger.py,sha256=0dvB75V0SuPFGxL539dAQrxTt1N5Acx0A3Ogwl5WMJ8,2199
|
|
65
|
-
pycti/utils/opencti_stix2.py,sha256=
|
|
65
|
+
pycti/utils/opencti_stix2.py,sha256=pYPvDJRkd9gTkC3__FYapxcSZdrAbRY-aSqDd0oKgUw,116521
|
|
66
66
|
pycti/utils/opencti_stix2_splitter.py,sha256=A2GqoiFzEga8hslgA3mm4FDoObFsWgx4zK4DdcWTguc,4907
|
|
67
67
|
pycti/utils/opencti_stix2_update.py,sha256=CnMyqkeVA0jgyxEcgqna8sABU4YPMjkEJ228GVurIn4,14658
|
|
68
68
|
pycti/utils/opencti_stix2_utils.py,sha256=4r9qglN3AIN8JH1B9Ts2o20Qn3K203M4c5-lIPzRpZ4,4138
|
|
69
|
-
pycti-6.
|
|
70
|
-
pycti-6.
|
|
71
|
-
pycti-6.
|
|
72
|
-
pycti-6.
|
|
73
|
-
pycti-6.
|
|
69
|
+
pycti-6.3.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
70
|
+
pycti-6.3.0.dist-info/METADATA,sha256=17jAjLMFaCKuHZ-zvBherP032tMq7dhUL5ez4rUHbO0,5418
|
|
71
|
+
pycti-6.3.0.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
72
|
+
pycti-6.3.0.dist-info/top_level.txt,sha256=cqEpxitAhHP4VgSA6xmrak6Yk9MeBkwoMTB6k7d2ZnE,6
|
|
73
|
+
pycti-6.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|