1
- from collections .abc import Iterable
2
1
import json
3
2
import os
4
-
5
- from modules import util
3
+ from collections . abc import Iterable
4
+ from typing import List
6
5
7
6
from loguru import logger
8
7
9
- from . import groups_config
8
+ from modules import util
9
+
10
10
from .. import site_config
11
+ from . import groups_config
11
12
12
13
13
14
def generate_groups ():
14
- """Responsible for verifying group directory and starting off
15
- group markdown generation
16
- """
17
-
15
+ """Responsible for verifying group directory and starting off group markdown generation."""
18
16
# Create content pages directory if does not already exist
19
17
util .buildhelpers .create_content_pages_dir ()
20
18
@@ -44,10 +42,7 @@ def generate_groups():
44
42
45
43
46
44
def generate_markdown_files ():
47
- """Responsible for generating group index page and getting shared data for
48
- all groups
49
- """
50
-
45
+ """Responsible for generating group index page and getting shared data for all groups."""
51
46
has_group = False
52
47
53
48
group_list = util .relationshipgetters .get_group_list ()
@@ -60,9 +55,6 @@ def generate_markdown_files():
60
55
if has_group :
61
56
data = {}
62
57
63
- # Amount of characters per category
64
- group_by = 2
65
-
66
58
notes = util .relationshipgetters .get_objects_using_notes ()
67
59
side_menu_data = util .buildhelpers .get_side_menu_data ("Groups" , "/groups/" , group_list_no_deprecated_revoked )
68
60
data ["side_menu_data" ] = side_menu_data
@@ -84,8 +76,7 @@ def generate_markdown_files():
84
76
85
77
86
78
def generate_group_md (group , side_menu_data , notes ):
87
- """Responsible for generating markdown of all groups"""
88
-
79
+ """Responsible for generating markdown of all groups."""
89
80
attack_id = util .buildhelpers .get_attack_id (group )
90
81
91
82
if attack_id :
@@ -132,13 +123,13 @@ def generate_group_md(group, side_menu_data, notes):
132
123
133
124
# Get navigator layers for this group
134
125
layers = util .buildhelpers .get_navigator_layers (
135
- data ["name" ],
136
- data ["attack_id" ],
137
- "group" ,
138
- "used by" ,
139
- data ["version" ] if "version" in data else None ,
140
- data ["technique_table_data" ],
141
- inheritance , # extend legend to include color coding for inherited techniques, if applicable
126
+ name = data ["name" ],
127
+ attack_id = data ["attack_id" ],
128
+ obj_type = "group" ,
129
+ rel_type = "used by" ,
130
+ version = data ["version" ] if "version" in data else None ,
131
+ techniques_used = data ["technique_table_data" ],
132
+ inheritance = inheritance , # extend legend to include color coding for inherited techniques, if applicable
142
133
)
143
134
144
135
data ["layers" ] = []
@@ -166,13 +157,19 @@ def generate_group_md(group, side_menu_data, notes):
166
157
)
167
158
168
159
# get campaign data for campaign table
169
- data ["campaign_data" ], data ["add_campaign_ref" ] = get_campaign_table_data (group , reference_list )
160
+ data ["campaign_data" ], data ["add_campaign_ref" ] = get_campaign_table_data (
161
+ group = group , reference_list = reference_list
162
+ )
170
163
171
164
# Grab software data for Software table
172
- data ["software_data" ], data ["add_software_ref" ] = get_software_table_data (group , reference_list )
165
+ data ["software_data" ], data ["add_software_ref" ] = get_software_table_data (
166
+ group = group , reference_list = reference_list
167
+ )
173
168
174
169
if group .get ("aliases" ):
175
- data ["alias_descriptions" ] = util .buildhelpers .get_alias_data (group ["aliases" ][1 :], ext_ref )
170
+ data ["alias_descriptions" ] = util .buildhelpers .get_alias_data (
171
+ alias_list = group ["aliases" ][1 :], ext_refs = ext_ref
172
+ )
176
173
177
174
data ["citations" ] = reference_list
178
175
@@ -192,8 +189,7 @@ def generate_group_md(group, side_menu_data, notes):
192
189
193
190
194
191
def get_groups_table_data (group_list ):
195
- """Responsible for generating group table data for the group index page"""
196
-
192
+ """Responsible for generating group table data for the group index page."""
197
193
groups_table_data = []
198
194
199
195
# Now the table on the right, which is made up of group data
@@ -223,9 +219,9 @@ def get_groups_table_data(group_list):
223
219
224
220
225
221
def get_techniques_used_by_group_data (group , reference_list ):
226
- """Given a group and its reference list, get the techniques used by the
227
- group. Check the reference list for citations, if not found
228
- in list, add it.
222
+ """Given a group and its reference list, get the techniques used by the group.
223
+
224
+ Check the reference list for citations, if not found in list, add it.
229
225
"""
230
226
technique_list = {}
231
227
@@ -304,7 +300,7 @@ def get_campaign_table_data(group, reference_list):
304
300
reference_list = util .buildhelpers .update_reference_list (reference_list , campaign ["object" ])
305
301
306
302
if campaign ["relationship" ].get ("description" ):
307
- if reference == False :
303
+ if reference is False :
308
304
reference = True
309
305
310
306
campaign_list [campaign_id ]["desc" ] = campaign ["relationship" ]["description" ]
@@ -344,7 +340,7 @@ def get_campaign_table_data(group, reference_list):
344
340
345
341
346
342
def get_software_table_data (group , reference_list ):
347
- """Given a group, get software table data"""
343
+ """Given a group, get software table data. """
348
344
software_list = {}
349
345
reference = False
350
346
@@ -361,7 +357,11 @@ def get_software_table_data(group, reference_list):
361
357
]
362
358
# get malware or tools used by group
363
359
software_list , reference = update_software_list (
364
- tools_and_malware , software_list , reference_list , reference , group .get ("id" )
360
+ pairings = tools_and_malware ,
361
+ software_list = software_list ,
362
+ reference_list = reference_list ,
363
+ reference = reference ,
364
+ id = group .get ("id" ),
365
365
)
366
366
367
367
# campaigns attributed to groups
@@ -384,7 +384,11 @@ def get_software_table_data(group, reference_list):
384
384
campaign_id = campaign ["object" ]["id" ]
385
385
# get malware or tools used by campaigns
386
386
software_list , reference = update_software_list (
387
- software_used_by_campaigns , software_list , reference_list , reference , campaign_id
387
+ pairings = software_used_by_campaigns ,
388
+ software_list = software_list ,
389
+ reference_list = reference_list ,
390
+ reference = reference ,
391
+ id = campaign_id ,
388
392
)
389
393
390
394
# Moving it to an array because jinja does not like to loop through dictionaries
@@ -400,12 +404,36 @@ def get_software_table_data(group, reference_list):
400
404
return data , reference
401
405
402
406
403
- def update_software_list (pairings , software_list , reference_list , reference , id ):
407
+ def update_software_list (pairings : List , software_list : List , reference_list : List , reference : bool , id : str ):
408
+ """Update the software list with the given pairings.
409
+
410
+ This function iterates through the given pairings and updates the software list with
411
+ the software that matches the given ID. It also updates the reference list with the
412
+ corresponding reference.
413
+
414
+ Parameters
415
+ ----------
416
+ pairings : List
417
+ A list of dictionaries that contain software and reference data.
418
+ software_list : List
419
+ The list of software to be updated.
420
+ reference_list : List
421
+ The list of references to be updated.
422
+ reference : bool
423
+ Whether the reference section should be included.
424
+ id : str
425
+ The ID of the software to be added to the software list.
426
+
427
+ Returns
428
+ -------
429
+ tuple
430
+ A tuple containing the updated software list and whether the reference section should be included.
431
+ """
404
432
for pairing in pairings :
405
433
if pairing ["software" ].get (id ):
406
434
for software in pairing ["software" ][id ]:
407
435
software_stix_id = software ["object" ]["id" ]
408
- software_attack_id = util .buildhelpers .get_attack_id (software ["object" ])
436
+ software_attack_id = util .buildhelpers .get_attack_id (object = software ["object" ])
409
437
# check if software not in software_list dict
410
438
if software_stix_id not in software_list and software_attack_id :
411
439
software_list [software_stix_id ] = {"id" : software_attack_id , "name" : software ["object" ]["name" ]}
@@ -416,7 +444,7 @@ def update_software_list(pairings, software_list, reference_list, reference, id)
416
444
software_list [software_stix_id ]["descr" ] = software ["relationship" ]["description" ]
417
445
# Update reference list
418
446
reference_list = util .buildhelpers .update_reference_list (
419
- reference_list , software ["relationship" ]
447
+ reference_list = reference_list , obj = software ["relationship" ]
420
448
)
421
449
422
450
# Check if techniques exists, add techniques used by software
@@ -426,12 +454,12 @@ def update_software_list(pairings, software_list, reference_list, reference, id)
426
454
427
455
for technique in pairing ["techniques" ][software_stix_id ]:
428
456
tech_data = {}
429
- t_id = util .buildhelpers .get_attack_id (technique ["object" ])
457
+ t_id = util .buildhelpers .get_attack_id (object = technique ["object" ])
430
458
if t_id :
431
- if util .buildhelpers .is_sub_tid (t_id ):
432
- tech_data ["parent_id" ] = util .buildhelpers .get_parent_technique_id (t_id )
433
- tech_data ["id" ] = util .buildhelpers .get_sub_technique_id (t_id )
434
- tech_data ["name" ] = util .buildhelpers .get_technique_name (tech_data ["parent_id" ])
459
+ if util .buildhelpers .is_sub_tid (sub_tid = t_id ):
460
+ tech_data ["parent_id" ] = util .buildhelpers .get_parent_technique_id (sub_tid = t_id )
461
+ tech_data ["id" ] = util .buildhelpers .get_sub_technique_id (sub_tid = t_id )
462
+ tech_data ["name" ] = util .buildhelpers .get_technique_name (tid = tech_data ["parent_id" ])
435
463
tech_data ["sub_name" ] = technique ["object" ]["name" ]
436
464
else :
437
465
tech_data ["id" ] = t_id
@@ -440,6 +468,7 @@ def update_software_list(pairings, software_list, reference_list, reference, id)
440
468
software_list [software_stix_id ]["techniques" ].append (tech_data )
441
469
return software_list , reference
442
470
471
+
443
472
def generate_sidebar_groups (side_menu_data ):
444
473
"""Responsible for generating the sidebar for the groups pages."""
445
474
logger .info ("Generating groups sidebar" )
0 commit comments