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

Commit 39600e9

Browse files
author
Samuel Hassine
committed
#1 Add method to select observable and relations, with example
1 parent 77a0da5 commit 39600e9

File tree

6 files changed

+74
-5
lines changed

6 files changed

+74
-5
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# coding: utf-8
2+
3+
import os
4+
import yaml
5+
6+
from pycti.opencti import OpenCTI
7+
8+
# Load configuration
9+
config = yaml.load(open(os.path.dirname(__file__) + '/../config.yml'))
10+
11+
# File to import
12+
file_to_import = config['mitre']['repository_path_cti'] + '/enterprise-attack/enterprise-attack.json'
13+
14+
# OpenCTI initialization
15+
opencti = OpenCTI(config['opencti']['api_url'], config['opencti']['api_key'], config['opencti']['log_file'], config['opencti']['verbose'])
16+
17+
# Get observables and their context
18+
observables = opencti.get_stix_observables(10)
19+
20+
for observable in observables:
21+
observable_value = observable['observable_value']
22+
for relation in observable['stixRelations']:
23+
first_seen = relation['first_seen']
24+
last_seen = relation['last_seen']
25+
print('Observable with value "' + observable_value + '" (first_seen: ' + first_seen + ', last_seen: ' + last_seen + ')')

examples/stix2/export.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from opencti import OpenCTI
88

99
# Load configuration
10-
config = yaml.load(open(os.path.dirname(__file__) + '/config.yml'))
10+
config = yaml.load(open(os.path.dirname(__file__) + '/../config.yml'))
1111

1212
# Export file
1313
export_file = './exports/IntrusionSets.json'

examples/stix2/import.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from opencti import OpenCTI
77

88
# Load configuration
9-
config = yaml.load(open(os.path.dirname(__file__) + '/config.yml'))
9+
config = yaml.load(open(os.path.dirname(__file__) + '/../config.yml'))
1010

1111
# File to import
1212
file_to_import = config['mitre']['repository_path_cti'] + '/enterprise-attack/enterprise-attack.json'
@@ -15,4 +15,4 @@
1515
opencti = OpenCTI(config['opencti']['api_url'], config['opencti']['api_key'], config['opencti']['log_file'], config['opencti']['verbose'])
1616

1717
# Import the bundle
18-
opencti.stix2_import_bundle_from_file(file_to_import)
18+
opencti.stix2_import_bundle_from_file(file_to_import, False)

pycti/opencti.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ def parse_stix(self, data):
7070
data['observableRefs'] = self.parse_multiple(data['observableRefs'])
7171
if 'relationRefs' in data:
7272
data['relationRefs'] = self.parse_multiple(data['relationRefs'])
73+
if 'stixRelations' in data:
74+
data['stixRelations'] = self.parse_multiple(data['stixRelations'])
7375
return data
7476

7577
def check_existing_stix_domain_entity(self, stix_id=None, name=None, type=None):
@@ -81,6 +83,7 @@ def check_existing_stix_domain_entity(self, stix_id=None, name=None, type=None):
8183
return object_result
8284

8385
def update_settings_field(self, id, key, value):
86+
8487
self.log('Updating settings field ' + key + ' of ' + id + '...')
8588
query = """
8689
mutation SettingsEdit($id: ID!, $input: EditInput!) {
@@ -346,6 +349,8 @@ def get_stix_relation_by_id(self, id):
346349
description
347350
weight
348351
role_played
352+
score
353+
expiration
349354
first_seen
350355
last_seen
351356
created
@@ -365,6 +370,9 @@ def get_stix_relation_by_id(self, id):
365370
return result['data']['stixRelation']
366371

367372
def get_stix_relations(self, from_id=None, to_id=None, type='stix_relation', first_seen=None, last_seen=None):
373+
if type == 'revoked-by':
374+
return []
375+
368376
if first_seen is not None and last_seen is not None:
369377
first_seen = dateutil.parser.parse(first_seen)
370378
first_seen_start = (first_seen + datetime.timedelta(days=-1)).strftime('%Y-%m-%dT%H:%M:%S+00:00')
@@ -390,6 +398,8 @@ def get_stix_relations(self, from_id=None, to_id=None, type='stix_relation', fir
390398
description
391399
weight
392400
role_played
401+
score
402+
expiration
393403
first_seen
394404
last_seen
395405
created
@@ -436,6 +446,8 @@ def create_relation(self,
436446
last_seen,
437447
weight,
438448
role_played=None,
449+
score=None,
450+
expiration=None,
439451
id=None,
440452
stix_id=None,
441453
created=None,
@@ -458,6 +470,8 @@ def create_relation(self,
458470
'relationship_type': type,
459471
'description': description,
460472
'role_played': role_played,
473+
'score': score,
474+
'expiration': expiration,
461475
'first_seen': first_seen,
462476
'last_seen': last_seen,
463477
'weight': weight,
@@ -480,6 +494,8 @@ def create_relation_if_not_exists(self,
480494
last_seen,
481495
weight,
482496
role_played=None,
497+
score=None,
498+
expiration=None,
483499
id=None,
484500
stix_id=None,
485501
created=None,
@@ -522,6 +538,8 @@ def create_relation_if_not_exists(self,
522538
last_seen,
523539
weight,
524540
role_played,
541+
score,
542+
expiration,
525543
id,
526544
stix_id,
527545
created,
@@ -2807,6 +2825,10 @@ def get_stix_observable(self, id):
28072825
role_played
28082826
expiration
28092827
score
2828+
to {
2829+
id
2830+
name
2831+
}
28102832
}
28112833
}
28122834
}
@@ -2869,6 +2891,10 @@ def get_stix_observable_by_value(self, observable_value):
28692891
role_played
28702892
expiration
28712893
score
2894+
to {
2895+
id
2896+
name
2897+
}
28722898
}
28732899
}
28742900
}
@@ -2936,6 +2962,10 @@ def get_stix_observables(self, limit=10000):
29362962
role_played
29372963
expiration
29382964
score
2965+
to {
2966+
id
2967+
name
2968+
}
29392969
}
29402970
}
29412971
}
@@ -3443,6 +3473,12 @@ def resolve_role(self, relation_type, from_type, to_type):
34433473
'malware': {'from_role': 'indicator', 'to_role': 'characterize'},
34443474
'tool': {'from_role': 'indicator', 'to_role': 'characterize'},
34453475
}
3476+
},
3477+
'gathering': {
3478+
'sector': {
3479+
'sector': {'from_role': 'gather', 'to_role': 'part_of'},
3480+
'organization': {'from_role': 'gather', 'to_role': 'part_of'},
3481+
}
34463482
}
34473483
}
34483484
if relation_type in mapping and from_type in mapping[relation_type] and to_type in mapping[relation_type][

pycti/stix2.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,8 @@ def export_stix_relation(self, entity):
824824
'x_opencti_last_seen': entity['last_seen'],
825825
'x_opencti_weight': entity['weight'],
826826
'x_opencti_role_played': entity['role_played'],
827+
'x_opencti_score': entity['score'],
828+
'x_opencti_expiration': entity['expiration'],
827829
}
828830
return self.prepare_export(entity, stix_relation)
829831

@@ -872,7 +874,7 @@ def import_relationship(self, stix_relation, update=False):
872874
if date is None:
873875
date = datetime.datetime.utcnow().replace(microsecond=0, tzinfo=datetime.timezone.utc).isoformat()
874876

875-
stix_relation_id = self.opencti.create_relation_if_not_exists(
877+
stix_relation = self.opencti.create_relation_if_not_exists(
876878
source_id,
877879
source_type,
878880
target_id,
@@ -885,11 +887,17 @@ def import_relationship(self, stix_relation, update=False):
885887
'x_opencti_last_seen'] if 'x_opencti_last_seen' in stix_relation else date,
886888
stix_relation['x_opencti_weight'] if 'x_opencti_weight' in stix_relation else 4,
887889
stix_relation['x_opencti_role_played'] if 'x_opencti_role_played' in stix_relation else None,
890+
stix_relation['x_opencti_score'] if 'x_opencti_score' in stix_relation else None,
891+
stix_relation['x_opencti_expiration'] if 'x_opencti_expiration' in stix_relation else None,
888892
stix_relation['x_opencti_id'] if 'x_opencti_id' in stix_relation else None,
889893
stix_relation['id'] if 'id' in stix_relation else None,
890894
stix_relation['created'] if 'created' in stix_relation else None,
891895
stix_relation['modified'] if 'modified' in stix_relation else None,
892-
)['id']
896+
)
897+
if stix_relation is not None:
898+
stix_relation_id = stix_relation['id']
899+
else:
900+
return None
893901

894902
# External References
895903
external_references_ids = []

0 commit comments

Comments
 (0)