Skip to content

Commit ca39431

Browse files
committed
chg: [stix export] Made the parse_json_content method for actual content and added parse_file_content to pass filename(s)
1 parent 978f349 commit ca39431

File tree

4 files changed

+66
-58
lines changed

4 files changed

+66
-58
lines changed

misp_stix_converter/misp2stix/exportparser.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
# -*- coding: utf-8 -*-
22
#!/usr/bin/env python3
33

4+
import json
45
import traceback
56
from .stix1_mapping import MISPtoSTIX1Mapping
67
from .stix20_mapping import MISPtoSTIX20Mapping
78
from .stix21_mapping import MISPtoSTIX21Mapping
89
from abc import ABCMeta
910
from collections import defaultdict
1011
from datetime import datetime, timezone
12+
from io import BufferedIOBase, TextIOBase
13+
from pathlib import Path
1114
from pymisp import MISPAttribute, MISPObject
12-
from typing import Optional, Union
15+
from typing import IO, Optional, Union
1316

1417

1518
class MISPtoSTIXParser(metaclass=ABCMeta):
@@ -42,6 +45,18 @@ def warnings(self) -> dict:
4245
for identifier, warnings in self.__warnings.items()
4346
}
4447

48+
def parse_json_file(self, filename: Path | str):
49+
with open(filename, 'rt', encoding='utf-8') as f:
50+
json_content = json.loads(f.read())
51+
self._parse_json_content(json_content)
52+
53+
def parse_json_content(self, json_content: IO | str | bytes | dict | list):
54+
if isinstance(json_content, (BufferedIOBase, TextIOBase)):
55+
json_content = json_content.read()
56+
if isinstance(json_content, (str, bytes)):
57+
json_content = json.loads(json_content)
58+
self._parse_json_content(json_content)
59+
4560
############################################################################
4661
# COMMON PARSING FUNCTIONS #
4762
############################################################################

misp_stix_converter/misp2stix/misp_to_stix1.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,11 +1102,9 @@ def __init__(self, orgname: str, version: str):
11021102
self._identifier = 'attributes collection'
11031103
self._ids = set()
11041104

1105-
def parse_json_content(self, filename):
1106-
with open(filename, 'rt', encoding='utf-8') as f:
1107-
attributes = json.loads(f.read())
1108-
if attributes.get('response') is not None:
1109-
attributes = attributes['response']
1105+
def _parse_json_content(self, attributes: dict | list):
1106+
if attributes.get('response') is not None:
1107+
attributes = attributes['response']
11101108
self._stix_package = STIXPackage()
11111109
if 'Attribute' in attributes:
11121110
attributes = attributes['Attribute']
@@ -1152,9 +1150,7 @@ class MISPtoSTIX1EventsParser(MISPtoSTIX1Parser):
11521150
def __init__(self, orgname: str, version: str):
11531151
super().__init__(orgname, version)
11541152

1155-
def parse_json_content(self, filename):
1156-
with open(filename, 'rt', encoding='utf-8') as f:
1157-
json_content = json.loads(f.read())
1153+
def _parse_json_content(self, json_content: dict):
11581154
if json_content.get('response'):
11591155
package = _stix_package(self._orgname, self._version, header=False)
11601156
for event in json_content['response']:

misp_stix_converter/misp2stix/misp_to_stix2.py

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#!/usr/bin/env python3
22
# -*- coding: utf-8 -*-
33

4-
import io
54
import json
65
import os
76
import re
@@ -10,7 +9,7 @@
109
from base64 import b64encode
1110
from collections import defaultdict
1211
from datetime import datetime
13-
from dateutil import parser
12+
from io import BytesIO
1413
from pathlib import Path
1514
from pymisp import (
1615
MISPAttribute, MISPEvent, MISPEventReport, MISPGalaxy, MISPGalaxyCluster,
@@ -83,31 +82,6 @@ def __init__(self, interoperability: bool):
8382
}
8483
self._markings = {}
8584

86-
def parse_json_content(self, filename: Union[Path, str]):
87-
self._results_handling_function = '_append_SDO'
88-
with open(filename, 'rt', encoding='utf-8') as f:
89-
json_content = json.loads(f.read())
90-
if 'response' in json_content:
91-
json_content = json_content['response']
92-
if isinstance(json_content, list):
93-
if not self.__initiated:
94-
self._initiate_events_parsing()
95-
for event in json_content:
96-
self._parse_misp_event(event)
97-
self.__index = len(self.__objects)
98-
else:
99-
self.parse_misp_attributes(json_content)
100-
else:
101-
if isinstance(json_content, list):
102-
for content in json_content:
103-
if 'Attribute' in content:
104-
self.parse_misp_attribute(content)
105-
else:
106-
if 'Event' in json_content or 'info' in json_content:
107-
self.parse_misp_event(json_content)
108-
else:
109-
self.parse_misp_attributes(json_content)
110-
11185
def parse_misp_attribute(self, attribute: Union[MISPAttribute, dict]):
11286
self._results_handling_function = '_append_SDO_without_refs'
11387
self._identifier = 'attribute feed'
@@ -143,7 +117,30 @@ def parse_misp_event(self, misp_event: Union[MISPEvent, dict]):
143117
self._initiate_events_parsing()
144118
self._parse_misp_event(misp_event)
145119

146-
def _parse_misp_event(self, misp_event: Union[MISPEvent, dict]):
120+
def _parse_json_content(self, json_content: dict | list):
121+
self._results_handling_function = '_append_SDO'
122+
if 'response' in json_content:
123+
json_content = json_content['response']
124+
if isinstance(json_content, list):
125+
if not self.__initiated:
126+
self._initiate_events_parsing()
127+
for event in json_content:
128+
self._parse_misp_event(event)
129+
self.__index = len(self.__objects)
130+
else:
131+
self.parse_misp_attributes(json_content)
132+
else:
133+
if isinstance(json_content, list):
134+
for content in json_content:
135+
if 'Attribute' in content:
136+
self.parse_misp_attribute(content)
137+
else:
138+
if 'Event' in json_content or 'info' in json_content:
139+
self.parse_misp_event(json_content)
140+
else:
141+
self.parse_misp_attributes(json_content)
142+
143+
def _parse_misp_event(self, misp_event: MISPEvent | dict):
147144
if 'Event' in misp_event:
148145
misp_event = misp_event['Event']
149146
self._misp_event = misp_event
@@ -173,18 +170,18 @@ def _parse_misp_event(self, misp_event: Union[MISPEvent, dict]):
173170
self.__objects.insert(self.__index, report)
174171

175172
def _define_stix_object_id(
176-
self, feature: str, misp_object: Union[MISPObject, dict]) -> str:
173+
self, feature: str, misp_object: MISPObject | dict) -> str:
177174
return f"{feature}--{misp_object['uuid']}"
178175

179176
def _define_stix_object_id_from_attribute(
180-
self, feature: str, attribute: Union[MISPAttribute, dict]) -> str:
177+
self, feature: str, attribute: MISPAttribute | dict) -> str:
181178
attribute_uuid = attribute['uuid']
182179
stix_id = f'{feature}--{attribute_uuid}'
183180
self._event_report_matching[attribute_uuid].append(stix_id)
184181
return stix_id
185182

186183
def _define_stix_object_id_from_object(
187-
self, feature: str, misp_object: Union[MISPObject, dict]) -> str:
184+
self, feature: str, misp_object: MISPObject | dict) -> str:
188185
object_uuid = misp_object['uuid']
189186
stix_id = f'{feature}--{object_uuid}'
190187
self._event_report_matching[object_uuid].append(stix_id)
@@ -3870,7 +3867,7 @@ def _parse_lnk_args(self, attributes: dict, misp_object) -> dict:
38703867
return file_args
38713868

38723869
def _parse_malware_sample_additional_fields(
3873-
self, data: Union[io.BytesIO, str]) -> dict:
3870+
self, data: BytesIO | str) -> dict:
38743871
if not isinstance(data, str):
38753872
data = b64encode(data.getvalue()).decode()
38763873
return {
@@ -3879,7 +3876,7 @@ def _parse_malware_sample_additional_fields(
38793876
}
38803877

38813878
def _parse_malware_sample_args(
3882-
self, value: str, data: Union[io.BytesIO, str]) -> dict:
3879+
self, value: str, data: BytesIO | str) -> dict:
38833880
args = {'allow_custom': True}
38843881
for separator in self.composite_separators:
38853882
if separator in value:
@@ -3897,7 +3894,7 @@ def _parse_malware_sample_args(
38973894
return args
38983895

38993896
def _parse_malware_sample_custom_args(
3900-
self, value: str, data: Union[io.BytesIO, str]) -> dict:
3897+
self, value: str, data: BytesIO | str) -> dict:
39013898
args = {'allow_custom': True, 'x_misp_malware_sample': value}
39023899
args.update(self._parse_malware_sample_additional_fields(data))
39033900
return args

misp_stix_converter/misp_stix_converter.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ def misp_attribute_collection_to_stix1(
269269
filename = input_files[0]
270270
if isinstance(filename, str):
271271
filename = Path(filename).resolve()
272-
parser.parse_json_content(filename)
272+
parser.parse_json_file(filename)
273273
name = _check_filename(
274274
filename.parent, f'{filename.name}.out', output_dir, output_name
275275
)
@@ -290,7 +290,7 @@ def misp_attribute_collection_to_stix1(
290290
if in_memory:
291291
for filename in input_files:
292292
try:
293-
parser.parse_json_content(filename)
293+
parser.parse_json_file(filename)
294294
current = parser.stix_package
295295
for campaign in current.campaigns:
296296
stix_package.add_campaign(campaign)
@@ -319,7 +319,7 @@ def misp_attribute_collection_to_stix1(
319319
tmp_path = name.parent
320320
for filename in input_files:
321321
try:
322-
parser.parse_json_content(filename)
322+
parser.parse_json_file(filename)
323323
package = parser.stix_package
324324
for feature in _STIX1_features:
325325
values = getattr(package, feature)
@@ -364,7 +364,7 @@ def misp_attribute_collection_to_stix1(
364364
try:
365365
if isinstance(filename, str):
366366
filename = Path(filename).resolve()
367-
parser.parse_json_content(filename)
367+
parser.parse_json_file(filename)
368368
name = _check_output(
369369
filename.parent, f'{filename.name}.out', output_dir
370370
)
@@ -400,7 +400,7 @@ def misp_event_collection_to_stix1(
400400
try:
401401
if not isinstance(filename, Path):
402402
filename = Path(filename).resolve()
403-
parser.parse_json_content(filename)
403+
parser.parse_json_file(filename)
404404
name = _check_filename(
405405
filename.parent, f'{filename.name}.out', output_dir, output_name
406406
)
@@ -421,7 +421,7 @@ def misp_event_collection_to_stix1(
421421
try:
422422
if not isinstance(filename, Path):
423423
filename = Path(filename).resolve()
424-
parser.parse_json_content(filename)
424+
parser.parse_json_file(filename)
425425
if parser.stix_package.related_packages is not None:
426426
for related_package in parser.stix_package.related_packages:
427427
stix_package.add_related_package(related_package)
@@ -440,7 +440,7 @@ def misp_event_collection_to_stix1(
440440
try:
441441
if not isinstance(filename, Path):
442442
filename = Path(filename).resolve()
443-
parser.parse_json_content(filename)
443+
parser.parse_json_file(filename)
444444
content = _get_events(parser.stix_package, return_format)
445445
with open(name, 'wt', encoding='utf-8') as f:
446446
f.write(f'{header}{content}')
@@ -450,7 +450,7 @@ def misp_event_collection_to_stix1(
450450
try:
451451
if not isinstance(filename, Path):
452452
filename = Path(filename).resolve()
453-
parser.parse_json_content(filename)
453+
parser.parse_json_file(filename)
454454
content = _get_events(parser.stix_package, return_format)
455455
with open(name, 'at', encoding='utf-8') as f:
456456
f.write(f'{separator}{content}')
@@ -465,7 +465,7 @@ def misp_event_collection_to_stix1(
465465
try:
466466
if not isinstance(filename, Path):
467467
filename = Path(filename).resolve()
468-
parser.parse_json_content(filename)
468+
parser.parse_json_file(filename)
469469
name = _check_output(
470470
filename.parent, f'{filename.name}.out', output_dir
471471
)
@@ -493,7 +493,7 @@ def misp_collection_to_stix2(
493493
try:
494494
if not isinstance(filename, Path):
495495
filename = Path(filename).resolve()
496-
parser.parse_json_content(filename)
496+
parser.parse_json_file(filename)
497497
name = _check_filename(
498498
filename.parent, f'{filename.name}.out', output_dir, output_name
499499
)
@@ -509,7 +509,7 @@ def misp_collection_to_stix2(
509509
try:
510510
if not isinstance(filename, Path):
511511
filename = Path(filename).resolve()
512-
parser.parse_json_content(filename)
512+
parser.parse_json_file(filename)
513513
except Exception as exception:
514514
traceback['fails'].append(f'{filename} - {exception.__str__()}')
515515
if any(filename not in traceback.get('fails', []) for filename in input_files):
@@ -537,7 +537,7 @@ def misp_collection_to_stix2(
537537
filename = input_files[0]
538538
if not isinstance(filename, Path):
539539
filename = Path(filename).resolve()
540-
parser.parse_json_content(filename)
540+
parser.parse_json_file(filename)
541541
stix_objects = json.dumps(
542542
[parser.fetch_stix_objects], cls=STIXJSONEncoder, indent=4
543543
)
@@ -550,7 +550,7 @@ def misp_collection_to_stix2(
550550
try:
551551
if not isinstance(filename, Path):
552552
filename = Path(filename).resolve()
553-
parser.parse_json_content(filename)
553+
parser.parse_json_file(filename)
554554
stix_objects = json.dumps(
555555
[parser.fetch_stix_objects], cls=STIXJSONEncoder, indent=4
556556
)
@@ -572,7 +572,7 @@ def misp_collection_to_stix2(
572572
try:
573573
if not isinstance(filename, Path):
574574
filename = Path(filename).resolve()
575-
parser.parse_json_content(filename)
575+
parser.parse_json_file(filename)
576576
name = _check_output(
577577
filename.parent, f'{filename.name}.out', output_dir
578578
)
@@ -602,7 +602,7 @@ def misp_to_stix1(
602602
try:
603603
if not isinstance(filename, Path):
604604
filename = Path(filename).resolve()
605-
parser.parse_json_content(filename)
605+
parser.parse_json_file(filename)
606606
name = _check_filename(
607607
filename.parent, f'{filename.name}.out', output_dir, output_name
608608
)

0 commit comments

Comments
 (0)