Skip to content

Commit 4c9f0ee

Browse files
committed
feat[scripts] generate_mapping 2.0
Initial version of generate_mapping for 2.0
1 parent f32a26f commit 4c9f0ee

File tree

1 file changed

+225
-33
lines changed

1 file changed

+225
-33
lines changed

src/mscp/generate/mapping.py

Lines changed: 225 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import sys
77
import csv
88
import os
9+
import yaml
10+
import glob
911
from pathlib import Path
1012
from typing import Any
1113

@@ -45,12 +47,15 @@ def generate_mapping(args: argparse.Namespace) -> None:
4547
rules: list[Macsecurityrule] = Macsecurityrule.collect_all_rules(
4648
args.os_name, args.os_version
4749
)
50+
print(args)
4851
custom_rules: list[Macsecurityrule] = []
4952
print(args)
5053
# csv_data: dict[str, Any] = open_file(args.csv)
5154
for rule in rules:
5255
# sub_directory = rule.split(".yaml")[0].split("/")[2]
53-
sub_directory = "os"
56+
sub_directory = rule.rule_id.split("_")[0]
57+
if sub_directory == "system":
58+
sub_directory = "system_settings"
5459

5560
if "supplemental" in rule or "srg" in rule:
5661
continue
@@ -81,8 +86,7 @@ def generate_mapping(args: argparse.Namespace) -> None:
8186
for row in reader:
8287

8388
if args.framework != nist_header:
84-
sys.exit(str(args.framework) + " not found in CSV")
85-
89+
sys.exit(str(args.framework) + " not found in CSV")
8690
if "N/A" in row[nist_header]:
8791
continue
8892

@@ -103,21 +107,20 @@ def generate_mapping(args: argparse.Namespace) -> None:
103107

104108

105109
references = []
106-
if "custom_refs" not in rule_yaml['references']:
110+
111+
# if "custom_refs" not in rule_yaml['references']:
112+
if rule_yaml['references']['custom_refs'] is None:
113+
114+
references = rule_yaml.references[framework_main][framework_sub]
115+
116+
if framework_sub == "800-53r5" or "800-171r3":
117+
framework_sub = "nist_{}".format(framework_sub.replace("-","_"))
107118

108-
# references = rule_yaml['references'][framework_main][framework_sub]
109-
# references = rule_yaml.references.framework_main.framework_sub
110-
references = rule_yaml.references
111-
if rule_yaml.rule_id == "os_airdrop_disable":
112-
print("-------")
113-
print(references)
114-
print(references['nist'])
115-
topleveltype = references['nist']
116-
print(topleveltype['nist_800_53r5'])
117-
print(type(references['nist']))
118-
sys.exit("i am done")
119+
references = rule_yaml.references[framework_main][framework_sub]
120+
121+
119122
else:
120-
references = rule_yaml['references']['custom'][framework_main][framework_sub]
123+
references = rule_yaml['references']['custom_refs'][framework_main][framework_sub]
121124

122125
for yaml_control in references:
123126
if duplicate == str(yaml_control).split("(")[0]:
@@ -133,18 +136,36 @@ def generate_mapping(args: argparse.Namespace) -> None:
133136
row_array = str(row[other_header]).split(",")
134137
for item in row_array:
135138
control_array.append(item)
136-
print(rule_yaml['id'] + " - " + str(args.framework) + " " + str(yaml_control) + " maps to " + other_header + " " + item)
139+
print(rule_yaml['rule_id'] + " - " + str(args.framework) + " " + str(yaml_control) + " maps to " + other_header + " " + item)
137140

138141

139142
else:
140-
143+
141144
references = []
142-
if "custom" not in rule_yaml['references']:
143-
references = rule_yaml['references'][args.framework]
145+
# if "custom" not in rule_yaml['references']:
146+
147+
if rule_yaml['references']['custom_refs'] is None:
148+
# framework = args.framework
149+
framework_main = "nist"
150+
if args.framework == "disa_stig" or args.framework == "cci" or args.framework == "srg" or args.framework == "cmmc" or args.framework == "sfr":
151+
framework_main = "disa"
152+
if args.framework == "benchmark" or args.framework == "controls_v8":
153+
framework_main = "cis"
154+
if args.framework == "indigo":
155+
framework_main = "bsi"
156+
framework_sub = args.framework
157+
158+
if args.framework == "800-53r5" or "800-171r3":
159+
# framework = "nist_{}".format(args.framework.replace("-","_"))
160+
framework_sub = "nist_{}".format(args.framework.replace("-","_"))
161+
162+
163+
references = rule_yaml['references'][framework_main][framework_sub]
164+
144165
else:
145-
references = rule_yaml['references']['custom'][args.framework]
166+
references = rule_yaml['references']['custom_refs'][args.framework]
146167

147-
for yaml_control in references:
168+
for yaml_control in references:
148169
if duplicate == str(yaml_control).split("(")[0]:
149170
continue
150171
if csv_duplicate == str(row[other_header]):
@@ -156,7 +177,7 @@ def generate_mapping(args: argparse.Namespace) -> None:
156177
row_array = str(row[other_header]).split(",")
157178
for item in row_array:
158179
control_array.append(item)
159-
print(rule_yaml['id'] + " - " + str(args.framework) + " " + str(yaml_control) + " maps to " + other_header + " " + item)
180+
print(rule_yaml['rule_id'] + " - " + str(args.framework) + " " + str(yaml_control) + " maps to " + other_header + " " + item)
160181

161182
except:
162183
continue
@@ -165,7 +186,6 @@ def generate_mapping(args: argparse.Namespace) -> None:
165186
continue
166187

167188
custom_rule = '''references:
168-
custom:
169189
{}:'''.format(other_header)
170190

171191
for control in control_array:
@@ -175,25 +195,197 @@ def generate_mapping(args: argparse.Namespace) -> None:
175195
custom_rule = custom_rule + '''
176196
tags:
177197
- {}'''.format(other_header)
198+
199+
output_dir: Path = Path(config["output_dir"], other_header.lower())
178200

179-
if os.path.isdir("../build/" + other_header) == False:
180-
os.mkdir("../build/" + other_header)
181-
if os.path.isdir("../build/" + other_header + "/rules/") == False:
182-
os.mkdir("../build/" + other_header + "/rules/")
183-
if os.path.isdir("../build/" + other_header + "/rules/" + sub_directory) == False:
184-
os.mkdir("../build/" + other_header + "/rules/" + sub_directory)
201+
rule_path = output_dir / "rules" / sub_directory
202+
rule_path.mkdir(parents=True, exist_ok=True)
185203

186204
try:
187-
with open("../build/" + other_header + "/rules/" + sub_directory + "/" + rule_yaml['id'] + ".yaml", 'w') as r:
205+
with open(str(rule_path) + "/" + rule_yaml['rule_id'] + ".yaml", 'w') as r:
188206
custom_yaml = r.read()
189207

190208
custom_yaml = custom_yaml.replace(other_header + ": ", custom_rule)
191-
with open("../build/" + other_header + "/rules/" + sub_directory + "/" + rule_yaml['id'] + ".yaml", 'w') as fw:
209+
with open(str(rule_path) + "/" + rule_yaml['rule_id'] + ".yaml", 'w') as fw:
192210
fw.write(custom_yaml)
193211
except:
194-
with open("../build/" + other_header + "/rules/" + sub_directory + "/" + rule_yaml['id'] + ".yaml", 'w') as fw:
212+
with open(str(rule_path) + "/" + rule_yaml['rule_id'] + ".yaml", 'w') as fw:
195213
fw.write(custom_rule)
196214

215+
audit = []
216+
auth = []
217+
icloud = []
218+
os_section = []
219+
pwpolicy = []
220+
system_settings = []
221+
sysprefs = []
222+
inherent = []
223+
na = []
224+
perm = []
225+
226+
for rule in glob.glob(str(output_dir) + '/rules/*/*.yaml'):
227+
if "supplemental" in rule or "srg" in rule or "baseline" in rule:
228+
continue
229+
with open(rule) as r:
230+
custom_rule = yaml.load(r, Loader=yaml.SafeLoader)
231+
232+
rule_id = rule.split(".yaml")[0].split("/")[-1]
233+
234+
235+
if other_header in custom_rule['tags']:
236+
if "inherent" in rule_yaml['tags']:
237+
inherent.append(rule_id)
238+
continue
239+
if "permanent" in custom_rule['tags']:
240+
perm.append(rule_id)
241+
continue
242+
if "n_a" in custom_rule['tags']:
243+
na.append(rule_id)
244+
continue
245+
if "/audit/" in rule:
246+
audit.append(rule_id)
247+
continue
248+
if "/auth/" in rule:
249+
auth.append(rule_id)
250+
continue
251+
if "/icloud/" in rule:
252+
icloud.append(rule_id)
253+
continue
254+
if "/os/" in rule:
255+
os_section.append(rule_id)
256+
continue
257+
if "/pwpolicy/" in rule:
258+
pwpolicy.append(rule_id)
259+
continue
260+
if "/system_settings/" in rule:
261+
system_settings.append(rule_id)
262+
continue
263+
if "/settings/" in rule:
264+
sysprefs.append(rule_id)
265+
continue
266+
267+
268+
full_baseline = '''title: "{1} {2}: Security Configuration - {0}"
269+
description: |
270+
This guide describes the actions to take when securing a {1} {2} system against the {0}.
271+
authors:
272+
- name: (ENTER AUTHOR NAME)
273+
organization: (ENTER ORG NAME)
274+
parent_values: recommended
275+
platform:
276+
os: {1}
277+
version: {2}
278+
profile:'''.format(other_header,args.os_name,args.os_version)
279+
280+
if len(audit) != 0:
281+
282+
full_baseline = full_baseline + '''
283+
- section: Auditing
284+
rules:'''
285+
audit.sort()
286+
287+
for rule in audit:
288+
full_baseline = full_baseline + '''
289+
- {}'''.format(rule)
290+
if len(auth) != 0:
291+
full_baseline = full_baseline + '''
292+
- section: Authentication
293+
rules:'''
294+
auth.sort()
295+
296+
for rule in auth:
297+
full_baseline = full_baseline + '''
298+
- {}'''.format(rule)
299+
300+
if len(system_settings) != 0:
301+
full_baseline = full_baseline + '''
302+
- section: System Settings
303+
rules:'''
304+
system_settings.sort()
305+
306+
for rule in system_settings:
307+
full_baseline = full_baseline + '''
308+
- {}'''.format(rule)
309+
310+
if len(icloud) != 0:
311+
full_baseline = full_baseline + '''
312+
- section: iCloud
313+
rules:'''
314+
icloud.sort()
315+
for rule in icloud:
316+
full_baseline = full_baseline + '''
317+
- {}'''.format(rule)
318+
319+
if len(os_section) != 0 and args.os_name == "os":
320+
full_baseline = full_baseline + '''
321+
- section: Operating System
322+
rules:'''
323+
os_section.sort()
324+
for rule in os_section:
325+
full_baseline = full_baseline + '''
326+
- {}'''.format(rule)
327+
328+
if len(pwpolicy) != 0:
329+
full_baseline = full_baseline + '''
330+
- section: Password Policy
331+
rules:'''
332+
pwpolicy.sort()
333+
for rule in pwpolicy:
334+
full_baseline = full_baseline + '''
335+
- {}'''.format(rule)
336+
337+
if len(inherent) != 0:
338+
full_baseline = full_baseline + '''
339+
- section: Inherent
340+
rules:'''
341+
inherent.sort()
342+
for rule in inherent:
343+
full_baseline = full_baseline + '''
344+
- {}'''.format(rule)
345+
346+
if len(perm) != 0:
347+
full_baseline = full_baseline + '''
348+
- section: Permanent
349+
rules:'''
350+
perm.sort()
351+
for rule in perm:
352+
full_baseline = full_baseline + '''
353+
- {}'''.format(rule)
354+
355+
if len(na) != 0:
356+
full_baseline = full_baseline + '''
357+
- section: Not Applicable
358+
rules:'''
359+
na.sort()
360+
for rule in na:
361+
full_baseline = full_baseline + '''
362+
- {}'''.format(rule)
363+
364+
# listofsupplementals = str()
365+
# for supp_rule in glob.glob('../rules/supplemental/*.yaml',recursive=True):
366+
# listofsupplementals = listofsupplementals + '''- {}
367+
# '''.format(os.path.basename(supp_rule).split(".")[0])
368+
# full_baseline = full_baseline + '''
369+
# - section: Supplemental
370+
# rules:
371+
# {}
372+
# '''.format(listofsupplementals)
373+
374+
try:
375+
output_dir: Path = Path(config["output_dir"], other_header.lower())
376+
377+
baseline_path = output_dir / "baselines"
378+
baseline_path.mkdir(parents=True, exist_ok=True)
379+
380+
381+
with open(str(baseline_path) + "/" + other_header.lower().replace(" ","_") + ".yaml",'w') as fw:
382+
fw.write(full_baseline)
383+
print(other_header.lower().replace(" ","_") + ".yaml baseline file created in build/" + other_header + "/baseline/")
384+
385+
print("Move all of the folders in rules into the custom folder.")
386+
except:
387+
print("No controls mapped were found in rule files.")
388+
197389
# print(args.csv)
198390
# if len(csv_data.keys()) < 2:
199391
# print(len(csv_data.keys()))

0 commit comments

Comments
 (0)