pycti 6.6.17__tar.gz → 6.7.0__tar.gz
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-6.6.17 → pycti-6.7.0}/PKG-INFO +4 -4
- {pycti-6.6.17 → pycti-6.7.0}/pycti/__init__.py +1 -1
- {pycti-6.6.17 → pycti-6.7.0}/pycti/api/opencti_api_client.py +12 -0
- pycti-6.7.0/pycti/api/opencti_api_draft.py +19 -0
- pycti-6.7.0/pycti/api/opencti_api_notification.py +39 -0
- pycti-6.7.0/pycti/api/opencti_api_pir.py +37 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/api/opencti_api_playbook.py +20 -0
- pycti-6.7.0/pycti/api/opencti_api_public_dashboard.py +25 -0
- pycti-6.7.0/pycti/api/opencti_api_trash.py +42 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/api/opencti_api_work.py +19 -0
- pycti-6.7.0/pycti/api/opencti_api_workspace.py +24 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/connector/opencti_connector_helper.py +7 -8
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_group.py +7 -1
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_identity.py +59 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_indicator.py +37 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_stix.py +4 -3
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_stix_core_object.py +327 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_stix_core_relationship.py +83 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_stix_domain_object.py +80 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_stix_object_or_stix_relationship.py +40 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_stix_sighting_relationship.py +81 -0
- pycti-6.7.0/pycti/entities/opencti_vulnerability.py +1162 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/utils/constants.py +2 -1
- {pycti-6.6.17 → pycti-6.7.0}/pycti/utils/opencti_stix2.py +212 -13
- {pycti-6.6.17 → pycti-6.7.0}/pycti/utils/opencti_stix2_splitter.py +12 -6
- {pycti-6.6.17 → pycti-6.7.0}/pycti/utils/opencti_stix2_utils.py +31 -4
- {pycti-6.6.17 → pycti-6.7.0}/pycti.egg-info/PKG-INFO +4 -4
- {pycti-6.6.17 → pycti-6.7.0}/pycti.egg-info/SOURCES.txt +6 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti.egg-info/requires.txt +3 -3
- {pycti-6.6.17 → pycti-6.7.0}/setup.cfg +3 -3
- pycti-6.6.17/pycti/entities/opencti_vulnerability.py +0 -575
- {pycti-6.6.17 → pycti-6.7.0}/LICENSE +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/README.md +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/api/__init__.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/api/opencti_api_connector.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/connector/__init__.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/connector/opencti_connector.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/connector/opencti_metric_handler.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/__init__.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/indicator/__init__.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/indicator/opencti_indicator_properties.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_attack_pattern.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_campaign.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_capability.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_case_incident.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_case_rfi.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_case_rft.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_channel.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_course_of_action.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_data_component.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_data_source.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_event.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_external_reference.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_feedback.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_grouping.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_incident.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_infrastructure.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_intrusion_set.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_kill_chain_phase.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_label.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_language.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_location.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_malware.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_malware_analysis.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_marking_definition.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_narrative.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_note.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_observed_data.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_opinion.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_report.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_role.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_settings.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_stix_cyber_observable.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_stix_nested_ref_relationship.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_task.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_threat_actor.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_threat_actor_group.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_threat_actor_individual.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_tool.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_user.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/opencti_vocabulary.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/stix_cyber_observable/__init__.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/stix_cyber_observable/opencti_stix_cyber_observable_deprecated.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/entities/stix_cyber_observable/opencti_stix_cyber_observable_properties.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/utils/__init__.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/utils/opencti_logger.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/utils/opencti_stix2_identifier.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti/utils/opencti_stix2_update.py +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti.egg-info/dependency_links.txt +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pycti.egg-info/top_level.txt +0 -0
- {pycti-6.6.17 → pycti-6.7.0}/pyproject.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pycti
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.7.0
|
|
4
4
|
Summary: Python API client for OpenCTI.
|
|
5
5
|
Home-page: https://github.com/OpenCTI-Platform/client-python
|
|
6
6
|
Author: Filigran
|
|
@@ -29,7 +29,7 @@ Requires-Dist: python-magic-bin~=0.4.14; sys_platform == "win32"
|
|
|
29
29
|
Requires-Dist: python_json_logger~=3.3.0
|
|
30
30
|
Requires-Dist: PyYAML~=6.0
|
|
31
31
|
Requires-Dist: requests~=2.32.3
|
|
32
|
-
Requires-Dist: setuptools~=
|
|
32
|
+
Requires-Dist: setuptools~=80.9.0
|
|
33
33
|
Requires-Dist: cachetools~=5.5.0
|
|
34
34
|
Requires-Dist: prometheus-client~=0.21.1
|
|
35
35
|
Requires-Dist: opentelemetry-api~=1.32.0
|
|
@@ -46,9 +46,9 @@ Requires-Dist: isort~=6.0.0; extra == "dev"
|
|
|
46
46
|
Requires-Dist: types-pytz~=2025.2.0.20250326; extra == "dev"
|
|
47
47
|
Requires-Dist: pre-commit~=4.2.0; extra == "dev"
|
|
48
48
|
Requires-Dist: pytest-cases~=3.8.0; extra == "dev"
|
|
49
|
-
Requires-Dist: pytest-cov~=6.
|
|
49
|
+
Requires-Dist: pytest-cov~=6.2.1; extra == "dev"
|
|
50
50
|
Requires-Dist: pytest_randomly~=3.16.0; extra == "dev"
|
|
51
|
-
Requires-Dist: pytest~=8.
|
|
51
|
+
Requires-Dist: pytest~=8.4.1; extra == "dev"
|
|
52
52
|
Requires-Dist: types-python-dateutil~=2.9.0; extra == "dev"
|
|
53
53
|
Requires-Dist: wheel~=0.45.1; extra == "dev"
|
|
54
54
|
Provides-Extra: doc
|
|
@@ -10,8 +10,14 @@ import requests
|
|
|
10
10
|
|
|
11
11
|
from pycti import __version__
|
|
12
12
|
from pycti.api.opencti_api_connector import OpenCTIApiConnector
|
|
13
|
+
from pycti.api.opencti_api_draft import OpenCTIApiDraft
|
|
14
|
+
from pycti.api.opencti_api_notification import OpenCTIApiNotification
|
|
15
|
+
from pycti.api.opencti_api_pir import OpenCTIApiPir
|
|
13
16
|
from pycti.api.opencti_api_playbook import OpenCTIApiPlaybook
|
|
17
|
+
from pycti.api.opencti_api_public_dashboard import OpenCTIApiPublicDashboard
|
|
18
|
+
from pycti.api.opencti_api_trash import OpenCTIApiTrash
|
|
14
19
|
from pycti.api.opencti_api_work import OpenCTIApiWork
|
|
20
|
+
from pycti.api.opencti_api_workspace import OpenCTIApiWorkspace
|
|
15
21
|
from pycti.entities.opencti_attack_pattern import AttackPattern
|
|
16
22
|
from pycti.entities.opencti_campaign import Campaign
|
|
17
23
|
from pycti.entities.opencti_capability import Capability
|
|
@@ -167,9 +173,15 @@ class OpenCTIApiClient:
|
|
|
167
173
|
self.session = requests.session()
|
|
168
174
|
# Define the dependencies
|
|
169
175
|
self.work = OpenCTIApiWork(self)
|
|
176
|
+
self.notification = OpenCTIApiNotification(self)
|
|
177
|
+
self.trash = OpenCTIApiTrash(self)
|
|
178
|
+
self.draft = OpenCTIApiDraft(self)
|
|
179
|
+
self.workspace = OpenCTIApiWorkspace(self)
|
|
180
|
+
self.public_dashboard = OpenCTIApiPublicDashboard(self)
|
|
170
181
|
self.playbook = OpenCTIApiPlaybook(self)
|
|
171
182
|
self.connector = OpenCTIApiConnector(self)
|
|
172
183
|
self.stix2 = OpenCTIStix2(self)
|
|
184
|
+
self.pir = OpenCTIApiPir(self)
|
|
173
185
|
|
|
174
186
|
# Define the entities
|
|
175
187
|
self.vocabulary = Vocabulary(self)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class OpenCTIApiDraft:
|
|
2
|
+
"""OpenCTIApiDraft"""
|
|
3
|
+
|
|
4
|
+
def __init__(self, api):
|
|
5
|
+
self.api = api
|
|
6
|
+
|
|
7
|
+
def delete(self, **kwargs):
|
|
8
|
+
id = kwargs.get("id", None)
|
|
9
|
+
query = """
|
|
10
|
+
mutation DraftWorkspaceDelete($id: ID!) {
|
|
11
|
+
draftWorkspaceDelete(id: $id)
|
|
12
|
+
}
|
|
13
|
+
"""
|
|
14
|
+
self.api.query(
|
|
15
|
+
query,
|
|
16
|
+
{
|
|
17
|
+
"id": id,
|
|
18
|
+
},
|
|
19
|
+
)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
class OpenCTIApiNotification:
|
|
2
|
+
"""OpenCTIApiJob"""
|
|
3
|
+
|
|
4
|
+
def __init__(self, api):
|
|
5
|
+
self.api = api
|
|
6
|
+
|
|
7
|
+
def delete(self, **kwargs):
|
|
8
|
+
notification_id = kwargs.get("id", None)
|
|
9
|
+
self.api.app_logger.info(
|
|
10
|
+
"Deleting notifcation", {"notification_id": notification_id}
|
|
11
|
+
)
|
|
12
|
+
query = """
|
|
13
|
+
mutation notificationDelete($id: ID!) {
|
|
14
|
+
notificationDelete(id: $id)
|
|
15
|
+
}
|
|
16
|
+
"""
|
|
17
|
+
self.api.query(query, {"id": notification_id})
|
|
18
|
+
|
|
19
|
+
def update_field(self, **kwargs):
|
|
20
|
+
notification_id = kwargs.get("id", None)
|
|
21
|
+
input = kwargs.get("input", None)
|
|
22
|
+
for input_value in input:
|
|
23
|
+
if input_value["key"] == "is_read":
|
|
24
|
+
is_read_value = bool(input_value["value"][0])
|
|
25
|
+
self.mark_as_read(notification_id, is_read_value)
|
|
26
|
+
|
|
27
|
+
def mark_as_read(self, notification_id: str, read: bool):
|
|
28
|
+
self.api.app_logger.info(
|
|
29
|
+
"Marking notifcation as read",
|
|
30
|
+
{"notification_id": notification_id, "read": read},
|
|
31
|
+
)
|
|
32
|
+
query = """
|
|
33
|
+
mutation notificationMarkRead($id: ID!, $read: Boolean!) {
|
|
34
|
+
notificationMarkRead(id: $id, read: $read) {
|
|
35
|
+
id
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
"""
|
|
39
|
+
self.api.query(query, {"id": notification_id, "read": read})
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
class OpenCTIApiPir:
|
|
2
|
+
"""OpenCTIApiPir"""
|
|
3
|
+
|
|
4
|
+
def __init__(self, api):
|
|
5
|
+
self.api = api
|
|
6
|
+
|
|
7
|
+
def pir_flag_element(self, **kwargs):
|
|
8
|
+
id = kwargs.get("id", None)
|
|
9
|
+
input = kwargs.get("input", None)
|
|
10
|
+
query = """
|
|
11
|
+
mutation PirFlagElement($id: ID!, $input: PirFlagElementInput!) {
|
|
12
|
+
pirFlagElement(id: $id, input: $input)
|
|
13
|
+
}
|
|
14
|
+
"""
|
|
15
|
+
self.api.query(
|
|
16
|
+
query,
|
|
17
|
+
{
|
|
18
|
+
"id": id,
|
|
19
|
+
"input": input,
|
|
20
|
+
},
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
def pir_unflag_element(self, **kwargs):
|
|
24
|
+
id = kwargs.get("id", None)
|
|
25
|
+
input = kwargs.get("input", None)
|
|
26
|
+
query = """
|
|
27
|
+
mutation PirUnflagElement($id: ID!, $input: PirUnflagElementInput!) {
|
|
28
|
+
pirUnflagElement(id: $id, input: $input)
|
|
29
|
+
}
|
|
30
|
+
"""
|
|
31
|
+
self.api.query(
|
|
32
|
+
query,
|
|
33
|
+
{
|
|
34
|
+
"id": id,
|
|
35
|
+
"input": input,
|
|
36
|
+
},
|
|
37
|
+
)
|
|
@@ -32,3 +32,23 @@ class OpenCTIApiPlaybook:
|
|
|
32
32
|
"bundle": bundle,
|
|
33
33
|
},
|
|
34
34
|
)
|
|
35
|
+
|
|
36
|
+
def delete(self, **kwargs):
|
|
37
|
+
id = kwargs.get("id", None)
|
|
38
|
+
if id is not None:
|
|
39
|
+
query = """
|
|
40
|
+
mutation PlaybookDelete($id: ID!) {
|
|
41
|
+
playbookDelete(id: $id)
|
|
42
|
+
}
|
|
43
|
+
"""
|
|
44
|
+
self.api.query(
|
|
45
|
+
query,
|
|
46
|
+
{
|
|
47
|
+
"id": id,
|
|
48
|
+
},
|
|
49
|
+
)
|
|
50
|
+
else:
|
|
51
|
+
self.opencti.app_logger.error(
|
|
52
|
+
"[stix_playbook] Cant delete playbook, missing parameters: id"
|
|
53
|
+
)
|
|
54
|
+
return None
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
class OpenCTIApiPublicDashboard:
|
|
2
|
+
"""OpenCTIApiPublicDashboard"""
|
|
3
|
+
|
|
4
|
+
def __init__(self, api):
|
|
5
|
+
self.api = api
|
|
6
|
+
|
|
7
|
+
def delete(self, **kwargs):
|
|
8
|
+
id = kwargs.get("id", None)
|
|
9
|
+
if id is not None:
|
|
10
|
+
query = """
|
|
11
|
+
mutation PublicDashboardDelete($id: ID!) {
|
|
12
|
+
publicDashboardDelete(id: $id)
|
|
13
|
+
}
|
|
14
|
+
"""
|
|
15
|
+
self.api.query(
|
|
16
|
+
query,
|
|
17
|
+
{
|
|
18
|
+
"id": id,
|
|
19
|
+
},
|
|
20
|
+
)
|
|
21
|
+
else:
|
|
22
|
+
self.opencti.app_logger.error(
|
|
23
|
+
"[stix_public_dashboard] Cant delete public dashboard, missing parameters: id"
|
|
24
|
+
)
|
|
25
|
+
return None
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
class OpenCTIApiTrash:
|
|
2
|
+
"""OpenCTIApiTrash"""
|
|
3
|
+
|
|
4
|
+
def __init__(self, api):
|
|
5
|
+
self.api = api
|
|
6
|
+
|
|
7
|
+
def restore(self, operation_id: str):
|
|
8
|
+
query = """
|
|
9
|
+
mutation DeleteOperationRestore($id: ID!) {
|
|
10
|
+
deleteOperationRestore(id: $id)
|
|
11
|
+
}
|
|
12
|
+
"""
|
|
13
|
+
self.api.query(
|
|
14
|
+
query,
|
|
15
|
+
{
|
|
16
|
+
"id": operation_id,
|
|
17
|
+
},
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
def delete(self, **kwargs):
|
|
21
|
+
"""Delete a trash item given its ID
|
|
22
|
+
|
|
23
|
+
:param id: ID for the delete operation on the platform.
|
|
24
|
+
:type id: str
|
|
25
|
+
"""
|
|
26
|
+
id = kwargs.get("id", None)
|
|
27
|
+
if id is None:
|
|
28
|
+
self.api.admin_logger.error(
|
|
29
|
+
"[opencti_trash] Cant confirm delete, missing parameter: id"
|
|
30
|
+
)
|
|
31
|
+
return None
|
|
32
|
+
query = """
|
|
33
|
+
mutation DeleteOperationConfirm($id: ID!) {
|
|
34
|
+
deleteOperationConfirm(id: $id)
|
|
35
|
+
}
|
|
36
|
+
"""
|
|
37
|
+
self.api.query(
|
|
38
|
+
query,
|
|
39
|
+
{
|
|
40
|
+
"id": id,
|
|
41
|
+
},
|
|
42
|
+
)
|
|
@@ -131,6 +131,25 @@ class OpenCTIApiWork:
|
|
|
131
131
|
work = self.api.query(query, {"workId": work_id}, True)
|
|
132
132
|
return work["data"]
|
|
133
133
|
|
|
134
|
+
def delete(self, **kwargs):
|
|
135
|
+
id = kwargs.get("id", None)
|
|
136
|
+
if id is None:
|
|
137
|
+
self.opencti.admin_logger.error(
|
|
138
|
+
"[opencti_work] Cant delete work, missing parameter: id"
|
|
139
|
+
)
|
|
140
|
+
return None
|
|
141
|
+
query = """
|
|
142
|
+
mutation ConnectorWorksMutation($workId: ID!) {
|
|
143
|
+
workEdit(id: $workId) {
|
|
144
|
+
delete
|
|
145
|
+
}
|
|
146
|
+
}"""
|
|
147
|
+
work = self.api.query(
|
|
148
|
+
query,
|
|
149
|
+
{"workId": id},
|
|
150
|
+
)
|
|
151
|
+
return work["data"]
|
|
152
|
+
|
|
134
153
|
def wait_for_work_to_finish(self, work_id: str):
|
|
135
154
|
status = ""
|
|
136
155
|
cnt = 0
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class OpenCTIApiWorkspace:
|
|
2
|
+
"""OpenCTIApiWorkspace"""
|
|
3
|
+
|
|
4
|
+
def __init__(self, api):
|
|
5
|
+
self.api = api
|
|
6
|
+
|
|
7
|
+
def delete(self, **kwargs):
|
|
8
|
+
id = kwargs.get("id", None)
|
|
9
|
+
if id is None:
|
|
10
|
+
self.api.admin_logger.error(
|
|
11
|
+
"[opencti_workspace] Cant delete workspace, missing parameter: id"
|
|
12
|
+
)
|
|
13
|
+
return None
|
|
14
|
+
query = """
|
|
15
|
+
mutation WorkspaceDelete($id: ID!) {
|
|
16
|
+
workspaceDelete(id: $id)
|
|
17
|
+
}
|
|
18
|
+
"""
|
|
19
|
+
self.api.query(
|
|
20
|
+
query,
|
|
21
|
+
{
|
|
22
|
+
"id": id,
|
|
23
|
+
},
|
|
24
|
+
)
|
|
@@ -1918,14 +1918,13 @@ class OpenCTIConnectorHelper: # pylint: disable=too-many-public-methods
|
|
|
1918
1918
|
os.rename(write_file, final_write_file)
|
|
1919
1919
|
|
|
1920
1920
|
stix2_splitter = OpenCTIStix2Splitter()
|
|
1921
|
-
(
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
cleanup_inconsistent_bundle=cleanup_inconsistent_bundle,
|
|
1921
|
+
(expectations_number, _, bundles) = (
|
|
1922
|
+
stix2_splitter.split_bundle_with_expectations(
|
|
1923
|
+
bundle=bundle,
|
|
1924
|
+
use_json=True,
|
|
1925
|
+
event_version=event_version,
|
|
1926
|
+
cleanup_inconsistent_bundle=cleanup_inconsistent_bundle,
|
|
1927
|
+
)
|
|
1929
1928
|
)
|
|
1930
1929
|
|
|
1931
1930
|
if len(bundles) == 0:
|
|
@@ -315,12 +315,18 @@ class Group:
|
|
|
315
315
|
)
|
|
316
316
|
return self.opencti.process_multiple_fields(result["data"]["groupAdd"])
|
|
317
317
|
|
|
318
|
-
def delete(self,
|
|
318
|
+
def delete(self, **kwargs):
|
|
319
319
|
"""Delete a given group from OpenCTI
|
|
320
320
|
|
|
321
321
|
:param id: ID of the group to delete.
|
|
322
322
|
:type id: str
|
|
323
323
|
"""
|
|
324
|
+
id = kwargs.get("id", None)
|
|
325
|
+
if id is None:
|
|
326
|
+
self.opencti.admin_logger.error(
|
|
327
|
+
"[opencti_group] Cant delete group, missing parameter: id"
|
|
328
|
+
)
|
|
329
|
+
return None
|
|
324
330
|
self.opencti.admin_logger.info("Deleting group", {"id": id})
|
|
325
331
|
query = """
|
|
326
332
|
mutation GroupDelete($id: ID!) {
|
|
@@ -51,11 +51,15 @@ class Identity:
|
|
|
51
51
|
}
|
|
52
52
|
... on Organization {
|
|
53
53
|
x_opencti_organization_type
|
|
54
|
+
x_opencti_score
|
|
54
55
|
}
|
|
55
56
|
... on Individual {
|
|
56
57
|
x_opencti_firstname
|
|
57
58
|
x_opencti_lastname
|
|
58
59
|
}
|
|
60
|
+
... on SecurityPlatform {
|
|
61
|
+
security_platform_type
|
|
62
|
+
}
|
|
59
63
|
}
|
|
60
64
|
objectMarking {
|
|
61
65
|
id
|
|
@@ -110,6 +114,10 @@ class Identity:
|
|
|
110
114
|
}
|
|
111
115
|
... on Organization {
|
|
112
116
|
x_opencti_organization_type
|
|
117
|
+
x_opencti_score
|
|
118
|
+
}
|
|
119
|
+
... on SecurityPlatform {
|
|
120
|
+
security_platform_type
|
|
113
121
|
}
|
|
114
122
|
"""
|
|
115
123
|
self.properties_with_files = """
|
|
@@ -152,11 +160,15 @@ class Identity:
|
|
|
152
160
|
}
|
|
153
161
|
... on Organization {
|
|
154
162
|
x_opencti_organization_type
|
|
163
|
+
x_opencti_score
|
|
155
164
|
}
|
|
156
165
|
... on Individual {
|
|
157
166
|
x_opencti_firstname
|
|
158
167
|
x_opencti_lastname
|
|
159
168
|
}
|
|
169
|
+
... on SecurityPlatform {
|
|
170
|
+
security_platform_type
|
|
171
|
+
}
|
|
160
172
|
}
|
|
161
173
|
objectMarking {
|
|
162
174
|
id
|
|
@@ -224,6 +236,10 @@ class Identity:
|
|
|
224
236
|
}
|
|
225
237
|
... on Organization {
|
|
226
238
|
x_opencti_organization_type
|
|
239
|
+
x_opencti_score
|
|
240
|
+
}
|
|
241
|
+
... on SecurityPlatform {
|
|
242
|
+
security_platform_type
|
|
227
243
|
}
|
|
228
244
|
importFiles {
|
|
229
245
|
edges {
|
|
@@ -410,8 +426,10 @@ class Identity:
|
|
|
410
426
|
contact_information = kwargs.get("contact_information", None)
|
|
411
427
|
roles = kwargs.get("roles", None)
|
|
412
428
|
x_opencti_aliases = kwargs.get("x_opencti_aliases", None)
|
|
429
|
+
security_platform_type = kwargs.get("security_platform_type", None)
|
|
413
430
|
x_opencti_organization_type = kwargs.get("x_opencti_organization_type", None)
|
|
414
431
|
x_opencti_reliability = kwargs.get("x_opencti_reliability", None)
|
|
432
|
+
x_opencti_score = kwargs.get("x_opencti_score", None)
|
|
415
433
|
x_opencti_firstname = kwargs.get("x_opencti_firstname", None)
|
|
416
434
|
x_opencti_lastname = kwargs.get("x_opencti_lastname", None)
|
|
417
435
|
x_opencti_stix_ids = kwargs.get("x_opencti_stix_ids", None)
|
|
@@ -456,7 +474,26 @@ class Identity:
|
|
|
456
474
|
x_opencti_organization_type
|
|
457
475
|
)
|
|
458
476
|
input_variables["x_opencti_reliability"] = x_opencti_reliability
|
|
477
|
+
input_variables["x_opencti_score"] = x_opencti_score
|
|
459
478
|
result_data_field = "organizationAdd"
|
|
479
|
+
elif type == IdentityTypes.SECURITYPLATFORM.value:
|
|
480
|
+
query = """
|
|
481
|
+
mutation SecurityPlatformAdd($input: SecurityPlatformAddInput!) {
|
|
482
|
+
securityPlatformAdd(input: $input) {
|
|
483
|
+
id
|
|
484
|
+
standard_id
|
|
485
|
+
entity_type
|
|
486
|
+
parent_types
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
"""
|
|
490
|
+
input_variables["security_platform_type"] = security_platform_type
|
|
491
|
+
# no need for these attributes for security platform
|
|
492
|
+
del input_variables["contact_information"]
|
|
493
|
+
del input_variables["lang"]
|
|
494
|
+
del input_variables["roles"]
|
|
495
|
+
del input_variables["x_opencti_aliases"]
|
|
496
|
+
result_data_field = "securityPlatformAdd"
|
|
460
497
|
elif type == IdentityTypes.INDIVIDUAL.value:
|
|
461
498
|
query = """
|
|
462
499
|
mutation IndividualAdd($input: IndividualAddInput!) {
|
|
@@ -536,6 +573,8 @@ class Identity:
|
|
|
536
573
|
type = "Sector"
|
|
537
574
|
elif stix_object["identity_class"] == "system":
|
|
538
575
|
type = "System"
|
|
576
|
+
elif stix_object["identity_class"] == "securityplatform":
|
|
577
|
+
type = "SecurityPlatform"
|
|
539
578
|
|
|
540
579
|
# Search in extensions
|
|
541
580
|
if "x_opencti_aliases" not in stix_object:
|
|
@@ -548,10 +587,20 @@ class Identity:
|
|
|
548
587
|
"organization_type", stix_object
|
|
549
588
|
)
|
|
550
589
|
)
|
|
590
|
+
if "security_platform_type" not in stix_object:
|
|
591
|
+
stix_object["security_platform_type"] = (
|
|
592
|
+
self.opencti.get_attribute_in_extension(
|
|
593
|
+
"security_platform_type", stix_object
|
|
594
|
+
)
|
|
595
|
+
)
|
|
551
596
|
if "x_opencti_reliability" not in stix_object:
|
|
552
597
|
stix_object["x_opencti_reliability"] = (
|
|
553
598
|
self.opencti.get_attribute_in_extension("reliability", stix_object)
|
|
554
599
|
)
|
|
600
|
+
if "x_opencti_score" not in stix_object:
|
|
601
|
+
stix_object["x_opencti_score"] = (
|
|
602
|
+
self.opencti.get_attribute_in_extension("score", stix_object)
|
|
603
|
+
)
|
|
555
604
|
if "x_opencti_organization_type" not in stix_object:
|
|
556
605
|
stix_object["x_opencti_organization_type"] = (
|
|
557
606
|
self.opencti.get_attribute_in_extension(
|
|
@@ -625,11 +674,21 @@ class Identity:
|
|
|
625
674
|
if "x_opencti_organization_type" in stix_object
|
|
626
675
|
else None
|
|
627
676
|
),
|
|
677
|
+
security_platform_type=(
|
|
678
|
+
stix_object["security_platform_type"]
|
|
679
|
+
if "security_platform_type" in stix_object
|
|
680
|
+
else None
|
|
681
|
+
),
|
|
628
682
|
x_opencti_reliability=(
|
|
629
683
|
stix_object["x_opencti_reliability"]
|
|
630
684
|
if "x_opencti_reliability" in stix_object
|
|
631
685
|
else None
|
|
632
686
|
),
|
|
687
|
+
x_opencti_score=(
|
|
688
|
+
stix_object["x_opencti_score"]
|
|
689
|
+
if "x_opencti_score" in stix_object
|
|
690
|
+
else None
|
|
691
|
+
),
|
|
633
692
|
x_opencti_firstname=(
|
|
634
693
|
stix_object["x_opencti_firstname"]
|
|
635
694
|
if "x_opencti_firstname" in stix_object
|
|
@@ -301,6 +301,43 @@ class Indicator:
|
|
|
301
301
|
"name or pattern or pattern_type or x_opencti_main_observable_type"
|
|
302
302
|
)
|
|
303
303
|
|
|
304
|
+
"""
|
|
305
|
+
Update an Indicator object field
|
|
306
|
+
|
|
307
|
+
:param id: the Indicator id
|
|
308
|
+
:param input: the input of the field
|
|
309
|
+
"""
|
|
310
|
+
|
|
311
|
+
def update_field(self, **kwargs):
|
|
312
|
+
id = kwargs.get("id", None)
|
|
313
|
+
input = kwargs.get("input", None)
|
|
314
|
+
if id is not None and input is not None:
|
|
315
|
+
self.opencti.app_logger.info("Updating Indicator", {"id": id})
|
|
316
|
+
query = """
|
|
317
|
+
mutation IndicatorFieldPatch($id: ID!, $input: [EditInput!]!) {
|
|
318
|
+
indicatorFieldPatch(id: $id, input: $input) {
|
|
319
|
+
id
|
|
320
|
+
standard_id
|
|
321
|
+
entity_type
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
"""
|
|
325
|
+
result = self.opencti.query(
|
|
326
|
+
query,
|
|
327
|
+
{
|
|
328
|
+
"id": id,
|
|
329
|
+
"input": input,
|
|
330
|
+
},
|
|
331
|
+
)
|
|
332
|
+
return self.opencti.process_multiple_fields(
|
|
333
|
+
result["data"]["indicatorFieldPatch"]
|
|
334
|
+
)
|
|
335
|
+
else:
|
|
336
|
+
self.opencti.app_logger.error(
|
|
337
|
+
"[opencti_stix_domain_object] Cant update indicator field, missing parameters: id and input"
|
|
338
|
+
)
|
|
339
|
+
return None
|
|
340
|
+
|
|
304
341
|
def add_stix_cyber_observable(self, **kwargs):
|
|
305
342
|
"""
|
|
306
343
|
Add a Stix-Cyber-Observable object to Indicator object (based-on)
|
|
@@ -11,16 +11,17 @@ class Stix:
|
|
|
11
11
|
|
|
12
12
|
def delete(self, **kwargs):
|
|
13
13
|
id = kwargs.get("id", None)
|
|
14
|
+
force_delete = kwargs.get("force_delete", True)
|
|
14
15
|
if id is not None:
|
|
15
16
|
self.opencti.app_logger.info("Deleting Stix element", {"id": id})
|
|
16
17
|
query = """
|
|
17
|
-
mutation StixEdit($id: ID
|
|
18
|
+
mutation StixEdit($id: ID!, $forceDelete: Boolean) {
|
|
18
19
|
stixEdit(id: $id) {
|
|
19
|
-
delete
|
|
20
|
+
delete(forceDelete: $forceDelete)
|
|
20
21
|
}
|
|
21
22
|
}
|
|
22
23
|
"""
|
|
23
|
-
self.opencti.query(query, {"id": id})
|
|
24
|
+
self.opencti.query(query, {"id": id, "forceDelete": force_delete})
|
|
24
25
|
else:
|
|
25
26
|
self.opencti.app_logger.error("[opencti_stix] Missing parameters: id")
|
|
26
27
|
return None
|