assemblyline-v4-service 4.5.1.dev231__py3-none-any.whl → 4.5.1.dev233__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of assemblyline-v4-service might be problematic. Click here for more details.
- assemblyline_v4_service/VERSION +1 -1
- assemblyline_v4_service/common/ontology_helper.py +37 -31
- {assemblyline_v4_service-4.5.1.dev231.dist-info → assemblyline_v4_service-4.5.1.dev233.dist-info}/METADATA +7 -7
- {assemblyline_v4_service-4.5.1.dev231.dist-info → assemblyline_v4_service-4.5.1.dev233.dist-info}/RECORD +8 -8
- {assemblyline_v4_service-4.5.1.dev231.dist-info → assemblyline_v4_service-4.5.1.dev233.dist-info}/WHEEL +1 -1
- test/test_common/test_ontology_helper.py +65 -5
- {assemblyline_v4_service-4.5.1.dev231.dist-info → assemblyline_v4_service-4.5.1.dev233.dist-info}/LICENCE.md +0 -0
- {assemblyline_v4_service-4.5.1.dev231.dist-info → assemblyline_v4_service-4.5.1.dev233.dist-info}/top_level.txt +0 -0
assemblyline_v4_service/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.5.1.
|
|
1
|
+
4.5.1.dev233
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import os
|
|
3
3
|
from collections import defaultdict
|
|
4
|
-
from typing import Dict, Optional
|
|
4
|
+
from typing import Any, Dict, Optional, List, Tuple
|
|
5
5
|
|
|
6
6
|
from assemblyline_v4_service.common import helper
|
|
7
|
+
from assemblyline_v4_service.common.result import HEUR_LIST, ResultSection
|
|
7
8
|
|
|
8
9
|
from assemblyline.common import forge
|
|
9
10
|
from assemblyline.common.dict_utils import flatten, get_dict_fingerprint_hash, unflatten
|
|
@@ -18,9 +19,30 @@ ONTOLOGY_CLASS_TO_FIELD = {
|
|
|
18
19
|
NetworkConnection: "netflow"
|
|
19
20
|
}
|
|
20
21
|
|
|
22
|
+
if not HEUR_LIST:
|
|
23
|
+
# Get heuristics of service if not already set
|
|
24
|
+
HEUR_LIST = helper.get_heuristics()
|
|
25
|
+
|
|
21
26
|
Classification = forge.get_classification()
|
|
22
27
|
|
|
23
28
|
|
|
29
|
+
# Cleanup invalid tagging from service results
|
|
30
|
+
def validate_tags(tag_map: Dict[str, List[str]]) -> Dict[str, List[str]]:
|
|
31
|
+
tag_map, _ = construct_safe(Tagging, unflatten(tag_map))
|
|
32
|
+
tag_map = flatten(tag_map.as_primitives(strip_null=True))
|
|
33
|
+
return tag_map
|
|
34
|
+
|
|
35
|
+
# Merge tags
|
|
36
|
+
def merge_tags(tag_a: Dict[str, List[str]], tag_b: Dict[str, List[str]]) -> Dict[str, List[str]]:
|
|
37
|
+
if not tag_a:
|
|
38
|
+
return tag_b
|
|
39
|
+
|
|
40
|
+
elif not tag_b:
|
|
41
|
+
return tag_a
|
|
42
|
+
|
|
43
|
+
all_keys = list(tag_a.keys()) + list(tag_b.keys())
|
|
44
|
+
return {key: list(set(tag_a.get(key, []) + tag_b.get(key, []))) for key in all_keys}
|
|
45
|
+
|
|
24
46
|
class OntologyHelper:
|
|
25
47
|
def __init__(self, logger, service_name) -> None:
|
|
26
48
|
self.log = logger
|
|
@@ -84,32 +106,12 @@ class OntologyHelper:
|
|
|
84
106
|
|
|
85
107
|
ontology['results'].update(self.results)
|
|
86
108
|
|
|
87
|
-
def
|
|
88
|
-
|
|
89
|
-
heuristics = helper.get_heuristics()
|
|
90
|
-
|
|
91
|
-
def preprocess_result_for_dump(sections, current_max, heur_tag_map, tag_map):
|
|
109
|
+
def _preprocess_result_for_dump(self, sections: List[ResultSection], current_max: str,
|
|
110
|
+
heur_tag_map: Dict[str, Dict[str, Any]], tag_map: Dict[str, List[str]], score: int) -> Tuple[str, Dict[str, Dict[str, Any]], Dict[str, List[str]], int]:
|
|
92
111
|
for section in sections:
|
|
93
112
|
# Determine max classification of the overall result
|
|
94
113
|
current_max = Classification.max_classification(section.classification, current_max)
|
|
95
114
|
|
|
96
|
-
# Cleanup invalid tagging from service results
|
|
97
|
-
def validate_tags(tag_map):
|
|
98
|
-
tag_map, _ = construct_safe(Tagging, unflatten(tag_map))
|
|
99
|
-
tag_map = flatten(tag_map.as_primitives(strip_null=True))
|
|
100
|
-
return tag_map
|
|
101
|
-
|
|
102
|
-
# Merge tags
|
|
103
|
-
def merge_tags(tag_a, tag_b):
|
|
104
|
-
if not tag_a:
|
|
105
|
-
return tag_b
|
|
106
|
-
|
|
107
|
-
elif not tag_b:
|
|
108
|
-
return tag_a
|
|
109
|
-
|
|
110
|
-
all_keys = list(tag_a.keys()) + list(tag_b.keys())
|
|
111
|
-
return {key: list(set(tag_a.get(key, []) + tag_b.get(key, []))) for key in all_keys}
|
|
112
|
-
|
|
113
115
|
# Append tags raised by the service, if any
|
|
114
116
|
section_tags = validate_tags(section.tags)
|
|
115
117
|
if section_tags:
|
|
@@ -117,8 +119,8 @@ class OntologyHelper:
|
|
|
117
119
|
|
|
118
120
|
# Append tags associated to heuristics raised by the service, if any
|
|
119
121
|
if section.heuristic:
|
|
120
|
-
heur =
|
|
121
|
-
key = f'{
|
|
122
|
+
heur = HEUR_LIST[section.heuristic.heur_id]
|
|
123
|
+
key = f'{self.service.upper()}_{heur.heur_id}'
|
|
122
124
|
heur_tag_map[key].update({
|
|
123
125
|
"heur_id": key,
|
|
124
126
|
"name": heur.name,
|
|
@@ -126,24 +128,27 @@ class OntologyHelper:
|
|
|
126
128
|
"score": heur.score,
|
|
127
129
|
"times_raised": heur_tag_map[key]["times_raised"] + 1
|
|
128
130
|
})
|
|
131
|
+
score += section.heuristic.score
|
|
129
132
|
|
|
130
133
|
# Recurse through subsections
|
|
131
134
|
if section.subsections:
|
|
132
|
-
current_max, heur_tag_map, tag_map =
|
|
133
|
-
section.subsections, current_max, heur_tag_map, tag_map)
|
|
135
|
+
current_max, heur_tag_map, tag_map = self._preprocess_result_for_dump(
|
|
136
|
+
section.subsections, current_max, heur_tag_map, tag_map, score)
|
|
134
137
|
|
|
135
|
-
return current_max, heur_tag_map, tag_map
|
|
138
|
+
return current_max, heur_tag_map, tag_map, score
|
|
136
139
|
|
|
140
|
+
def _attach_ontology(self, request, working_dir) -> Optional[str]:
|
|
137
141
|
if not request.result or not request.result.sections:
|
|
138
142
|
# No service results, therefore no ontological output
|
|
139
143
|
return
|
|
140
144
|
|
|
141
|
-
max_result_classification, heur_tag_map, tag_map =
|
|
145
|
+
max_result_classification, heur_tag_map, tag_map, score = self._preprocess_result_for_dump(
|
|
142
146
|
sections=request.result.sections,
|
|
143
147
|
current_max=Classification.max_classification(request.task.min_classification,
|
|
144
148
|
request.task.service_default_result_classification),
|
|
145
149
|
heur_tag_map=defaultdict(lambda: {"tags": dict(), "times_raised": int()}),
|
|
146
|
-
tag_map=defaultdict(list)
|
|
150
|
+
tag_map=defaultdict(list),
|
|
151
|
+
score=0)
|
|
147
152
|
|
|
148
153
|
if not heur_tag_map and not tag_map and not self._result_parts:
|
|
149
154
|
# No heuristics, tagging, or ontologies found, therefore informational results
|
|
@@ -168,7 +173,8 @@ class OntologyHelper:
|
|
|
168
173
|
},
|
|
169
174
|
"results": {
|
|
170
175
|
"tags": tag_map,
|
|
171
|
-
"heuristics": list(heur_tag_map.values())
|
|
176
|
+
"heuristics": list(heur_tag_map.values()),
|
|
177
|
+
"score": score
|
|
172
178
|
}
|
|
173
179
|
}
|
|
174
180
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: assemblyline-v4-service
|
|
3
|
-
Version: 4.5.1.
|
|
3
|
+
Version: 4.5.1.dev233
|
|
4
4
|
Summary: Assemblyline 4 - Service base
|
|
5
5
|
Home-page: https://github.com/CybercentreCanada/assemblyline-v4-service/
|
|
6
6
|
Author: CCCS Assemblyline development team
|
|
@@ -24,15 +24,15 @@ Requires-Dist: assemblyline-core
|
|
|
24
24
|
Requires-Dist: cart
|
|
25
25
|
Requires-Dist: fuzzywuzzy
|
|
26
26
|
Requires-Dist: pefile
|
|
27
|
-
Requires-Dist: pillow
|
|
27
|
+
Requires-Dist: pillow!=10.1.0,!=10.2.0
|
|
28
28
|
Requires-Dist: python-Levenshtein
|
|
29
29
|
Requires-Dist: regex
|
|
30
30
|
Provides-Extra: updater
|
|
31
|
-
Requires-Dist: gunicorn[gevent]
|
|
32
|
-
Requires-Dist: flask
|
|
33
|
-
Requires-Dist: gitpython
|
|
34
|
-
Requires-Dist: git-remote-codecommit
|
|
35
|
-
Requires-Dist: psutil
|
|
31
|
+
Requires-Dist: gunicorn[gevent]; extra == "updater"
|
|
32
|
+
Requires-Dist: flask; extra == "updater"
|
|
33
|
+
Requires-Dist: gitpython; extra == "updater"
|
|
34
|
+
Requires-Dist: git-remote-codecommit; extra == "updater"
|
|
35
|
+
Requires-Dist: psutil; extra == "updater"
|
|
36
36
|
|
|
37
37
|
# Assemblyline 4 - Service Base
|
|
38
38
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
assemblyline_v4_service/VERSION,sha256=
|
|
1
|
+
assemblyline_v4_service/VERSION,sha256=Z6ozwNHb47WpLFd4QhbnMbJ7bL5wRoGPPh3JUf5voM4,13
|
|
2
2
|
assemblyline_v4_service/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
3
|
assemblyline_v4_service/healthz.py,sha256=sS1cFkDLw8hUPMpj7tbHXFv8ZmHcazrwZ0l6oQDwwkQ,1575
|
|
4
4
|
assemblyline_v4_service/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -9,7 +9,7 @@ assemblyline_v4_service/common/api.py,sha256=Xzp8j4HCCfjPvNSGKiZl5ttH2_Itg47cjlH
|
|
|
9
9
|
assemblyline_v4_service/common/base.py,sha256=4rnK_183qsSfkRkuVp_0wy-haW49umx4jJIC0OalGDM,14218
|
|
10
10
|
assemblyline_v4_service/common/helper.py,sha256=xs9quuf-M1JOdKieBqOmWaOece0CtzXFhhe85xQYmuY,3289
|
|
11
11
|
assemblyline_v4_service/common/ocr.py,sha256=3fV0PyY3oui_ucAM9dkolP0VRYKACKJuGY4M64DudIE,8841
|
|
12
|
-
assemblyline_v4_service/common/ontology_helper.py,sha256=
|
|
12
|
+
assemblyline_v4_service/common/ontology_helper.py,sha256=kiYI0ecQJc1zxEHePWTX73mAWTEdv4v3wpSk6ONQTsE,8270
|
|
13
13
|
assemblyline_v4_service/common/request.py,sha256=W7fqC2xQE3i5i2jlCDyUDp3ZqJQQqSshNW0mQfJMkFg,11792
|
|
14
14
|
assemblyline_v4_service/common/result.py,sha256=9AqM6qCYiia_Bpyn_fBFhzNQMcqJbtFSiGjp57fXW2E,32713
|
|
15
15
|
assemblyline_v4_service/common/task.py,sha256=dJsvRpW0x88CCF_LW6w87jQ_UKTVaOs2Gb117IDNiU8,14233
|
|
@@ -33,13 +33,13 @@ test/test_common/test_api.py,sha256=7wlo7wgB12T23zMLbwjJ3GIomLHqE_Qvs3xkibSsR1U,
|
|
|
33
33
|
test/test_common/test_base.py,sha256=fuJSSlPxIDHq6HU1xbvaMFitw2z1spOZNHD2SJ4UUic,13346
|
|
34
34
|
test/test_common/test_helper.py,sha256=sO6YAiBhKTqaxlpLhFYDuy2ZdbuF2cg07Ylzo83ZzQs,2575
|
|
35
35
|
test/test_common/test_ocr.py,sha256=mt_PgElgwQKJmNrp2nRVx9NjfMedVk40I6IV317vATI,1753
|
|
36
|
-
test/test_common/test_ontology_helper.py,sha256=
|
|
36
|
+
test/test_common/test_ontology_helper.py,sha256=a_bX1MPQnwV1QILGgrUSNsgMgCnl663fAB40cw3ElHI,10237
|
|
37
37
|
test/test_common/test_request.py,sha256=Ceyds8BNO1O0f1kH1VEb84faJcaupvSjVKIrGdHexsc,11842
|
|
38
38
|
test/test_common/test_result.py,sha256=6BiOKxEPrKBjOY44jv3TY-yiXm0qI1ok_CZBnjP9TM4,45447
|
|
39
39
|
test/test_common/test_task.py,sha256=P44mNcSe-3tJgDk9ppN3KbM7oN4LBVIuhONG-Gveh74,19007
|
|
40
40
|
test/test_common/test_utils.py,sha256=TbnBxqpS_ZC5ptXR9XJX3xtbItD0mTbtiBxxdyP8J5k,5904
|
|
41
|
-
assemblyline_v4_service-4.5.1.
|
|
42
|
-
assemblyline_v4_service-4.5.1.
|
|
43
|
-
assemblyline_v4_service-4.5.1.
|
|
44
|
-
assemblyline_v4_service-4.5.1.
|
|
45
|
-
assemblyline_v4_service-4.5.1.
|
|
41
|
+
assemblyline_v4_service-4.5.1.dev233.dist-info/LICENCE.md,sha256=NSkYo9EH8h5oOkzg4VhjAHF4339MqPP2cQ8msTPgl-c,1396
|
|
42
|
+
assemblyline_v4_service-4.5.1.dev233.dist-info/METADATA,sha256=q1LCbQQGOjZUK2eAqnpTpZefohsJQB6M-ysdVYjXQw4,9493
|
|
43
|
+
assemblyline_v4_service-4.5.1.dev233.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
|
|
44
|
+
assemblyline_v4_service-4.5.1.dev233.dist-info/top_level.txt,sha256=LpTOEaVCatkrvbVq3EZseMSIa2PQZU-2rhuO_FTpZgY,29
|
|
45
|
+
assemblyline_v4_service-4.5.1.dev233.dist-info/RECORD,,
|
|
@@ -7,7 +7,7 @@ from test.test_common import setup_module
|
|
|
7
7
|
setup_module()
|
|
8
8
|
|
|
9
9
|
import pytest
|
|
10
|
-
from assemblyline_v4_service.common.ontology_helper import
|
|
10
|
+
from assemblyline_v4_service.common.ontology_helper import OntologyHelper, validate_tags, merge_tags
|
|
11
11
|
from assemblyline_v4_service.common.result import ResultSection
|
|
12
12
|
|
|
13
13
|
from assemblyline.odm.models.ontology.ontology import ODM_VERSION
|
|
@@ -224,15 +224,75 @@ def test_attach_ontology(dummy_request_class):
|
|
|
224
224
|
'odm_type': 'Assemblyline Result Ontology',
|
|
225
225
|
'odm_version': ODM_VERSION,
|
|
226
226
|
'results': {'heuristics': [],
|
|
227
|
-
'tags': {'network.static.domain': ['blah.com']}
|
|
227
|
+
'tags': {'network.static.domain': ['blah.com']},
|
|
228
|
+
'score': 0},
|
|
228
229
|
'service': {'name': 'blah',
|
|
229
230
|
'tool_version': 'blah',
|
|
230
|
-
'version': '4.0.0'}
|
|
231
|
+
'version': '4.0.0'}
|
|
231
232
|
}
|
|
232
233
|
|
|
233
|
-
#
|
|
234
|
-
|
|
234
|
+
# Assign a heuristic to the section and check to see if the score gets updated correctly
|
|
235
|
+
req.result.sections[0].set_heuristic(1)
|
|
236
|
+
req.result.sections.append(req.result.sections[0])
|
|
237
|
+
req.task.supplementary = []
|
|
238
|
+
assert oh._attach_ontology(req, working_dir) is None
|
|
239
|
+
assert oh.results == {}
|
|
240
|
+
assert req.task.supplementary == [
|
|
241
|
+
{
|
|
242
|
+
'classification': 'TLP:C',
|
|
243
|
+
'description': 'Result Ontology from blah',
|
|
244
|
+
'name': 'blah_blah.ontology',
|
|
245
|
+
'path': os.path.join(working_dir, "blah.ontology")
|
|
246
|
+
}
|
|
247
|
+
]
|
|
235
248
|
|
|
249
|
+
with open(os.path.join(working_dir, "blah.ontology"), "r") as f:
|
|
250
|
+
file_contents = json.loads(f.read())
|
|
251
|
+
# The sum of the overall result should be 500 points since the heuristic was raised twice with a score of 250 per section
|
|
252
|
+
assert file_contents == {
|
|
253
|
+
'classification': 'TLP:C',
|
|
254
|
+
'file': {'md5': 'blah',
|
|
255
|
+
'names': ['blah'],
|
|
256
|
+
'sha1': 'blah',
|
|
257
|
+
'sha256': 'blah',
|
|
258
|
+
'size': 123,
|
|
259
|
+
'type': None},
|
|
260
|
+
'odm_type': 'Assemblyline Result Ontology',
|
|
261
|
+
'odm_version': ODM_VERSION,
|
|
262
|
+
'results': {'heuristics': [{'tags': {'network.static.domain': ['blah.com']}, 'times_raised': 2, 'heur_id': 'BLAH_1', 'name': 'blah', 'score': 250}],
|
|
263
|
+
'tags': {'network.static.domain': ['blah.com']},
|
|
264
|
+
'score': 500},
|
|
265
|
+
'service': {'name': 'blah',
|
|
266
|
+
'tool_version': 'blah',
|
|
267
|
+
'version': '4.0.0'}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def test_validate_tags():
|
|
272
|
+
# Valid tag
|
|
273
|
+
assert validate_tags({'network.static.domain':['blah.com']})
|
|
274
|
+
|
|
275
|
+
# Invalid tag
|
|
276
|
+
assert not validate_tags({'blah':['blah.com']})
|
|
277
|
+
|
|
278
|
+
def test_merge_tags():
|
|
279
|
+
# Merge with null should yield the tag map with value
|
|
280
|
+
assert merge_tags({'abc':['xyz']}, None) == {'abc':['xyz']}
|
|
281
|
+
assert merge_tags(None, {'abc':['xyz']}) == {'abc':['xyz']}
|
|
282
|
+
|
|
283
|
+
# Merge with mutually exclusive keys
|
|
284
|
+
assert merge_tags({'abc':['xyz']}, {'def':['xyz']}) == {
|
|
285
|
+
'abc':['xyz'],
|
|
286
|
+
'def':['xyz']
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
# Merge with non-mutually exclusive keys
|
|
290
|
+
merged_tags = merge_tags({'abc':['xyz'], 'def':['tuv']}, {'def':['xyz']})
|
|
291
|
+
merged_tags['def'] = sorted(merged_tags['def'])
|
|
292
|
+
merged_tags == {
|
|
293
|
+
'abc':['xyz'],
|
|
294
|
+
'def':['tuv', 'xyz']
|
|
295
|
+
}
|
|
236
296
|
|
|
237
297
|
def test_reset():
|
|
238
298
|
oh = OntologyHelper(None, "blah")
|
|
File without changes
|
|
File without changes
|