66import sys
77import csv
88import os
9+ import yaml
10+ import glob
911from pathlib import Path
1012from 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 + '''
176196tags:
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