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

Commit 6fa7421

Browse files
author
Samuel Hassine
committed
[client] Add sightings
1 parent 063afda commit 6fa7421

21 files changed

+1002
-69
lines changed

examples/import_stix2_file.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
from pycti import OpenCTIApiClient
44

55
# Variables
6-
api_url = "https://demo.opencti.io"
7-
api_token = "2b4f29e3-5ea8-4890-8cf5-a76f61f1e2b2"
6+
api_url = "http://localhost:4000"
7+
api_token = "0b23f787-d013-41a8-8078-97bee84cc99d"
88

99
# OpenCTI initialization
1010
opencti_api_client = OpenCTIApiClient(api_url, api_token)

pycti/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from .entities.opencti_stix_domain_entity import StixDomainEntity
1919
from .entities.opencti_stix_observable import StixObservable
2020
from .entities.opencti_stix_relation import StixRelation
21+
from .entities.opencti_stix_sighting import StixSighting
2122
from .entities.opencti_stix_observable_relation import StixObservableRelation
2223
from .entities.opencti_identity import Identity
2324
from .entities.opencti_threat_actor import ThreatActor
@@ -54,6 +55,7 @@
5455
"StixDomainEntity",
5556
"StixObservable",
5657
"StixRelation",
58+
"StixSighting",
5759
"StixObservableRelation",
5860
"Identity",
5961
"ThreatActor",

pycti/api/opencti_api_client.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from pycti.entities.opencti_stix_domain_entity import StixDomainEntity
2121
from pycti.entities.opencti_stix_observable import StixObservable
2222
from pycti.entities.opencti_stix_relation import StixRelation
23+
from pycti.entities.opencti_stix_sighting import StixSighting
2324
from pycti.entities.opencti_stix_observable_relation import StixObservableRelation
2425
from pycti.entities.opencti_identity import Identity
2526
from pycti.entities.opencti_threat_actor import ThreatActor
@@ -89,6 +90,7 @@ def __init__(self, url, token, log_level="info", ssl_verify=False):
8990
self.stix_domain_entity = StixDomainEntity(self, File)
9091
self.stix_observable = StixObservable(self)
9192
self.stix_relation = StixRelation(self)
93+
self.stix_sighting = StixSighting(self)
9294
self.stix_observable_relation = StixObservableRelation(self)
9395
self.identity = Identity(self)
9496
self.threat_actor = ThreatActor(self)

pycti/entities/opencti_attack_pattern.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ def __init__(self, opencti):
1717
name
1818
alias
1919
description
20+
confidence
2021
graph_data
2122
platform
2223
required_permission
@@ -251,6 +252,7 @@ def create_raw(self, **kwargs):
251252
platform = kwargs.get("platform", None)
252253
required_permission = kwargs.get("required_permission", None)
253254
external_id = kwargs.get("external_id", None)
255+
confidence = kwargs.get("confidence", 50)
254256
id = kwargs.get("id", None)
255257
stix_id_key = kwargs.get("stix_id_key", None)
256258
created = kwargs.get("created", None)
@@ -283,6 +285,7 @@ def create_raw(self, **kwargs):
283285
"platform": platform,
284286
"required_permission": required_permission,
285287
"external_id": external_id,
288+
"confidence": confidence,
286289
"internal_id_key": id,
287290
"stix_id_key": stix_id_key,
288291
"created": created,
@@ -317,6 +320,7 @@ def create(self, **kwargs):
317320
platform = kwargs.get("platform", None)
318321
required_permission = kwargs.get("required_permission", None)
319322
external_id = kwargs.get("external_id", None)
323+
confidence = kwargs.get("confidence", 50)
320324
id = kwargs.get("id", None)
321325
stix_id_key = kwargs.get("stix_id_key", None)
322326
created = kwargs.get("created", None)
@@ -332,6 +336,7 @@ def create(self, **kwargs):
332336
name
333337
description
334338
alias
339+
confidence
335340
createdByRef {
336341
node {
337342
id
@@ -362,7 +367,10 @@ def create(self, **kwargs):
362367
)
363368
object_result["name"] = name
364369
# description
365-
if object_result["description"] != description:
370+
if (
371+
description is not None
372+
and object_result["description"] != description
373+
):
366374
self.opencti.stix_domain_entity.update_field(
367375
id=object_result["id"], key="description", value=description
368376
)
@@ -405,6 +413,12 @@ def create(self, **kwargs):
405413
id=object_result["id"], key="external_id", value=external_id
406414
)
407415
object_result["external_id"] = external_id
416+
# confidence
417+
if confidence is not None and object_result["confidence"] != confidence:
418+
self.opencti.stix_domain_entity.update_field(
419+
id=object_result["id"], key="confidence", value=confidence
420+
)
421+
object_result["confidence"] = confidence
408422
return object_result
409423
else:
410424
return self.create_raw(
@@ -414,6 +428,7 @@ def create(self, **kwargs):
414428
platform=platform,
415429
required_permission=required_permission,
416430
external_id=external_id,
431+
confidence=confidence,
417432
id=id,
418433
stix_id_key=stix_id_key,
419434
created=created,
@@ -465,6 +480,9 @@ def import_from_stix2(self, **kwargs):
465480
if "x_mitre_permissions_required" in stix_object
466481
else None,
467482
external_id=external_id,
483+
confidence=stix_object["confidence"]
484+
if "confidence" in stix_object
485+
else None,
468486
id=stix_object[CustomProperties.ID]
469487
if CustomProperties.ID in stix_object
470488
else None,

pycti/entities/opencti_campaign.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ def __init__(self, opencti):
1717
name
1818
alias
1919
description
20+
confidence
2021
graph_data
2122
objective
2223
first_seen
@@ -287,6 +288,7 @@ def create(self, **kwargs):
287288
name
288289
description
289290
alias
291+
confidence
290292
createdByRef {
291293
node {
292294
id
@@ -313,7 +315,10 @@ def create(self, **kwargs):
313315
)
314316
object_result["name"] = name
315317
# description
316-
if object_result["description"] != description:
318+
if (
319+
description is not None
320+
and object_result["description"] != description
321+
):
317322
self.opencti.stix_domain_entity.update_field(
318323
id=object_result["id"], key="description", value=description
319324
)
@@ -399,11 +404,11 @@ def to_stix2(self, **kwargs):
399404
if self.opencti.not_empty(entity["objective"]):
400405
campaign["objective"] = entity["objective"]
401406
if self.opencti.not_empty(entity["first_seen"]):
402-
campaign[CustomProperties.FIRST_SEEN] = self.opencti.stix2.format_date(
407+
campaign["first_seen"] = self.opencti.stix2.format_date(
403408
entity["first_seen"]
404409
)
405410
if self.opencti.not_empty(entity["last_seen"]):
406-
campaign[CustomProperties.LAST_SEEN] = self.opencti.stix2.format_date(
411+
campaign["last_seen"] = self.opencti.stix2.format_date(
407412
entity["last_seen"]
408413
)
409414
campaign["created"] = self.opencti.stix2.format_date(entity["created"])

pycti/entities/opencti_course_of_action.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ def __init__(self, opencti):
1717
name
1818
alias
1919
description
20+
confidence
2021
graph_data
2122
created
2223
modified
@@ -302,7 +303,10 @@ def create(self, **kwargs):
302303
)
303304
object_result["name"] = name
304305
# description
305-
if object_result["description"] != description:
306+
if (
307+
description is not None
308+
and object_result["description"] != description
309+
):
306310
self.opencti.stix_domain_entity.update_field(
307311
id=object_result["id"], key="description", value=description
308312
)

pycti/entities/opencti_identity.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,10 @@ def create(self, **kwargs):
302302
)
303303
object_result["name"] = name
304304
# description
305-
if object_result["description"] != description:
305+
if (
306+
description is not None
307+
and object_result["description"] != description
308+
):
306309
self.opencti.stix_domain_entity.update_field(
307310
id=object_result["id"], key="description", value=description
308311
)

pycti/entities/opencti_incident.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,10 @@ def create(self, **kwargs):
321321
)
322322
object_result["name"] = name
323323
# description
324-
if object_result["description"] != description:
324+
if (
325+
description is not None
326+
and object_result["description"] != description
327+
):
325328
self.opencti.stix_domain_entity.update_field(
326329
id=object_result["id"], key="description", value=description
327330
)

pycti/entities/opencti_indicator.py

Lines changed: 94 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,8 @@ def create_raw(self, **kwargs):
269269
valid_from = kwargs.get("valid_from", None)
270270
valid_until = kwargs.get("valid_until", None)
271271
score = kwargs.get("score", None)
272+
confidence = kwargs.get("confidence", 50)
273+
detection = kwargs.get("detection", False)
272274
id = kwargs.get("id", None)
273275
stix_id_key = kwargs.get("stix_id_key", None)
274276
created = kwargs.get("created", None)
@@ -309,6 +311,8 @@ def create_raw(self, **kwargs):
309311
"valid_from": valid_from,
310312
"valid_until": valid_until,
311313
"score": score,
314+
"detection": detection,
315+
"confidence": confidence,
312316
"internal_id_key": id,
313317
"stix_id_key": stix_id_key,
314318
"created": created,
@@ -343,6 +347,8 @@ def create(self, **kwargs):
343347
valid_from = kwargs.get("valid_from", None)
344348
valid_until = kwargs.get("valid_until", None)
345349
score = kwargs.get("score", None)
350+
confidence = kwargs.get("confidence", 50)
351+
detection = kwargs.get("detection", False)
346352
id = kwargs.get("id", None)
347353
stix_id_key = kwargs.get("stix_id_key", None)
348354
created = kwargs.get("created", None)
@@ -358,11 +364,13 @@ def create(self, **kwargs):
358364
name
359365
description
360366
score
367+
confidence
368+
detection
361369
createdByRef {
362370
node {
363371
id
364372
}
365-
}
373+
}
366374
... on Indicator {
367375
observableRefs {
368376
edges {
@@ -418,6 +426,18 @@ def create(self, **kwargs):
418426
id=object_result["id"], key="score", value=score
419427
)
420428
object_result["score"] = score
429+
# confidence
430+
if confidence is not None and object_result["confidence"] != confidence:
431+
self.opencti.stix_domain_entity.update_field(
432+
id=object_result["id"], key="confidence", value=confidence
433+
)
434+
object_result["confidence"] = confidence
435+
# detection
436+
if detection is not None and object_result["detection"] != detection:
437+
self.opencti.stix_domain_entity.update_field(
438+
id=object_result["id"], key="detection", value=detection
439+
)
440+
object_result["detection"] = detection
421441
return object_result
422442
else:
423443
return self.create_raw(
@@ -429,6 +449,8 @@ def create(self, **kwargs):
429449
valid_from=valid_from,
430450
valid_until=valid_until,
431451
score=score,
452+
detection=detection,
453+
confidence=confidence,
432454
id=id,
433455
stix_id_key=stix_id_key,
434456
created=created,
@@ -500,6 +522,75 @@ def add_stix_observable(self, **kwargs):
500522
)
501523
return False
502524

525+
"""
526+
Import an Indicator object from a STIX2 object
527+
528+
:param stixObject: the Stix-Object Indicator
529+
:return Indicator object
530+
"""
531+
532+
def import_from_stix2(self, **kwargs):
533+
stix_object = kwargs.get("stixObject", None)
534+
extras = kwargs.get("extras", {})
535+
update = kwargs.get("update", False)
536+
if stix_object is not None:
537+
pattern_type = "stix"
538+
if CustomProperties.PATTERN_TYPE in stix_object:
539+
pattern_type = stix_object[CustomProperties.PATTERN_TYPE]
540+
elif "pattern_type" in stix_object:
541+
pattern_type = stix_object["pattern_type"]
542+
return self.create(
543+
name=stix_object["name"] if "name" in stix_object else "",
544+
description=self.opencti.stix2.convert_markdown(
545+
stix_object["description"]
546+
)
547+
if "description" in stix_object
548+
else "",
549+
indicator_pattern=stix_object[CustomProperties.INDICATOR_PATTERN]
550+
if CustomProperties.INDICATOR_PATTERN in stix_object
551+
else stix_object["pattern"],
552+
main_observable_type=stix_object[CustomProperties.OBSERVABLE_TYPE]
553+
if CustomProperties.OBSERVABLE_TYPE in stix_object
554+
else "Unknown",
555+
pattern_type=pattern_type,
556+
valid_from=stix_object["valid_from"]
557+
if "valid_from" in stix_object
558+
else None,
559+
valid_until=stix_object["valid_until"]
560+
if "valid_until" in stix_object
561+
else None,
562+
score=stix_object[CustomProperties.SCORE]
563+
if CustomProperties.SCORE in stix_object
564+
else None,
565+
confidence=stix_object["confidence"]
566+
if "confidence" in stix_object
567+
else 50,
568+
detection=stix_object[CustomProperties.DETECTION]
569+
if CustomProperties.DETECTION in stix_object
570+
else None,
571+
id=stix_object[CustomProperties.ID]
572+
if CustomProperties.ID in stix_object
573+
else None,
574+
stix_id_key=stix_object["id"] if "id" in stix_object else None,
575+
created=stix_object["created"] if "created" in stix_object else None,
576+
modified=stix_object["modified"] if "modified" in stix_object else None,
577+
createdByRef=extras["created_by_ref_id"]
578+
if "created_by_ref_id" in extras
579+
else None,
580+
markingDefinitions=extras["marking_definitions_ids"]
581+
if "marking_definitions_ids" in extras
582+
else None,
583+
tags=extras["tags_ids"] if "tags_ids" in extras else [],
584+
killChainPhases=extras["kill_chain_phases_ids"]
585+
if "kill_chain_phases_ids" in extras
586+
else [],
587+
update=update,
588+
)
589+
else:
590+
self.opencti.log(
591+
"error", "[opencti_attack_pattern] Missing parameters: stixObject"
592+
)
593+
503594
"""
504595
Export an Indicator object in STIX2
505596
@@ -536,9 +627,9 @@ def to_stix2(self, **kwargs):
536627
entity["valid_until"]
537628
)
538629
if self.opencti.not_empty(entity["pattern_type"]):
539-
indicator[CustomProperties.PATTERN_TYPE] = entity["pattern_type"]
630+
indicator["pattern_type"] = entity["pattern_type"]
540631
else:
541-
indicator[CustomProperties.PATTERN_TYPE] = "stix"
632+
indicator["pattern_type"] = "stix"
542633
indicator["created"] = self.opencti.stix2.format_date(entity["created"])
543634
indicator["modified"] = self.opencti.stix2.format_date(entity["modified"])
544635
if self.opencti.not_empty(entity["alias"]):

0 commit comments

Comments
 (0)