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

Commit bc3824d

Browse files
[client] Upgrage client to support platform sync
1 parent f75785e commit bc3824d

12 files changed

+523
-38
lines changed

pycti/api/opencti_api_client.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
from pycti.entities.opencti_observed_data import ObservedData
3131
from pycti.entities.opencti_opinion import Opinion
3232
from pycti.entities.opencti_report import Report
33+
from pycti.entities.opencti_stix import Stix
34+
from pycti.entities.opencti_stix_core_object import StixCoreObject
3335
from pycti.entities.opencti_stix_core_relationship import StixCoreRelationship
3436
from pycti.entities.opencti_stix_cyber_observable import StixCyberObservable
3537
from pycti.entities.opencti_stix_cyber_observable_relationship import (
@@ -113,7 +115,9 @@ def __init__(self, url, token, log_level="info", ssl_verify=False, proxies={}):
113115
self.opencti_stix_object_or_stix_relationship = StixObjectOrStixRelationship(
114116
self
115117
)
118+
self.stix = Stix(self)
116119
self.stix_domain_object = StixDomainObject(self, File)
120+
self.stix_core_object = StixCoreObject(self, File)
117121
self.stix_cyber_observable = StixCyberObservable(self, File)
118122
self.stix_core_relationship = StixCoreRelationship(self)
119123
self.stix_sighting_relationship = StixSightingRelationship(self)

pycti/entities/opencti_kill_chain_phase.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,54 @@ def create(self, **kwargs):
168168
"error",
169169
"[opencti_kill_chain_phase] Missing parameters: kill_chain_name and phase_name",
170170
)
171+
172+
"""
173+
Update a Kill chain object field
174+
175+
:param id: the Kill chain id
176+
:param key: the key of the field
177+
:param value: the value of the field
178+
:return The updated Kill chain object
179+
"""
180+
181+
def update_field(self, **kwargs):
182+
id = kwargs.get("id", None)
183+
key = kwargs.get("key", None)
184+
value = kwargs.get("value", None)
185+
operation = kwargs.get("operation", "replace")
186+
if isinstance(value, list):
187+
value = [str(v) for v in value]
188+
else:
189+
value = str(value)
190+
if id is not None and key is not None and value is not None:
191+
self.opencti.log(
192+
"info", "Updating Kill chain {" + id + "} field {" + key + "}."
193+
)
194+
query = """
195+
mutation KillChainPhaseEdit($id: ID!, $input: EditInput!, $operation: EditOperation) {
196+
killChainPhaseEdit(id: $id) {
197+
fieldPatch(input: $input, operation: $operation) {
198+
id
199+
standard_id
200+
entity_type
201+
}
202+
}
203+
}
204+
"""
205+
result = self.opencti.query(
206+
query,
207+
{
208+
"id": id,
209+
"input": {"key": key, "value": value},
210+
"operation": operation,
211+
},
212+
)
213+
return self.opencti.process_multiple_fields(
214+
result["data"]["killChainPhaseEdit"]["fieldPatch"]
215+
)
216+
else:
217+
self.opencti.log(
218+
"error",
219+
"[opencti_kill_chain] Missing parameters: id and key and value",
220+
)
221+
return None

pycti/entities/opencti_label.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,3 +150,54 @@ def create(self, **kwargs):
150150
"error",
151151
"[opencti_label] Missing parameters: value",
152152
)
153+
154+
"""
155+
Update a Label object field
156+
157+
:param id: the Label id
158+
:param key: the key of the field
159+
:param value: the value of the field
160+
:return The updated Label object
161+
"""
162+
163+
def update_field(self, **kwargs):
164+
id = kwargs.get("id", None)
165+
key = kwargs.get("key", None)
166+
value = kwargs.get("value", None)
167+
operation = kwargs.get("operation", "replace")
168+
if isinstance(value, list):
169+
value = [str(v) for v in value]
170+
else:
171+
value = str(value)
172+
if id is not None and key is not None and value is not None:
173+
self.opencti.log(
174+
"info", "Updating Label {" + id + "} field {" + key + "}."
175+
)
176+
query = """
177+
mutation LabelEdit($id: ID!, $input: EditInput!, $operation: EditOperation) {
178+
labelEdit(id: $id) {
179+
fieldPatch(input: $input, operation: $operation) {
180+
id
181+
standard_id
182+
entity_type
183+
}
184+
}
185+
}
186+
"""
187+
result = self.opencti.query(
188+
query,
189+
{
190+
"id": id,
191+
"input": {"key": key, "value": value},
192+
"operation": operation,
193+
},
194+
)
195+
return self.opencti.process_multiple_fields(
196+
result["data"]["labelEdit"]["fieldPatch"]
197+
)
198+
else:
199+
self.opencti.log(
200+
"error",
201+
"[opencti_label] Missing parameters: id and key and value",
202+
)
203+
return None

pycti/entities/opencti_marking_definition.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,57 @@ def create(self, **kwargs):
176176
"[opencti_marking_definition] Missing parameters: definition and definition_type",
177177
)
178178

179+
"""
180+
Update a Marking definition object field
181+
182+
:param id: the Marking definition id
183+
:param key: the key of the field
184+
:param value: the value of the field
185+
:return The updated Marking definition object
186+
"""
187+
188+
def update_field(self, **kwargs):
189+
id = kwargs.get("id", None)
190+
key = kwargs.get("key", None)
191+
value = kwargs.get("value", None)
192+
operation = kwargs.get("operation", "replace")
193+
if isinstance(value, list):
194+
value = [str(v) for v in value]
195+
else:
196+
value = str(value)
197+
if id is not None and key is not None and value is not None:
198+
self.opencti.log(
199+
"info", "Updating Marking Definition {" + id + "} field {" + key + "}."
200+
)
201+
query = """
202+
mutation MarkingDefinitionEdit($id: ID!, $input: EditInput!, $operation: EditOperation) {
203+
markingDefinitionEdit(id: $id) {
204+
fieldPatch(input: $input, operation: $operation) {
205+
id
206+
standard_id
207+
entity_type
208+
}
209+
}
210+
}
211+
"""
212+
result = self.opencti.query(
213+
query,
214+
{
215+
"id": id,
216+
"input": {"key": key, "value": value},
217+
"operation": operation,
218+
},
219+
)
220+
return self.opencti.process_multiple_fields(
221+
result["data"]["markingDefinitionEdit"]["fieldPatch"]
222+
)
223+
else:
224+
self.opencti.log(
225+
"error",
226+
"[opencti_marking_definition] Missing parameters: id and key and value",
227+
)
228+
return None
229+
179230
"""
180231
Import an Marking Definition object from a STIX2 object
181232

pycti/entities/opencti_opinion.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -527,10 +527,10 @@ def import_from_stix2(self, **kwargs):
527527
else None,
528528
objectLabel=extras["object_label_ids"]
529529
if "object_label_ids" in extras
530-
else [],
530+
else None,
531531
externalReferences=extras["external_references_ids"]
532532
if "external_references_ids" in extras
533-
else [],
533+
else None,
534534
revoked=stix_object["revoked"] if "revoked" in stix_object else None,
535535
confidence=stix_object["confidence"]
536536
if "confidence" in stix_object
@@ -542,10 +542,10 @@ def import_from_stix2(self, **kwargs):
542542
stix_object["explanation"]
543543
)
544544
if "explanation" in stix_object
545-
else "",
545+
else None,
546546
authors=self.opencti.stix2.convert_markdown(stix_object["authors"])
547547
if "authors" in stix_object
548-
else "",
548+
else None,
549549
opinion=stix_object["opinion"] if "opinion" in stix_object else None,
550550
update=update,
551551
)

pycti/entities/opencti_report.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ def import_from_stix2(self, **kwargs):
605605
report_types=stix_object["report_types"]
606606
if "report_types" in stix_object
607607
else None,
608-
published=stix_object["published"],
608+
published=stix_object["published"] if "published" in stix_object else None,
609609
x_opencti_graph_data=stix_object["x_opencti_graph_data"]
610610
if "x_opencti_graph_data" in stix_object
611611
else None,

pycti/entities/opencti_stix.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# coding: utf-8
2+
3+
import json
4+
import os
5+
6+
import magic
7+
8+
9+
class Stix:
10+
def __init__(self, opencti):
11+
self.opencti = opencti
12+
13+
"""
14+
Delete a Stix element
15+
16+
:param id: the Stix element id
17+
:return void
18+
"""
19+
20+
def delete(self, **kwargs):
21+
id = kwargs.get("id", None)
22+
if id is not None:
23+
self.opencti.log("info", "Deleting Stix element {" + id + "}.")
24+
query = """
25+
mutation StixEdit($id: ID!) {
26+
stixEdit(id: $id) {
27+
delete
28+
}
29+
}
30+
"""
31+
self.opencti.query(query, {"id": id})
32+
else:
33+
self.opencti.log(
34+
"error", "[opencti_stix] Missing parameters: id"
35+
)
36+
return None
37+
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# coding: utf-8
2+
3+
import json
4+
import os
5+
6+
import magic
7+
8+
9+
class StixCoreObject:
10+
def __init__(self, opencti, file):
11+
self.opencti = opencti
12+
self.file = file
13+
14+
"""
15+
Update a Stix-Domain-Object object field
16+
17+
:param id: the Stix-Domain-Object id
18+
:param key: the key of the field
19+
:param value: the value of the field
20+
:return The updated Stix-Domain-Object object
21+
"""
22+
23+
def merge(self, **kwargs):
24+
id = kwargs.get("id", None)
25+
stix_core_objects_ids = kwargs.get("object_ids", None)
26+
if id is not None and stix_core_objects_ids is not None:
27+
self.opencti.log(
28+
"info", "Merging Core object {" + id + "} with {" + ','.join(stix_core_objects_ids) + "}."
29+
)
30+
query = """
31+
mutation StixCoreObjectEdit($id: ID!, $stixCoreObjectsIds: [String]!) {
32+
stixCoreObjectEdit(id: $id) {
33+
merge(stixCoreObjectsIds: $stixCoreObjectsIds) {
34+
id
35+
standard_id
36+
entity_type
37+
}
38+
}
39+
}
40+
"""
41+
result = self.opencti.query(
42+
query,
43+
{
44+
"id": id,
45+
"stixCoreObjectsIds": stix_core_objects_ids,
46+
},
47+
)
48+
return self.opencti.process_multiple_fields(
49+
result["data"]["stixCoreObjectEdit"]["merge"]
50+
)
51+
else:
52+
self.opencti.log(
53+
"error",
54+
"[opencti_stix_core_object] Missing parameters: id and object_ids",
55+
)
56+
return None

pycti/entities/opencti_stix_core_relationship.py

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,7 @@ def update_field(self, **kwargs):
536536
id = kwargs.get("id", None)
537537
key = kwargs.get("key", None)
538538
value = kwargs.get("value", None)
539+
operation = kwargs.get("operation", "replace")
539540
if isinstance(value, list):
540541
value = [str(v) for v in value]
541542
else:
@@ -546,9 +547,9 @@ def update_field(self, **kwargs):
546547
"Updating stix_core_relationship {" + id + "} field {" + key + "}.",
547548
)
548549
query = """
549-
mutation StixCoreRelationshipEdit($id: ID!, $input: EditInput!) {
550+
mutation StixCoreRelationshipEdit($id: ID!, $input: EditInput!, $operation: EditOperation) {
550551
stixCoreRelationshipEdit(id: $id) {
551-
fieldPatch(input: $input) {
552+
fieldPatch(input: $input, operation: $operation) {
552553
id
553554
standard_id
554555
entity_type
@@ -557,7 +558,11 @@ def update_field(self, **kwargs):
557558
}
558559
"""
559560
result = self.opencti.query(
560-
query, {"id": id, "input": {"key": key, "value": value}}
561+
query, {
562+
"id": id,
563+
"input": {"key": key, "value": value},
564+
"operation": operation
565+
}
561566
)
562567
return self.opencti.process_multiple_fields(
563568
result["data"]["stixCoreRelationshipEdit"]["fieldPatch"]
@@ -1068,16 +1073,8 @@ def import_from_stix2(self, **kwargs):
10681073
stix_relation["relationship_type"] = "part-of"
10691074
elif stix_relation["relationship_type"] == "localization":
10701075
stix_relation["relationship_type"] = "located-at"
1071-
source_ref = (
1072-
stix_relation["x_opencti_source_ref"]
1073-
if "x_opencti_source_ref" in stix_relation
1074-
else stix_relation["source_ref"]
1075-
)
1076-
target_ref = (
1077-
stix_relation["x_opencti_target_ref"]
1078-
if "x_opencti_target_ref" in stix_relation
1079-
else stix_relation["target_ref"]
1080-
)
1076+
source_ref = stix_relation["source_ref"]
1077+
target_ref = stix_relation["target_ref"]
10811078
return self.create(
10821079
fromId=source_ref,
10831080
toId=target_ref,

0 commit comments

Comments
 (0)