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

Commit 59e7aba

Browse files
author
Samuel Hassine
committed
[client] Fix relations creation in some cases (#47)
1 parent 0d034bb commit 59e7aba

File tree

4 files changed

+97
-27
lines changed

4 files changed

+97
-27
lines changed

CHANGELOG.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,70 @@
11
# Changelog
22

3+
## Version 2.1.5 (19/12/2019)
4+
5+
#### Enhancements:
6+
7+
- [#40](https://github.com/OpenCTI-Platform/client-python/issues/40) Handle indicators as observables AND indicators
8+
9+
---
10+
11+
## Version 2.1.4 (07/12/2019)
12+
13+
#### Bug Fixes:
14+
15+
- [#45](https://github.com/OpenCTI-Platform/client-python/issues/45) Indicators cannot be parsed
16+
17+
---
18+
19+
## Version 2.1.3 (05/12/2019)
20+
21+
#### Enhancements:
22+
23+
- [#41](https://github.com/OpenCTI-Platform/client-python/issues/41) Handle relations creation with first_seen and last_seen
24+
- [#39](https://github.com/OpenCTI-Platform/client-python/issues/39) Handle observed data as observables
25+
- [#37](https://github.com/OpenCTI-Platform/client-python/issues/37) Update the methods to be able to export all entities in STIX2
26+
- [#14](https://github.com/OpenCTI-Platform/client-python/issues/14) Refactor the client to make it more maintainable/understandable
27+
- [#13](https://github.com/OpenCTI-Platform/client-python/issues/13) Use **kwargs for all API client methods
28+
29+
---
30+
31+
## Version 2.0.1 (27/10/2019)
32+
33+
#### Enhancements:
34+
35+
- [#32](https://github.com/OpenCTI-Platform/client-python/issues/32) Introduce methods in API and connectors helper to store connectors states
36+
- [#28](https://github.com/OpenCTI-Platform/client-python/issues/28) removing commercial reports.
37+
38+
#### Bug Fixes:
39+
40+
- [#30](https://github.com/OpenCTI-Platform/client-python/issues/30) Use proper function to update observables
41+
42+
---
43+
44+
## Version 2.0.0 (23/10/2019)
45+
46+
#### Enhancements:
47+
48+
- [#25](https://github.com/OpenCTI-Platform/client-python/issues/25) Implement methods for export/import upload/download
49+
- [#24](https://github.com/OpenCTI-Platform/client-python/issues/24) Upgrade the library with methods for new generation connectors (2.0.0)
50+
- [#22](https://github.com/OpenCTI-Platform/client-python/issues/22) Handle update of all entities
51+
52+
#### Bug Fixes:
53+
54+
- [#26](https://github.com/OpenCTI-Platform/client-python/issues/26) Packaging problem
55+
- [#21](https://github.com/OpenCTI-Platform/client-python/issues/21) Case sensitivity
56+
- [#18](https://github.com/OpenCTI-Platform/client-python/issues/18) Possible race condition when creating non-existing objects?
57+
58+
---
59+
60+
## Version 1.2.13 (01/08/2019)
61+
62+
#### Bug Fixes:
63+
64+
- [#15](https://github.com/OpenCTI-Platform/client-python/issues/15) Queue delete leads to messages lost
65+
66+
---
67+
368
## Version 1.2.12 (21/07/2019)
469

570
#### Enhancements:

pycti/api/opencti_api_client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1762,7 +1762,7 @@ def resolve_role(self, relation_type, from_type, to_type):
17621762
relation_type = relation_type.lower()
17631763
from_type = from_type.lower()
17641764
from_type = 'observable' if ((ObservableTypes.has_value(from_type) and (
1765-
relation_type == 'localization' or relation_type == 'gathering')) or from_type == 'stix-observable'
1765+
relation_type == 'localization' or relation_type == 'gathering')) or from_type == 'stix-observable'
17661766
) else from_type
17671767
to_type = to_type.lower()
17681768
mapping = {
@@ -1887,7 +1887,7 @@ def resolve_role(self, relation_type, from_type, to_type):
18871887
'country': {'from_role': 'localized', 'to_role': 'location'},
18881888
'city': {'from_role': 'localized', 'to_role': 'location'}
18891889
},
1890-
'relation': {
1890+
'stix_relation': {
18911891
'region': {'from_role': 'localized', 'to_role': 'location'},
18921892
'country': {'from_role': 'localized', 'to_role': 'location'},
18931893
'city': {'from_role': 'localized', 'to_role': 'location'}

pycti/utils/opencti_stix2.py

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,9 @@ def extract_embedded_relationships(self, stix_object, types=None):
115115
created_by_ref_result = self.mapping_cache[created_by_ref]
116116
else:
117117
created_by_ref_result = self.opencti.stix_domain_entity.read(id=created_by_ref)
118+
if created_by_ref_result is not None:
119+
self.mapping_cache[created_by_ref] = {'id': created_by_ref_result['id'], 'type': created_by_ref_result['entity_type']}
118120
if created_by_ref_result is not None:
119-
self.mapping_cache[created_by_ref] = {'id': created_by_ref_result['id']}
120121
created_by_ref_id = created_by_ref_result['id']
121122

122123
# Object Marking Refs
@@ -127,31 +128,32 @@ def extract_embedded_relationships(self, stix_object, types=None):
127128
object_marking_ref_result = self.mapping_cache[object_marking_ref]
128129
else:
129130
object_marking_ref_result = self.opencti.marking_definition.read(id=object_marking_ref)
131+
if object_marking_ref_result is not None:
132+
self.mapping_cache[object_marking_ref] = {'id': object_marking_ref_result['id'], 'type': object_marking_ref_result['entity_type']}
130133
if object_marking_ref_result is not None:
131-
self.mapping_cache[object_marking_ref] = {'id': object_marking_ref_result['id']}
132134
marking_definitions_ids.append(object_marking_ref_result['id'])
133135

134-
# TODO Import tags
135136
# Object Tags
136137
tags_ids = []
137-
# if CustomProperties.TAG_TYPE in stix_object:
138-
# for tag in stix_object[CustomProperties.TAG_TYPE]:
139-
# if tag['id'] in self.mapping_cache:
140-
# tag_result = self.mapping_cache[tag['id']]
141-
# else:
142-
# object_marking_ref_result = self.opencti.tag.read(id=object_marking_ref)
143-
# if object_marking_ref_result is not None:
144-
# self.mapping_cache[object_marking_ref] = {'id': object_marking_ref_result['id']}
145-
# marking_definitions_ids.append(object_marking_ref_result['id'])
138+
if CustomProperties.TAG_TYPE in stix_object:
139+
for tag in stix_object[CustomProperties.TAG_TYPE]:
140+
if tag['id'] in self.mapping_cache:
141+
tag_result = self.mapping_cache[tag['id']]
142+
else:
143+
tag_result = self.opencti.tag.read(id=tag['id'])
144+
if tag_result is not None:
145+
self.mapping_cache[tag['id']] = {'id': tag_result['id']}
146+
if tag_result is not None:
147+
tags_ids.append(tag_result['id'])
146148

147149
# Kill Chain Phases
148150
kill_chain_phases_ids = []
149151
if 'kill_chain_phases' in stix_object:
150152
for kill_chain_phase in stix_object['kill_chain_phases']:
151153
if kill_chain_phase['phase_name'] in self.mapping_cache:
152-
kill_chain_phase_id = self.mapping_cache[kill_chain_phase['phase_name']]['id']
154+
kill_chain_phase = self.mapping_cache[kill_chain_phase['phase_name']]['id']
153155
else:
154-
kill_chain_phase_id = self.opencti.kill_chain_phase.create(
156+
kill_chain_phase = self.opencti.kill_chain_phase.create(
155157
kill_chain_name=kill_chain_phase['kill_chain_name'],
156158
phase_name=kill_chain_phase['phase_name'],
157159
phase_order=kill_chain_phase[
@@ -162,9 +164,9 @@ def extract_embedded_relationships(self, stix_object, types=None):
162164
CustomProperties.CREATED] if CustomProperties.CREATED in kill_chain_phase else None,
163165
modified=kill_chain_phase[
164166
CustomProperties.MODIFIED] if CustomProperties.MODIFIED in kill_chain_phase else None,
165-
)['id']
166-
self.mapping_cache[kill_chain_phase['phase_name']] = {'id': kill_chain_phase_id}
167-
kill_chain_phases_ids.append(kill_chain_phase_id)
167+
)
168+
self.mapping_cache[kill_chain_phase['phase_name']] = {'id': kill_chain_phase['id'], 'type': kill_chain_phase['entity_type']}
169+
kill_chain_phases_ids.append(kill_chain_phase['id'])
168170

169171
# Object refs
170172
object_refs_ids = []
@@ -174,11 +176,13 @@ def extract_embedded_relationships(self, stix_object, types=None):
174176
object_ref_result = self.mapping_cache[object_ref]
175177
elif 'relationship' in object_ref:
176178
object_ref_result = self.opencti.stix_relation.read(id=object_ref)
179+
if object_ref_result is not None:
180+
self.mapping_cache[object_ref] = {'id': object_ref_result['id'], 'type': object_ref_result['entity_type']}
177181
else:
178182
object_ref_result = self.opencti.stix_entity.read(id=object_ref)
179-
183+
if object_ref_result is not None:
184+
self.mapping_cache[object_ref] = {'id': object_ref_result['id'], 'type': object_ref_result['entity_type']}
180185
if object_ref_result is not None:
181-
self.mapping_cache[object_ref] = {'id': object_ref_result['id']}
182186
object_refs_ids.append(object_ref_result['id'])
183187

184188
# External References
@@ -284,6 +288,7 @@ def extract_embedded_relationships(self, stix_object, types=None):
284288
return {
285289
'created_by_ref': created_by_ref_id,
286290
'marking_definitions': marking_definitions_ids,
291+
'tags': tags_ids,
287292
'kill_chain_phases': kill_chain_phases_ids,
288293
'object_refs': object_refs_ids,
289294
'external_references': external_references_ids,
@@ -397,8 +402,8 @@ def import_relationship(self, stix_relation, update=False, types=None):
397402
else:
398403
source_ref = stix_relation['source_ref']
399404
if source_ref in self.mapping_cache:
400-
source_id = self.mapping_cache[stix_relation['source_ref']]['id']
401-
source_type = self.mapping_cache[stix_relation['source_ref']]['type']
405+
source_id = self.mapping_cache[source_ref]['id']
406+
source_type = self.mapping_cache[source_ref]['type']
402407
else:
403408
stix_object_result = self.opencti.stix_entity.read(id=source_ref)
404409
if stix_object_result is not None:
@@ -413,8 +418,8 @@ def import_relationship(self, stix_relation, update=False, types=None):
413418
else:
414419
target_ref = stix_relation['target_ref']
415420
if target_ref in self.mapping_cache:
416-
target_id = self.mapping_cache[stix_relation['target_ref']]['id']
417-
target_type = self.mapping_cache[stix_relation['target_ref']]['type']
421+
target_id = self.mapping_cache[target_ref]['id']
422+
target_type = self.mapping_cache[target_ref]['type']
418423
else:
419424
stix_object_result = self.opencti.stix_entity.read(id=target_ref)
420425
if stix_object_result is not None:
@@ -465,7 +470,7 @@ def import_relationship(self, stix_relation, update=False, types=None):
465470
CustomProperties.IGNORE_DATES] if CustomProperties.IGNORE_DATES in stix_relation else None,
466471
)
467472
if stix_relation_result is not None:
468-
self.mapping_cache[stix_relation['id']] = {'id': stix_relation_result['id']}
473+
self.mapping_cache[stix_relation['id']] = {'id': stix_relation_result['id'], 'type': stix_relation_result['entity_type']}
469474
else:
470475
return None
471476

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
print("warning: pypandoc module not found, could not convert Markdown to RST")
1414
read_md = lambda f: open(f, 'r').read()
1515

16-
VERSION = "2.1.5"
16+
VERSION = "2.1.6"
1717

1818

1919
class VerifyVersionCommand(install):

0 commit comments

Comments
 (0)