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

Commit e790813

Browse files
[client] Improve api to handle sync
1 parent 33f588f commit e790813

29 files changed

+217
-390
lines changed

pycti/connector/opencti_connector_helper.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ def __init__(
251251
self.token = token
252252
self.verify_ssl = verify_ssl
253253
self.start_timestamp = start_timestamp
254-
self.exit_event = threading.Event()
254+
self.exit = False
255255

256256
def run(self) -> None: # pylint: disable=too-many-branches
257257
current_state = self.helper.get_state()
@@ -335,8 +335,10 @@ def run(self) -> None: # pylint: disable=too-many-branches
335335
headers={"authorization": "Bearer " + self.helper.opencti_token},
336336
verify=self.helper.opencti_ssl_verify,
337337
)
338-
338+
# Iter on stream messages
339339
for msg in messages:
340+
if self.exit:
341+
break
340342
if msg.event == "heartbeat" or msg.event == "connected":
341343
continue
342344
if msg.event == "sync":
@@ -351,6 +353,9 @@ def run(self) -> None: # pylint: disable=too-many-branches
351353
state["connectorLastEventId"] = str(msg.id)
352354
self.helper.set_state(state)
353355

356+
def stop(self):
357+
self.exit = True
358+
354359

355360
class OpenCTIConnectorHelper: # pylint: disable=too-many-public-methods
356361
"""Python API for OpenCTI connector
@@ -504,7 +509,7 @@ def listen_stream(
504509
token=None,
505510
verify_ssl=None,
506511
start_timestamp=None,
507-
) -> None:
512+
) -> ListenStream:
508513
"""listen for messages and register callback function
509514
510515
:param message_callback: callback function to process messages
@@ -514,6 +519,7 @@ def listen_stream(
514519
self, message_callback, url, token, verify_ssl, start_timestamp
515520
)
516521
self.listen_stream.start()
522+
return self.listen_stream
517523

518524
def get_opencti_url(self) -> Optional[Union[bool, int, str]]:
519525
return self.opencti_url

pycti/entities/opencti_attack_pattern.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ def create(self, **kwargs):
269269
x_mitre_detection = kwargs.get("x_mitre_detection", None)
270270
x_mitre_id = kwargs.get("x_mitre_id", None)
271271
kill_chain_phases = kwargs.get("killChainPhases", None)
272+
x_opencti_stix_ids = kwargs.get("x_opencti_stix_ids", None)
272273
update = kwargs.get("update", False)
273274

274275
if name is not None and description is not None:
@@ -305,6 +306,7 @@ def create(self, **kwargs):
305306
"x_mitre_detection": x_mitre_detection,
306307
"x_mitre_id": x_mitre_id,
307308
"killChainPhases": kill_chain_phases,
309+
"x_opencti_stix_ids": x_opencti_stix_ids,
308310
"update": update,
309311
}
310312
},
@@ -400,6 +402,9 @@ def import_from_stix2(self, **kwargs):
400402
killChainPhases=extras["kill_chain_phases_ids"]
401403
if "kill_chain_phases_ids" in extras
402404
else None,
405+
x_opencti_stix_ids=stix_object["x_opencti_stix_ids"]
406+
if "x_opencti_stix_ids" in stix_object
407+
else None,
403408
update=update,
404409
)
405410
else:

pycti/entities/opencti_campaign.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ def create(self, **kwargs):
231231
last_seen = kwargs.get("last_seen", None)
232232
objective = kwargs.get("objective", None)
233233
update = kwargs.get("update", False)
234+
x_opencti_stix_ids = kwargs.get("x_opencti_stix_ids", None)
234235

235236
if name is not None and description is not None:
236237
self.opencti.log("info", "Creating Campaign {" + name + "}.")
@@ -265,6 +266,7 @@ def create(self, **kwargs):
265266
"last_seen": last_seen,
266267
"objective": objective,
267268
"update": update,
269+
"x_opencti_stix_ids": x_opencti_stix_ids,
268270
}
269271
},
270272
)
@@ -323,6 +325,9 @@ def import_from_stix2(self, **kwargs):
323325
last_seen=stix_object["last_seen"]
324326
if "last_seen" in stix_object
325327
else None,
328+
x_opencti_stix_ids=stix_object["x_opencti_stix_ids"]
329+
if "x_opencti_stix_ids" in stix_object
330+
else None,
326331
update=update,
327332
)
328333
else:

pycti/entities/opencti_course_of_action.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ def create(self, **kwargs):
228228
name = kwargs.get("name", None)
229229
description = kwargs.get("description", "")
230230
x_opencti_aliases = kwargs.get("x_opencti_aliases", None)
231+
x_opencti_stix_ids = kwargs.get("x_opencti_stix_ids", None)
231232
x_mitre_id = kwargs.get("x_mitre_id", None)
232233
update = kwargs.get("update", False)
233234

@@ -260,6 +261,7 @@ def create(self, **kwargs):
260261
"name": name,
261262
"description": description,
262263
"x_opencti_aliases": x_opencti_aliases,
264+
"x_opencti_stix_ids": x_opencti_stix_ids,
263265
"x_mitre_id": x_mitre_id,
264266
"update": update,
265267
}
@@ -327,6 +329,9 @@ def import_from_stix2(self, **kwargs):
327329
)
328330
if "description" in stix_object
329331
else "",
332+
x_opencti_stix_ids=stix_object["x_opencti_stix_ids"]
333+
if "x_opencti_stix_ids" in stix_object
334+
else None,
330335
x_opencti_aliases=self.opencti.stix2.pick_aliases(stix_object),
331336
x_mitre_id=x_mitre_id,
332337
update=update,

pycti/entities/opencti_external_reference.py

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ def create(self, **kwargs):
138138
url = kwargs.get("url", None)
139139
external_id = kwargs.get("external_id", None)
140140
description = kwargs.get("description", None)
141+
x_opencti_stix_ids = kwargs.get("x_opencti_stix_ids", None)
141142
update = kwargs.get("update", False)
142143

143144
if source_name is not None and url is not None:
@@ -166,6 +167,7 @@ def create(self, **kwargs):
166167
"external_id": external_id,
167168
"description": description,
168169
"url": url,
170+
"x_opencti_stix_ids": x_opencti_stix_ids,
169171
"update": update,
170172
}
171173
},
@@ -183,31 +185,25 @@ def create(self, **kwargs):
183185
Update a External Reference object field
184186
185187
:param id: the External Reference id
186-
:param key: the key of the field
187-
:param value: the value of the field
188+
:param input: the input of the field
188189
:return The updated External Reference object
189190
"""
190191

191192
def update_field(self, **kwargs):
192193
id = kwargs.get("id", None)
193-
key = kwargs.get("key", None)
194-
value = kwargs.get("value", None)
195-
if id is not None and key is not None and value is not None:
196-
self.opencti.log(
197-
"info", "Updating External-Reference {" + id + "} field {" + key + "}."
198-
)
194+
input = kwargs.get("input", None)
195+
if id is not None and input is not None:
196+
self.opencti.log("info", "Updating External-Reference {" + id + "}.")
199197
query = """
200-
mutation ExternalReferenceEdit($id: ID!, $input: EditInput!) {
198+
mutation ExternalReferenceEdit($id: ID!, $input: [EditInput]!) {
201199
externalReferenceEdit(id: $id) {
202200
fieldPatch(input: $input) {
203201
id
204202
}
205203
}
206204
}
207205
"""
208-
result = self.opencti.query(
209-
query, {"id": id, "input": {"key": key, "value": value}}
210-
)
206+
result = self.opencti.query(query, {"id": id, "input": input})
211207
return self.opencti.process_multiple_fields(
212208
result["data"]["externalReferenceEdit"]["fieldPatch"]
213209
)

pycti/entities/opencti_identity.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ def create(self, **kwargs):
246246
x_opencti_reliability = kwargs.get("x_opencti_reliability", None)
247247
x_opencti_firstname = kwargs.get("x_opencti_firstname", None)
248248
x_opencti_lastname = kwargs.get("x_opencti_lastname", None)
249+
x_opencti_stix_ids = kwargs.get("x_opencti_stix_ids", None)
249250
update = kwargs.get("update", False)
250251

251252
if type is not None and name is not None and description is not None:
@@ -266,6 +267,7 @@ def create(self, **kwargs):
266267
"contact_information": contact_information,
267268
"roles": roles,
268269
"x_opencti_aliases": x_opencti_aliases,
270+
"x_opencti_stix_ids": x_opencti_stix_ids,
269271
"update": update,
270272
}
271273
if type == IdentityTypes.ORGANIZATION.value:
@@ -388,6 +390,9 @@ def import_from_stix2(self, **kwargs):
388390
x_opencti_lastname=stix_object["x_opencti_lastname"]
389391
if "x_opencti_lastname" in stix_object
390392
else None,
393+
x_opencti_stix_ids=stix_object["x_opencti_stix_ids"]
394+
if "x_opencti_stix_ids" in stix_object
395+
else None,
391396
update=update,
392397
)
393398
else:

pycti/entities/opencti_incident.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ def create(self, **kwargs):
230230
first_seen = kwargs.get("first_seen", None)
231231
last_seen = kwargs.get("last_seen", None)
232232
objective = kwargs.get("objective", None)
233+
x_opencti_stix_ids = kwargs.get("x_opencti_stix_ids", None)
233234
update = kwargs.get("update", False)
234235

235236
if name is not None and description is not None:
@@ -264,6 +265,7 @@ def create(self, **kwargs):
264265
"first_seen": first_seen,
265266
"last_seen": last_seen,
266267
"objective": objective,
268+
"x_opencti_stix_ids": x_opencti_stix_ids,
267269
"update": update,
268270
}
269271
},
@@ -321,6 +323,9 @@ def import_from_stix2(self, **kwargs):
321323
last_seen=stix_object["last_seen"]
322324
if "last_seen" in stix_object
323325
else None,
326+
x_opencti_stix_ids=stix_object["x_opencti_stix_ids"]
327+
if "x_opencti_stix_ids" in stix_object
328+
else None,
324329
update=update,
325330
)
326331
else:

pycti/entities/opencti_indicator.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ def create(self, **kwargs):
314314
)
315315
x_mitre_platforms = kwargs.get("x_mitre_platforms", None)
316316
kill_chain_phases = kwargs.get("killChainPhases", None)
317+
x_opencti_stix_ids = kwargs.get("x_opencti_stix_ids", None)
317318
update = kwargs.get("update", False)
318319

319320
if (
@@ -371,6 +372,7 @@ def create(self, **kwargs):
371372
"x_opencti_detection": x_opencti_detection,
372373
"x_opencti_main_observable_type": x_opencti_main_observable_type,
373374
"x_mitre_platforms": x_mitre_platforms,
375+
"x_opencti_stix_ids": x_opencti_stix_ids,
374376
"killChainPhases": kill_chain_phases,
375377
"update": update,
376378
}
@@ -516,6 +518,9 @@ def import_from_stix2(self, **kwargs):
516518
killChainPhases=extras["kill_chain_phases_ids"]
517519
if "kill_chain_phases_ids" in extras
518520
else None,
521+
x_opencti_stix_ids=stix_object["x_opencti_stix_ids"]
522+
if "x_opencti_stix_ids" in stix_object
523+
else None,
519524
update=update,
520525
)
521526
else:

pycti/entities/opencti_infrastructure.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ def create(self, **kwargs):
285285
first_seen = kwargs.get("first_seen", None)
286286
last_seen = kwargs.get("last_seen", None)
287287
kill_chain_phases = kwargs.get("killChainPhases", None)
288+
x_opencti_stix_ids = kwargs.get("x_opencti_stix_ids", None)
288289
update = kwargs.get("update", False)
289290

290291
if name is not None:
@@ -320,6 +321,7 @@ def create(self, **kwargs):
320321
"first_seen": first_seen,
321322
"last_seen": last_seen,
322323
"killChainPhases": kill_chain_phases,
324+
"x_opencti_stix_ids": x_opencti_stix_ids,
323325
"update": update,
324326
}
325327
},
@@ -385,6 +387,9 @@ def import_from_stix2(self, **kwargs):
385387
killChainPhases=extras["kill_chain_phases_ids"]
386388
if "kill_chain_phases_ids" in extras
387389
else None,
390+
x_opencti_stix_ids=stix_object["x_opencti_stix_ids"]
391+
if "x_opencti_stix_ids" in stix_object
392+
else None,
388393
update=update,
389394
)
390395
else:

pycti/entities/opencti_intrusion_set.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ def create(self, **kwargs):
236236
resource_level = kwargs.get("resource_level", None)
237237
primary_motivation = kwargs.get("primary_motivation", None)
238238
secondary_motivations = kwargs.get("secondary_motivations", None)
239+
x_opencti_stix_ids = kwargs.get("x_opencti_stix_ids", None)
239240
update = kwargs.get("update", False)
240241

241242
if name is not None and description is not None:
@@ -273,6 +274,7 @@ def create(self, **kwargs):
273274
"resource_level": resource_level,
274275
"primary_motivation": primary_motivation,
275276
"secondary_motivations": secondary_motivations,
277+
"x_opencti_stix_ids": x_opencti_stix_ids,
276278
"update": update,
277279
}
278280
},
@@ -342,6 +344,9 @@ def import_from_stix2(self, **kwargs):
342344
secondary_motivations=stix_object["secondary_motivations"]
343345
if "secondary_motivations" in stix_object
344346
else None,
347+
x_opencti_stix_ids=stix_object["x_opencti_stix_ids"]
348+
if "x_opencti_stix_ids" in stix_object
349+
else None,
345350
update=update,
346351
)
347352
else:

0 commit comments

Comments
 (0)