#!/usr/bin/env python3 # filename: generate_scap.py # description: Input a keyword for the baseline, output the scap/oval/xccdf import sys import os import os.path import yaml import glob import re import warnings from pathlib import Path from datetime import datetime import shutil from time import sleep import argparse from xml.sax.saxutils import escape warnings.filterwarnings("ignore", category=DeprecationWarning) def format_mobileconfig_fix(mobileconfig): """Takes a list of domains and setting from a mobileconfig, and reformats it for the output of the fix section of the guide. """ rulefix = "" for domain, settings in mobileconfig.items(): if domain == "com.apple.ManagedClient.preferences": rulefix = rulefix + \ (f"NOTE: The following settings are in the ({domain}) payload. This payload requires the additional settings to be sub-payloads within, containing their defined payload types.\n\n") rulefix = rulefix + format_mobileconfig_fix(settings) else: rulefix = rulefix + ( f"Create a configuration profile containing the following keys in the ({domain}) payload type:\n\n") rulefix = rulefix + "[source,xml]\n----\n" for item in settings.items(): rulefix = rulefix + (f"{item[0]}\n") if type(item[1]) == bool: rulefix = rulefix + \ (f"<{str(item[1]).lower()}/>\n") elif type(item[1]) == list: rulefix = rulefix + "\n" for setting in item[1]: rulefix = rulefix + \ (f" {setting}\n") rulefix = rulefix + "\n" elif type(item[1]) == int: rulefix = rulefix + \ (f"{item[1]}\n") elif type(item[1]) == str: rulefix = rulefix + \ (f"{item[1]}\n") elif type(item[1]) == dict: rulefix = rulefix + "\n" for k,v in item[1].items(): if type(v) == dict: rulefix = rulefix + \ (f" {k}\n") rulefix = rulefix + \ (f" \n") for x,y in v.items(): rulefix = rulefix + \ (f" {x}\n") rulefix = rulefix + \ (f" {y}\n") rulefix = rulefix + \ (f" \n") break if isinstance(v, list): rulefix = rulefix + " \n" for setting in v: rulefix = rulefix + \ (f" {setting}\n") rulefix = rulefix + " \n" else: rulefix = rulefix + \ (f" {k}\n") rulefix = rulefix + \ (f" {v}\n") rulefix = rulefix + "\n" rulefix = rulefix + "----\n\n" return rulefix def replace_ocil(xccdf, x): regex = r'''([\r\n].*?)(?:=?\r|\n)(.*?(?:def:{}\").*)'''.format(x) substr = '''''' result = re.sub(regex, substr, xccdf, 0, re.MULTILINE) return result def create_args(): parser = argparse.ArgumentParser( description="Easily generate xccdf, oval, or scap datastream. If no option is defined, it will generate an scap datastream file.") parser.add_argument("-x", "--xccdf", default=None, help="Generate an xccdf file.", action="store_true") parser.add_argument("-o", "--oval", default=None, help="Generate an oval file of the checks.", action="store_true") parser.add_argument("-l", "--list_tags", default=None, help="List the available keyword tags to search for.", action="store_true") parser.add_argument("-b", "--baseline", default="None", help="Choose a baseline to generate an xml file for, if none is specified it will generate for every rule found.", action="store") return parser.parse_args() def generate_scap(all_rules, all_baselines, args): export_as = "" version_file = "../VERSION.yaml" with open(version_file) as r: version_yaml = yaml.load(r, Loader=yaml.SafeLoader) if args.xccdf: export_as = "xccdf" if args.oval: export_as = "oval" if "ios" in version_yaml['cpe']: print("OVAL generation is not available on iOS") exit() if args.oval == None and args.xccdf == None: export_as = "scap" if "ios" in version_yaml['cpe']: print("iOS will only export as XCCDF") export_as = "xccdf" now = datetime.now() date_time_string = now.strftime("%Y-%m-%dT%H:%M:%S") filenameversion = version_yaml['version'].split(",")[1].replace(" ", "_")[1:] output = "../build/macOS_{0}_Security_Compliance_Benchmark-{1}".format(version_yaml['os'],filenameversion) if "ios" in version_yaml['cpe']: output = "../build/iOS_{0}_Security_Compliance_Benchmark-{1}".format(version_yaml['os'],filenameversion) if export_as == "xccdf": output = output + "_xccdf.xml" if export_as == "oval": output = output + "_oval.xml" if export_as == "scap": output = output + ".xml" oval_definition = str() oval_test = str() oval_object = str() oval_state = str() oval_variable = str() xccdf_profiles = str() total_scap = str() scap_groups = str() xccdf_rules = str() x = 1 d = 1 ovalPrefix = ''' 5.11.2 {0} Copyright (c) 2020, NIST. macOS Security Compliance Project '''.format(date_time_string) ostype = "macOS" if "ios" in version_yaml['cpe']: ostype = "iOS/iPadOS" xccdfPrefix = ''' draft {4} {1}: Security Configuration {4} {1}: Security Configuration Security Content Automation Protocol National Institute of Standards and Technology {2} National Institute of Standards and Technology National Institute of Standards and Technology https://github.com/usnistgov/macos_security/releases/latest Bob Gendler - National Institute of Standards and Technology Dan Brodjieski - National Aeronautics and Space Administration Allen Golbig - Jamf '''.format(date_time_string, version_yaml['os'], version_yaml['version'],date_time_string.split("T")[0] + "Z", ostype) scapPrefix = ''' draft macOS {1}: Security Configuration macOS {1}: Security Configuration Security Content Automation Protocol National Institute of Standards and Technology platform-cpe-dictionary platform-cpe-oval {3} National Institute of Standards and Technology National Institute of Standards and Technology https://github.com/usnistgov/macos_security/releases/latest Bob Gendler - National Institute of Standards and Technology Dan Brodjieski - National Aeronautics and Space Administration Allen Golbig - Jamf '''.format(date_time_string, version_yaml['os'], version_yaml['cpe'], version_yaml['version'],date_time_string.split("T")[0] + "Z") generated_baselines = {} for rule in all_rules: if glob.glob('../custom/rules/**/{}.yaml'.format(rule),recursive=True): rule_file = glob.glob('../custom/rules/**/{}.yaml'.format(rule),recursive=True)[0] custom=True elif glob.glob('../rules/*/{}.yaml'.format(rule)): rule_file = glob.glob('../rules/*/{}.yaml'.format(rule))[0] custom=False odv_label = str() og_rule_yaml = get_rule_yaml(rule_file, custom) loop = 1 if "odv" in og_rule_yaml: loop = len(og_rule_yaml['odv']) if args.baseline != "None": loop = 1 for a in range(0, loop): rule_yaml = get_rule_yaml(rule_file, custom) try: # # odv_label = list(rule_yaml['odv'].keys())[a] # # odv_label.remove('hint') if args.baseline != "None": odv_label = args.baseline if args.baseline not in list(rule_yaml['odv'].keys())[a]: odv_label = "recommended" # if args.baseline not in list(rule_yaml['odv'].keys())[a]: # odv_label = "recommended" else: odv_label = list(rule_yaml['odv'].keys())[a] # if odv_label == "hint": # continue odv_value = str(rule_yaml['odv'][odv_label]) rule_yaml['title'] = rule_yaml['title'].replace("$ODV",str(odv_value)) rule_yaml['discussion'] = rule_yaml['discussion'].replace("$ODV",odv_value) rule_yaml['check'] = rule_yaml['check'].replace("$ODV",odv_value) rule_yaml['fix'] = rule_yaml['fix'].replace("$ODV",odv_value) if "result" in rule_yaml: for result_value in rule_yaml['result']: if "$ODV" == rule_yaml['result'][result_value]: rule_yaml['result'][result_value] = rule_yaml['result'][result_value].replace("$ODV",odv_value) if rule_yaml['mobileconfig_info']: for mobileconfig_type in rule_yaml['mobileconfig_info']: if isinstance(rule_yaml['mobileconfig_info'][mobileconfig_type], dict): for mobileconfig_value in rule_yaml['mobileconfig_info'][mobileconfig_type]: if "$ODV" in str(resulting_yaml['mobileconfig_info'][mobileconfig_type][mobileconfig_value]): if type(resulting_yaml['mobileconfig_info'][mobileconfig_type][mobileconfig_value]) == dict: for k,v in resulting_yaml['mobileconfig_info'][mobileconfig_type][mobileconfig_value].items(): if v == "$ODV": resulting_yaml['mobileconfig_info'][mobileconfig_type][mobileconfig_value][k] = odv_value else: resulting_yaml['mobileconfig_info'][mobileconfig_type][mobileconfig_value] = odv_value except: odv_label = "recommended" for baseline in all_baselines: found_rules = [] for tag in rule_yaml['tags']: if tag == baseline: if odv_label != "recommended" and odv_label == tag or odv_label == "custom": if baseline in generated_baselines: generated_baselines[baseline].append(rule_yaml['id'] + "_" + odv_label) else: generated_baselines[baseline] = [rule_yaml['id'] + "_" + odv_label] continue elif odv_label == "recommended" or odv_label == "custom": if "odv" in rule_yaml: if baseline not in rule_yaml['odv']: if baseline in generated_baselines: generated_baselines[baseline].append(rule_yaml['id'] + "_" + odv_label) else: generated_baselines[baseline] = [rule_yaml['id'] + "_" + odv_label] else: if baseline in generated_baselines: generated_baselines[baseline].append(rule_yaml['id'] + "_" + odv_label) else: generated_baselines[baseline] = [rule_yaml['id'] + "_" + odv_label] if odv_label == "hint": continue result = str() if "result" in rule_yaml: result = "\nResult: {}".format(rule_yaml['result']) else: result = "" severity = str() if severity in rule_yaml: if isinstance(rule_yaml["severity"], str): severity = f'{rule_yaml["severity"]}' if isinstance(rule_yaml["severity"], dict): try: severity = f'{rule_yaml["severity"][args.baseline]}' except KeyError: severity = "unknown" else: severity = "unknown" check_rule = str() if "inherent" in rule_yaml['tags'] or "n_a" in rule_yaml['tags'] or "permanent" in rule_yaml['tags']: check_rule = ''' ''' else: check_rule = ''' '''.format(x) references = str() if "800-53r5" in rule_yaml['references'] and rule_yaml['references']['800-53r5'][0] != "N/A": references = references + "NIST SP 800-53r5: " for nist80053 in rule_yaml['references']['800-53r5']: references = references + nist80053 + ", " references = references[:-2] + "" if "800-53r4" in rule_yaml['references'] and rule_yaml['references']['800-53r4'][0] != "N/A": references = references + "NIST SP 800-53r4: " for nist80053 in rule_yaml['references']['800-53r4']: references = references + nist80053 + ", " references = references[:-2] + "" if "800-171r3" in rule_yaml['references'] and rule_yaml['references']['800-171r3'][0] != "N/A": references = references + "NIST SP 800-171r3: " for nist800171 in rule_yaml['references']['800-171r3']: references = references + nist800171 + ", " references = references[:-2] + "" if "disa_stig" in rule_yaml['references'] and rule_yaml['references']['disa_stig'][0] != "N/A": references = references + "DISA STIG(s): " for disa_stig in rule_yaml['references']['disa_stig']: references = references + disa_stig + ", " references = references[:-2] + "" if "cis" in rule_yaml['references']: if "benchmark" in rule_yaml['references']['cis'] and rule_yaml['references']['cis']['benchmark'][0] != "N/A": references = references + "CIS Benchmark: " for benchmark in rule_yaml['references']['cis']['benchmark']: references = references + benchmark + ", " references = references[:-2] + "" if "controls v8" in rule_yaml['references']['cis'] and rule_yaml['references']['cis']['controls v8'][0] != "N/A": references = references + "CIS Controls V8: " for v8controls in rule_yaml['references']['cis']['controls v8']: references = references + str(v8controls) + ", " references = references[:-2] + "" for k,v in rule_yaml['references'].items(): if k == "cci" or k == "srg": continue if k == "custom": for i,u in rule_yaml['references']['custom'].items(): references = references + '{0}: '.format(i) for refs in rule_yaml['references']['custom'][i]: references = references + '{0}, '.format(str(refs)) references = references[:-2] + "" cce = str() if "cce" not in rule_yaml['references'] or rule_yaml['references']['cce'] == "N/A": cce = "CCE-11111-1" else: cce = rule_yaml['references']['cce'][0] if export_as == "scap": mobileconfig_info = "" if rule_yaml['mobileconfig']: mobileconfig_info = escape(format_mobileconfig_fix(rule_yaml['mobileconfig_info'])) xccdf_rules = xccdf_rules + ''' {2} {3} {4} {5}{9} {6} {7} {8} '''.format(rule_yaml['id'] + "_" + odv_label, severity, rule_yaml['title'], rule_yaml['discussion'].replace("<","<").replace(">",">").replace("&","&").rstrip(), rule_yaml['check'].replace("<","<").replace(">",">").replace("&","&").rstrip(), result, cce,rule_yaml['fix'].replace("<","<").replace(">",">").replace("&","&") + "\n" + mobileconfig_info, check_rule, references) if export_as == "xccdf": mobileconfig_info = "" if rule_yaml['mobileconfig']: mobileconfig_info = escape(format_mobileconfig_fix(rule_yaml['mobileconfig_info'])) xccdf_rules = xccdf_rules + ''' {2} {3} {4} {5}{8} {6} {7} '''.format(rule_yaml['id'] + "_" + odv_label, severity, rule_yaml['title'], rule_yaml['discussion'].replace("<","<").replace(">",">").replace("&","&").rstrip(), rule_yaml['check'].replace("<","<").replace(">",">").replace("&","&").rstrip(), result, cce,rule_yaml['fix'].replace("<","<").replace(">",">").replace("&","&") + "\n" + mobileconfig_info, references) continue if "inherent" in rule_yaml['tags'] or "n_a" in rule_yaml['tags'] or "permanent" in rule_yaml['tags']: xccdf_rules = replace_ocil(xccdf_rules,x) x += 1 continue if "time_machine" in rule_yaml['id'] and "encrypted" in rule_yaml['id']: print(rule_yaml['id'] + " - Manual Check Required") xccdf_rules = replace_ocil(xccdf_rules,x) x += 1 continue if "bluetooth" in rule_yaml['id'] and "unpaired" in rule_yaml['id']: print(rule_yaml['id'] + " - Manual Check Required") xccdf_rules = replace_ocil(xccdf_rules,x) x += 1 continue if rule_yaml['check'][0] != "/" and "[source,bash]" not in rule_yaml['fix']: print(rule_yaml['id'] + " - Manual Check") xccdf_rules = replace_ocil(xccdf_rules,x) x += 1 continue if "hint" in rule_yaml['check'] and "dscl" in rule_yaml['check']: print(rule_yaml['id'] + " - no relevant oval") xccdf_rules = replace_ocil(xccdf_rules,x) x += 1 continue if "manual" in rule_yaml['tags']: print(rule_yaml['id'] + " - Manual Check") xccdf_rules = replace_ocil(xccdf_rules,x) x += 1 continue if "eficheck" in rule_yaml['check']: print(rule_yaml['id'] + " - eficheck - no relevant oval") xccdf_rules = replace_ocil(xccdf_rules,x) x += 1 continue if "newsyslog.conf" in rule_yaml['check'] or "asl.conf" in rule_yaml['check'] or "aslmanager" in rule_yaml['check']: print(rule_yaml['id'] + " - Manual Check Required") xccdf_rules = replace_ocil(xccdf_rules,x) x += 1 continue if "/usr/bin/pwpolicy getaccountpolicies" in rule_yaml['check']: print(rule_yaml['id'] + " - pwpolicy getaccountpolicies - no relevant oval") xccdf_rules = replace_ocil(xccdf_rules,x) x += 1 continue if "find" in rule_yaml['check'].split(" ")[0] and rule_yaml['id'] != "os_home_folders_secure": print(rule_yaml['id'] + " - no relevant oval") xccdf_rules = replace_ocil(xccdf_rules,x) x += 1 continue if "/usr/sbin/firmwarepasswd" in rule_yaml['check']: print(rule_yaml['id'] + " - no relevant oval") xccdf_rules = replace_ocil(xccdf_rules,x) x += 1 continue if "os_home_folders_secure" in rule_yaml['id']: oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label, rule_yaml['discussion'],rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x,x,x) oval_object = oval_object + ''' .* oval:mscp:ste:{} '''.format(rule_yaml['id'] + "_" + odv_label,x,x,x+999,x+999) oval_state = oval_state + ''' true true true false false false false false false ^[^_\s].* 0 0 /usr/bin/false '''.format(rule_yaml['id'] + "_" + odv_label,x,x+999) oval_variable = oval_variable + ''' '''.format(x,x+999) x = x + 1 continue if rule_yaml['mobileconfig']: if "spctl" in rule_yaml['check']: if "verbose" in rule_yaml['check']: xccdf_rules = replace_ocil(xccdf_rules,x) x = x + 1 continue else: oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'].rstrip(),rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x,x,x) oval_object = oval_object + ''' '''.format(x,rule_yaml['id']) oval_state = oval_state + ''' true '''.format(rule_yaml['id'] + "_" + odv_label,x) x += 1 continue for payload_type, info in rule_yaml['mobileconfig_info'].items(): if payload_type == "com.apple.systempolicy.control": continue if payload_type == "com.apple.ManagedClient.preferences": for payload_domain, settings in info.items(): oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'].rstrip()) if len(settings) > 1: oval_definition = oval_definition + '''''' else: oval_definition = oval_definition + '''''' for key, value in settings.items(): state_kind = "" if type(value) == bool: state_kind = "boolean" elif type(value) == int: state_kind = "int" elif type(value) == str: state_kind = "string" dz = d + 5000 oval_definition = oval_definition + ''''''.format(rule_yaml['id'] + '_' + odv_label + "_" + str(d), dz) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label + "_" + str(d),dz,dz,dz) if payload_domain == "com.apple.dock": oval_object = oval_object + ''' /Library/Preferences/com.apple.loginwindow.plist /plist/dict/key[string()="lastUserName"]/following-sibling::*[1]/text() //*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(x+1999,key,dz,x,key) oval_variable = oval_variable + ''' /Library/Managed Preferences/ /com.apple.dock.plist '''.format(x,x+1999) else: oval_object = oval_object + ''' /Library/Managed Preferences/{}.plist //*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(rule_yaml['id'] + "_" + odv_label,dz,payload_domain,key) oval_state = oval_state + ''' {} '''.format(rule_yaml['id'] + "_" + odv_label,dz,state_kind,value) d += 1 x += 1 oval_definition = oval_definition + ''' ''' continue for key, value in info.items(): if key == "familyControlsEnabled": xpath_search = "" if len(info) > 1: xpath_search = info['pathBlackList'] oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'].rstrip(),rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x,x,x) "" oval_object = oval_object + ''' /Library/Managed Preferences/com.apple.applicationaccess.new.plist boolean(plist/dict/array/string/text() = "{}") '''.format(rule_yaml['id'] + "_" + odv_label,x,str(xpath_search).replace('[',"").replace(']',"").replace("'","")) oval_state = oval_state + ''' true '''.format(rule_yaml['id'] + "_" + odv_label,x) x = x + 1 continue else: oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'].rstrip(),rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x,x,x) oval_object = oval_object + ''' /Library/Managed Preferences/{}.plist'''.format(rule_yaml['id'] + "_" + odv_label,x,payload_type) state_kind = "" if type(value) == bool: oval_object = oval_object + ''' name(//*[contains(text(), "{}")]/following-sibling::*[1]) '''.format(key) state_kind = "boolean" elif type(value) == int: state_kind = "int" oval_object = oval_object + ''' //*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(key) elif type(value) == str: state_kind = "string" oval_object = oval_object + ''' //*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(key) oval_state = oval_state + ''' {} '''.format(rule_yaml['id'] + "_" + odv_label,x,state_kind,value) x = x + 1 continue if payload_type == "com.apple.finder": oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'].rstrip(),rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x,x,x) oval_object = oval_object + ''' /Library/Preferences/com.apple.loginwindow.plist /plist/dict/key[string()="lastUserName"]/following-sibling::*[1]/text() '''.format(x+1999,rule_yaml['id'] + "_" + odv_label,x,x) state_kind = "" if type(value) == bool: oval_object = oval_object + ''' name(//*[contains(text(), "{}")]/following-sibling::*[1]) '''.format(key) state_kind = "boolean" elif type(value) == int: state_kind = "int" oval_object = oval_object + ''' //*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(key) elif type(value) == str: state_kind = "string" oval_object = oval_object + ''' //*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(key) oval_state = oval_state + ''' {} '''.format(rule_yaml['id'] + "_" + odv_label,x,state_kind,value) oval_variable = oval_variable + ''' /Library/Managed Preferences/ /com.apple.finder.plist '''.format(x,x+1999) x += 1 continue if payload_type == "com.apple.DiscRecording": oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'].rstrip(),rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x,x,x) oval_object = oval_object + ''' /Library/Preferences/com.apple.loginwindow.plist /plist/dict/key[string()="lastUserName"]/following-sibling::*[1]/text() '''.format(x+1999,rule_yaml['id'] + "_" + odv_label,x,x) state_kind = "" if type(value) == bool: oval_object = oval_object + ''' name(//*[contains(text(), "{}")]/following-sibling::*[1]) '''.format(key) state_kind = "boolean" elif type(value) == int: state_kind = "int" oval_object = oval_object + ''' //*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(key) elif type(value) == str: state_kind = "string" oval_object = oval_object + ''' //*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(key) oval_state = oval_state + ''' {} '''.format(rule_yaml['id'] + "_" + odv_label,x,state_kind,value) oval_variable = oval_variable + ''' /Library/Managed Preferences/ /com.apple.DiscRecording.plist '''.format(x,x+1999) x += 1 continue if payload_type == "com.apple.Safari" and key == "AutoOpenSafeDownloads": oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'].rstrip(),rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x,x,x) oval_object = oval_object + ''' /Library/Preferences/com.apple.loginwindow.plist /plist/dict/key[string()="lastUserName"]/following-sibling::*[1]/text() '''.format(x+1999,rule_yaml['id'] + "_" + odv_label,x,x) state_kind = "" if type(value) == bool: oval_object = oval_object + ''' name(//*[contains(text(), "{}")]/following-sibling::*[1]) '''.format(key) state_kind = "boolean" elif type(value) == int: state_kind = "int" oval_object = oval_object + ''' //*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(key) elif type(value) == str: state_kind = "string" oval_object = oval_object + ''' //*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(key) oval_state = oval_state + ''' {} '''.format(rule_yaml['id'] + "_" + odv_label,x,state_kind,value) oval_variable = oval_variable + ''' /Library/Managed Preferences/ /com.apple.Safari.plist '''.format(x,x+1999) x += 1 continue if payload_type == "com.apple.systempreferences" and key == "DisabledPreferencePanes" or payload_type == "com.apple.systempreferences" and key == "HiddenPreferencePanes" or payload_type == "com.apple.systempreferences" and key == "DisabledSystemSettings": oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'].rstrip(),rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x,x,x) oval_object = oval_object + ''' /Library/Preferences/com.apple.loginwindow.plist /plist/dict/key[string()="lastUserName"]/following-sibling::*[1]/text() /plist/dict/key[string()="{}"]/following-sibling::*[1]/string[string()="{}"]/text() '''.format(x+1999,rule_yaml['id'] + "_" + odv_label,x,x,key,str(value).strip('[]').strip("'")) oval_state = oval_state + ''' {} '''.format(rule_yaml['id'] + "_" + odv_label,x,str(value).strip('[]').strip("'")) oval_variable = oval_variable + ''' /Library/Managed Preferences/ /com.apple.systempreferences.plist '''.format(x,x+1999) x += 1 continue state_kind = "" if type(value) == bool: state_kind = "boolean" elif type(value) == int: state_kind = "int" elif type(value) == str: state_kind = "string" try: int(value) state_kind = "int" except: pass elif type(value) == dict: state_kind = "string" else: continue oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'].rstrip(),rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x,x,x) oval_object = oval_object + ''' /Library/Managed Preferences/{}.plist'''.format(rule_yaml['id'] + "_" + odv_label,x,payload_type) if state_kind == "boolean": oval_object = oval_object + ''' name(//*[contains(text(), "{}")]/following-sibling::*[1]) '''.format(key) else: if payload_type == "com.apple.mobiledevice.passwordpolicy" and "customRegex" in info: oval_object = oval_object + ''' //*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format("passwordContentRegex") oval_state = oval_state + ''' {} '''.format(rule_yaml['id'] + "_" + odv_label,x,state_kind,value['passwordContentRegex']) x += 1 continue else: oval_object = oval_object + ''' //*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(key) oval_state = oval_state + ''' {} '''.format(rule_yaml['id'] + "_" + odv_label,x,state_kind,value) x += 1 continue else: command = rule_yaml['check'].split("/") if "sntp" in rule_yaml['check']: print(rule_yaml['id'] + " - No relevant oval test") xccdf_rules = replace_ocil(xccdf_rules,x) x += 1 continue if "SPStorageDataType" in rule_yaml['check']: print(rule_yaml['id'] + " - No relevant oval test") xccdf_rules = replace_ocil(xccdf_rules,x) x += 1 continue try: if "fdesetup" in command[3]: print(rule_yaml['id'] + " - No relevant oval test") xccdf_rules = replace_ocil(xccdf_rules,x) x += 1 continue except: pass try: if "profiles" in command[3]: if "/usr/bin/profiles status -type enrollment" in rule_yaml['check']: oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'],x,x+899,x+799) oval_test = oval_test + ''' '''.format(x,x,x+899,x+899,x+799,x+799) oval_object = oval_object + ''' /Library/Managed Preferences/com.apple.extensiblesso.plist /Library/Managed Preferences/com.apple.syspolicy.kernel-extension-policy.plist /Library/Managed Preferences/com.apple.TCC.configuration-profile-policy.plist '''.format(x,x+899,x+799) x += 1 continue except: pass try: if "csrutil" in command[3]: if "authenticated-root" in command[3]: print(rule_yaml['id'] + " - No relevant oval test") xccdf_rules = replace_ocil(xccdf_rules,x) x += 1 continue oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'],rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x,x,x) oval_object = oval_object + ''' SPSoftwareDataType //*[contains(text(), "system_integrity")]/following-sibling::string[position()=1]/text() '''.format(rule_yaml['id'] + "_" + odv_label,x) oval_state = oval_state + ''' SPSoftwareDataType //*[contains(text(), "system_integrity")]/following-sibling::string[position()=1]/text() integrity_enabled '''.format(rule_yaml['id'] + "_" + odv_label,x) x += 1 continue except: pass if "pfctl" in rule_yaml['check']: print(rule_yaml['id'] + " - No relevant oval test") xccdf_rules = replace_ocil(xccdf_rules,x) x += 1 continue if "dump-keychain" in rule_yaml['check']: print(rule_yaml['id'] + " - No relevant oval test") xccdf_rules = replace_ocil(xccdf_rules,x) x += 1 continue try: if "mdmclient" in command[3]: print(rule_yaml['id'] + " - No relevant oval test") xccdf_rules = replace_ocil(xccdf_rules,x) x += 1 continue except: pass try: if "nvram" in command[3]: print(rule_yaml['id'] + " - No relevant oval test") xccdf_rules = replace_ocil(xccdf_rules,x) x += 1 continue except: pass try: if "pmset" in command[3] and "standby" in rule_yaml['check']: oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'],rule_yaml['id'] +"_standbydelayhigh",x, rule_yaml['id'] +"_standbydelaylow",x+877, rule_yaml['id'] +"_highstandbythreshold",x+888) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_standbydelayhigh",x,x,x) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_standbydelaylow",x+877,x+877,x+877) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_highstandbythreshold",x+888,x+888,x+888) standbydelayhigh = str() standbydelaylow = str() highstandbythreshold = str() for line in rule_yaml['fix'].split("----")[1].split("\n"): if line == "": continue if "standbydelayhigh" in line: standbydelayhigh = line.split(" ")[-1].rstrip() if "standbydelaylow" in line: standbydelaylow = line.split(" ")[-1].rstrip() if "highstandbythreshold" in line: highstandbythreshold = line.split(" ")[-1].rstrip() oval_object = oval_object + ''' SPHardwareDataType //*[contains(text(), "platform_UUID")]/following-sibling::string[position()=1]/text() '''.format("hardware UUID",x+999) oval_variable = oval_variable + ''' /Library/Preferences/com.apple.PowerManagement. .plist '''.format(x,x+999) oval_object = oval_object + ''' '''.format(rule_yaml['id'] + "_standbydelayhigh",x,x) oval_object = oval_object + ''' boolean(plist/dict[key="AC Power"]/dict[key="{}"]/integer/text() = "{}") '''.format("High Standby Delay",standbydelayhigh) oval_object = oval_object + ''' '''.format(rule_yaml['id'] + "_standbydelaylow",x+877, x) oval_object = oval_object + ''' boolean(plist/dict[key="AC Power"]/dict[key="{}"]/integer/text() = "{}") '''.format("Standby Delay",standbydelaylow) oval_object = oval_object + ''' '''.format(rule_yaml['id'] + "_highstandbythreshold",x+888, x) oval_object = oval_object + ''' boolean(plist/dict[key="AC Power"]/dict[key="{}"]/integer/text() = "{}") '''.format("Standby Battery Threshold",highstandbythreshold) oval_state = oval_state + ''' true '''.format(rule_yaml['id'] + "_standbydelayhigh",x) oval_state = oval_state + ''' true '''.format(rule_yaml['id'] + "_standbydelaylow",x+877) oval_state = oval_state + ''' true '''.format(rule_yaml['id'] + "_highstandbythreshold",x+888) x += 1 continue except: pass if "sudo -V" in rule_yaml['check']: if "grep" in rule_yaml['check'].split("|")[1]: oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'],rule_yaml['id'] + "_" + odv_label,x,rule_yaml['id'] + "_" + odv_label, x, rule_yaml['id'] + "_" + odv_label,x+5051) oval_test = oval_test + ''' '''.format(x, rule_yaml['id'] + "_" + odv_label, x) oval_test = oval_test + ''' '''.format(x+5051, rule_yaml['id'] + "_" + odv_label, x+5051) check_string = rule_yaml['fix'].split("echo")[1].split('"')[1] oval_object = oval_object + ''' /etc/sudoers {} 1 '''.format(x, rule_yaml['id'] + "_" + odv_label, check_string) oval_object = oval_object + ''' /etc/sudoers.d/ * {} 1 '''.format(x+5051, rule_yaml['id'] + "_" + odv_label, check_string) x = x + 1 continue if "awk" in rule_yaml['check'].split("|")[1]: if "timestamp_type" in rule_yaml['fix'] and rule_yaml['result']['string'] == "tty": oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'],rule_yaml['id'] + "_" + odv_label,x,rule_yaml['id'] + "_" + odv_label, x+8000, rule_yaml['id'] + "_" + odv_label,x+8001, rule_yaml['id'] + "_" + odv_label,x+8002,rule_yaml['id'] + "_" + odv_label,x+8003) oval_test = oval_test + ''' '''.format(x, rule_yaml['id'] + "_" + odv_label, x) oval_test = oval_test + ''' '''.format(x+8000, rule_yaml['id'] + "_" + odv_label, x+8000) oval_test = oval_test + ''' '''.format(x+8001, rule_yaml['id'] + "_" + odv_label, x+8001) oval_test = oval_test + ''' '''.format(x+8002, rule_yaml['id'] + "_" + odv_label, x+8002) oval_object = oval_object + ''' /etc/sudoers timestamp_type 1 '''.format(x, rule_yaml['id'] + "_" + odv_label) oval_object = oval_object + ''' /etc/sudoers.d/ * timestamp_type 1 '''.format(x+8000, rule_yaml['id'] + "_" + odv_label) oval_object = oval_object + ''' /etc/sudoers.d/ * !tty_tickets 1 '''.format(x+8001, rule_yaml['id'] + "_" + odv_label) oval_object = oval_object + ''' /etc/sudoers.d/ * !tty_tickets 1 '''.format(x+8002, rule_yaml['id'] + "_" + odv_label) x = x + 1 continue else: check_string = "Defaults.*.timestamp_type={}".format(rule_yaml['result']['string']) oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'],rule_yaml['id'] + "_" + odv_label,x,rule_yaml['id'] + "_" + odv_label, x+8000, rule_yaml['id'] + "_" + odv_label,x+8001, rule_yaml['id'] + "_" + odv_label,x+8002,rule_yaml['id'] + "_" + odv_label,x+8003) oval_test = oval_test + ''' '''.format(x, rule_yaml['id'] + "_" + odv_label, x) oval_test = oval_test + ''' '''.format(x+5000, rule_yaml['id'] + "_" + odv_label, x+7000) oval_object = oval_object + ''' /etc/sudoers {} 1 '''.format(x, rule_yaml['id'] + "_" + odv_label, check_string) oval_object = oval_object + ''' /etc/sudoers.d/ * {} 1 '''.format(x+7000, rule_yaml['id'] + "_" + odv_label, check_string) x = x + 1 continue if "ssh_config" in rule_yaml['discussion'] and "dscl" in rule_yaml['check']: oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'],rule_yaml['id'] + "_" + odv_label,x,rule_yaml['id'] + "_" + odv_label, x+5010, rule_yaml['id'] + "_" + odv_label,x+5025) oval_test = oval_test + ''' '''.format(x, rule_yaml['id'] + "_" + odv_label, x) oval_test = oval_test + ''' '''.format(x+5010, rule_yaml['id'] + "_" + odv_label, x+5010) oval_test = oval_test + ''' '''.format(x+5025, rule_yaml['id'] + "_" + odv_label, x+5025) regex = r"(?<=grep).*$" matches = re.finditer(regex, rule_yaml['check'], re.MULTILINE) matchy_match = "" for matchNum, match in enumerate(matches, start=1): matchy_match = match.group() ssh_config_pattern = matchy_match.split('"')[1] oval_object = oval_object + ''' /etc/ssh/ssh_config {} 1 '''.format(x, rule_yaml['id'] + "_" + odv_label, ssh_config_pattern) oval_object = oval_object + ''' /etc/ssh/ssh_config.d/ * {} 1 '''.format(x+5010, rule_yaml['id'] + "_" + odv_label, ssh_config_pattern) oval_object = oval_object + ''' {} 1 .* oval:mscp:ste:{} '''.format(x+5025,rule_yaml['id'] + "_" + odv_label,x,ssh_config_pattern,x+999,x+999) oval_state = oval_state + ''' ^[^_\s].* 0 0 /usr/bin/false '''.format(x+999) oval_variable = oval_variable + ''' /.ssh/config '''.format(x,x+999) x = x + 1 continue if "sshd -T" in rule_yaml['check'] and "fips" in rule_yaml['check'] or "sshd -G" in rule_yaml['check'] and "fips" in rule_yaml['check']: fipslist = rule_yaml['check'].split("\n")[0].split("(")[1].replace(")","").replace('" "',"\n").replace('"',"") oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'],rule_yaml['id'] + "_" + odv_label,x,rule_yaml['id'] + "_" + odv_label, x+6000, rule_yaml['id'] + "_" + odv_label,x+6001) oval_test = oval_test + ''' '''.format(x, rule_yaml['id'] + "_" + odv_label, x) oval_test = oval_test + ''' '''.format(x+6000, rule_yaml['id'] + "_" + odv_label, x+6000) oval_object = oval_object + ''' /etc/ssh/sshd_config {} 1 '''.format(x, rule_yaml['id'] + "_" + odv_label, fipslist) oval_object = oval_object + ''' /etc/ssh/sshd_config.d/ * {} 1 '''.format(x+6000, rule_yaml['id'] + "_" + odv_label, fipslist) x = x + 1 continue if "sshd -T" in rule_yaml['check'] or "sshd -G" in rule_yaml['check']: oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'],rule_yaml['id'] + "_" + odv_label,x,rule_yaml['id'] + "_" + odv_label, x+6000, rule_yaml['id'] + "_" + odv_label,x+6001) oval_test = oval_test + ''' '''.format(x, rule_yaml['id'] + "_" + odv_label, x) oval_test = oval_test + ''' '''.format(x+6000, rule_yaml['id'] + "_" + odv_label, x+6000) sshd_config_pattern = "" if "grep" in rule_yaml['check']: regex = r"(?<=grep).*$" matches = re.finditer(regex, rule_yaml['check'], re.MULTILINE) matchy_match = "" for matchNum, match in enumerate(matches, start=1): matchy_match = match.group() sshd_config_pattern = "" if '"' in matchy_match: sshd_config_pattern = matchy_match.split('"')[1] elif "'" in matchy_match: sshd_config_pattern = matchy_match.split("'")[1] if "awk" in rule_yaml['check']: matchy_match = rule_yaml['check'].split("'")[1].split("/")[1] for item in rule_yaml['result']: sshd_config_pattern = matchy_match + " " + str(rule_yaml['result'][item]) oval_object = oval_object + ''' /etc/ssh/sshd_config {} 1 '''.format(x, rule_yaml['id'] + "_" + odv_label, sshd_config_pattern) oval_object = oval_object + ''' /etc/ssh/sshd_config.d/ * {} 1 '''.format(x+6000, rule_yaml['id'] + "_" + odv_label, sshd_config_pattern) x = x + 1 continue try: if "pmset" in command[3]: oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'],rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x,x,x) oval_object = oval_object + ''' /Library/Preferences/com.apple.PowerManagement.plist'''.format(rule_yaml['id'] + "_" + odv_label,x) pmset_key = str() if "powernap" in rule_yaml['check']: pmset_key = "DarkWakeBackgroundTasks" if "womp" in rule_yaml['check']: pmset_key = "Wake On LAN" oval_object = oval_object + ''' boolean(plist/dict[key="AC Power"]/dict[key="{}"]/integer/text() = "{}") '''.format(pmset_key,rule_yaml['fix'].split("----")[1].replace("\n","")[-1]) oval_state = oval_state + ''' true '''.format(rule_yaml['id'] + "_" + odv_label,x) x += 1 continue except: pass if "socketfilterfw" in rule_yaml['check']: oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'],rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x,x,x) if rule_yaml['check'].split()[1] == "--getloggingmode": firewall_variable = "loggingenabled" elif rule_yaml['check'].split()[1] == "--getstealthmode": firewall_variable = "stealthenabled" elif rule_yaml['check'].split()[1] == "--getglobalstate": firewall_variable = "globalstate" oval_object = oval_object + ''' /Library/Preferences/com.apple.alf.plist //*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(rule_yaml['id'] + "_" + odv_label,x,firewall_variable) oval_state = oval_state + ''' 1 '''.format(rule_yaml['id'] + "_" + odv_label,x) x += 1 continue try: if "systemsetup" in command[3]: oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'],rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x,x,x) oval_object = oval_object + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x) state_test = "" if "-getnetworktimeserver" in rule_yaml['check']: timeservers = rule_yaml['result']['string'] state_test = ''' {} '''.format(timeservers) oval_state = oval_state + ''' {} '''.format(rule_yaml['id'] + "_" + odv_label,x,state_test) except: pass abc = 0 if "defaults" in rule_yaml['check'] and "grep" in rule_yaml['check'] and "CURRENT_USER" in rule_yaml['check']: regex = r"(?<=\()(.*?)(?=\))" test_str = rule_yaml['check'].split("grep")[1] matches = re.finditer(regex, test_str, re.MULTILINE) matchy_match = "" for matchNum, match in enumerate(matches, start=1): matchy_match = match.group() oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'],rule_yaml['id'] + "_" + odv_label,x) for multi_grep in matchy_match.split("|"): oval_definition = oval_definition + ''' '''.format(rule_yaml['id']+"_"+str(abc),x) oval_test = oval_test + ''' '''.format(rule_yaml['id']+"_"+str(abc),x,x,x) key = matchy_match.split("|")[abc].split(" = ")[0].replace("\"","") value = matchy_match.split("|")[abc].split(" = ")[1].replace(";","") if "$CURRENT_USER" in rule_yaml['check']: oval_object = oval_object + ''' .* oval:mscp:ste:{} '''.format(x+1999,x+1999) oval_state = oval_state + ''' ^[^_\s].* 0 0 /usr/bin/false '''.format(x+1999) plist = rule_yaml['check'].split("read")[1].split()[0].replace(".plist","") oval_variable = oval_variable + ''' /Library/Preferences/{}. plist '''.format(x,x+1999,plist) oval_object = oval_object + ''' '''.format(rule_yaml['id']+"_"+str(abc),x,x) oval_datatype = "" try: int(value) oval_datatype = "int" oval_object = oval_object + ''' //*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(key) except: if value.lower() == "true" or value.lower == "false": oval_datatype = "boolean" oval_object = oval_object + ''' name(//*[contains(text(), "{}")]/following-sibling::*[1]) '''.format(key) else: oval_datatype = "string" oval_object = oval_object + ''' //*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(key) oval_state = oval_state + ''' {} '''.format(rule_yaml['id']+"_"+str(abc),x,oval_datatype,value) abc =+ 1 x = x+1 oval_definition = oval_definition + ''' ''' oval_definition = re.sub('(?=\n\[NOTE\])(?s)(.*)\=\n<', '<', oval_definition) x = x+1 break if "defaults" in rule_yaml['check']: if rule_yaml['id'] == "system_settings_hot_corners_secure" or rule_yaml['id'] == "sysprefs_hot_corners_secure": oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'],rule_yaml['id'] + "_" + odv_label,x,rule_yaml['id'] + "_" + odv_label,x+5000,rule_yaml['id'] + "_" + odv_label,x+5001,rule_yaml['id'] + "_" + odv_label,x+5002) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x,x,x) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x+5000,x+5000,x+5000) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x+5001,x+5001,x+5001) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x+5002,x+5002,x+5002) plist = rule_yaml['check'].split("read")[1].split()[0].replace(".plist","") check_length = len(rule_yaml['check'].split()) key = rule_yaml['check'].split("\n")[0].replace(" 2>/dev/null","").split()[-1].replace('"','').replace(")",'') oval_object = oval_object + ''' .* oval:mscp:ste:{} '''.format(x+1999,x+1999,rule_yaml['id'] + "_" + odv_label,x,x) oval_object = oval_object + '''//*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(key) key = rule_yaml['check'].split("\n")[1].replace(" 2>/dev/null","").split()[-1].replace('"','').replace(")",'') oval_object = oval_object + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x+5000,x) oval_object = oval_object + '''//*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(key) key = rule_yaml['check'].split("\n")[2].replace(" 2>/dev/null","").split()[-1].replace('"','').replace(")",'') oval_object = oval_object + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x+5001,x) oval_object = oval_object + '''//*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(key) key = rule_yaml['check'].split("\n")[3].replace(" 2>/dev/null","").split()[-1].replace('"','').replace(")",'') oval_object = oval_object + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x+5002,x) oval_object = oval_object + '''//*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(key) oval_state = oval_state + ''' ^[^_\s].* 0 0 /usr/bin/false '''.format(x+1999) after_user = plist.split('"')[2] oval_variable = oval_variable + ''' {} .plist '''.format(x,x+1999,after_user,x+999) try: check_if = rule_yaml['check'].split("\n")[5] modifier = 0 for n in check_if.split(): if n.replace('"',"").isdigit(): if modifier >= 4999: modifier = modifier + 1 oval_state = oval_state + ''' {} '''.format(rule_yaml['id'] + "_" + odv_label,x+modifier,n.replace('"',"")) if modifier == 0: modifier = 4999 x = x + 1 continue except: x = x + 1 continue oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'],rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x,x,x) plist = rule_yaml['check'].split("read")[1].split()[0].replace(".plist","") if "ByHost" in rule_yaml['fix'] or "currentHost" in rule_yaml['fix']: oval_object = oval_object + ''' SPHardwareDataType //*[contains(text(), "platform_UUID")]/following-sibling::string[position()=1]/text() '''.format("hardware UUID",x+999) if "$CURRENT_USER" in rule_yaml['check']: check_length = len(rule_yaml['check'].split()) key = rule_yaml['check'].split()[check_length-1] oval_object = oval_object + ''' .* oval:mscp:ste:{} '''.format(x+1999,x+1999,rule_yaml['id'] + "_" + odv_label,x,x) try: rule_yaml['result']['boolean'] oval_object = oval_object + ''' name(//*[contains(text(), "{}")]/following-sibling::*[1]) '''.format(key) except: oval_object = oval_object + '''//*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(key) oval_state = oval_state + ''' ^[^_\s].* 0 0 /usr/bin/false '''.format(x+1999) oval_variable = oval_variable + ''' /Library/Preferences/ByHost/{}. .plist '''.format(x,x+1999,plist,x+999) else: check_length = len(rule_yaml['check'].split()) key = rule_yaml['check'].replace(" 2>/dev/null","").split()[check_length-1] oval_object = oval_object + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x,x) try: rule_yaml['result']['boolean'] oval_object = oval_object + ''' name(//*[contains(text(), "{}")]/following-sibling::*[1]) '''.format(key) except: oval_object = oval_object + ''' //*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(key) oval_variable = oval_variable + ''' {}. .plist '''.format(x,plist,x+999) elif "$CURRENT_USER" in rule_yaml['check']: check_length = len(rule_yaml['check'].split()) key = rule_yaml['check'].replace(" 2>/dev/null","").split()[-1] oval_object = oval_object + ''' .* oval:mscp:ste:{} '''.format(x+1999,x+1999,rule_yaml['id'] + "_" + odv_label,x,x) try: rule_yaml['result']['boolean'] oval_object = oval_object + ''' name(//*[contains(text(), "{}")]/following-sibling::*[1]) '''.format(key) except: oval_object = oval_object + '''//*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(key) oval_state = oval_state + ''' ^[^_\s].* 0 0 /usr/bin/false '''.format(x+1999) oval_variable = oval_variable + ''' /Library/Preferences/{}. plist '''.format(x,x+1999,plist,x+999) else: if plist[-6:] != ".plist": plist = plist + ".plist" plist_key = rule_yaml['check'].replace(" 2>/dev/null","").split(" ")[3].rstrip() oval_object = oval_object + ''' {}'''.format(rule_yaml['id'] + "_" + odv_label,x,plist) try: rule_yaml['result']['boolean'] oval_object = oval_object + ''' name(//*[contains(text(), "{}")]/following-sibling::*[1]) '''.format(plist_key) except: oval_object = oval_object + ''' //*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(plist_key) datatype = "" plist_key = rule_yaml['check'].split(" ")[3].rstrip() for key in rule_yaml['result']: datatype = key if datatype == "integer": oval_datatype = "int" else: oval_datatype = datatype if oval_datatype == "boolean" and rule_yaml['result'][datatype] == 0: value = "false" elif oval_datatype == "boolean" and rule_yaml['result'][datatype] == 1: value = "true" else: value = rule_yaml['result'][datatype] oval_state = oval_state + ''' {} '''.format(rule_yaml['id'] + "_" + odv_label,x,oval_datatype,value) oval_definition = re.sub('(?=\n\[NOTE\])(?s)(.*)\=\n<', '<', oval_definition) x = x+1 continue try: if "security" in command[3]: if rule_yaml['check'].split()[1] == "authorizationdb": check = rule_yaml['check'].split("|") authdb = rule_yaml['check'].split()[3] if len(check) > 2: matches = re.findall(r'(?<=\>)(.*)(?=\<)',check[1]) key = str(matches).replace("[","").replace("]","").replace("'","") length = len(check[2].split()) last_string = check[2].split()[length-1].replace('"',"").replace("<","").replace(">","").replace("/","") oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'],rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x,x,x) oval_object = oval_object + ''' {} boolean(//key[text()="{}"]/following-sibling::{}) '''.format(rule_yaml['id'] + "_" + odv_label,x,authdb,key,last_string) oval_state = oval_state + ''' true '''.format(rule_yaml['id'] + "_" + odv_label,x) else: key = (check[1].split()[2].replace("'","")) key = key.split('>')[1].split('<')[0] oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'],rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x,x,x) oval_object = oval_object + ''' {} //*[contains(text(), "{}")]/text() '''.format(rule_yaml['id'] + "_" + odv_label,x,authdb,key) oval_state = oval_state + ''' {} '''.format(rule_yaml['id'] + "_" + odv_label,x,key) else: if "authorizationdb" in rule_yaml['check']: regex = r"=\(.*.\)" matchy_match = [] matches = re.finditer(regex, rule_yaml['check'], re.MULTILINE) for matchNum, match in enumerate(matches, start=1): matchy_match = match.group().replace('=(',"").replace(")","").replace('"','').split() oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion']) for match in matchy_match: oval_definition = oval_definition + ''' '''.format(rule_yaml['id'] + "+" + match, x) oval_test = oval_test + ''' '''.format(match,x,x,x) key="shared" value="" if "false" in rule_yaml["check"]: value="false" else: value="true" oval_object = oval_object + ''' {} boolean(//key[text()="{}"]/following-sibling::{}) '''.format(match,x,match,key,value) oval_state = oval_state + ''' true '''.format(match,x) x += 1 oval_definition = oval_definition + "" x += 1 continue except: pass if "/bin/rm" in rule_yaml['fix'] and "/bin/ls" in rule_yaml['check']: oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'],rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(x,rule_yaml['id'] + "_" + odv_label,x) path = rule_yaml['fix'].split("----")[1].split(" ")[-1] oval_object = oval_object + ''' {} '''.format(x,rule_yaml['id'] + "_" + odv_label,path.rstrip()) x += 1 continue try: if "ls" in command[2] or "stat" in command[3].split()[0]: if '/Library/Security/PolicyBanner.rtf' in rule_yaml['check']: oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'],rule_yaml['id'] + "_" + odv_label,x,rule_yaml['id'] + "_" + odv_label,x+2999) oval_test = oval_test + ''' '''.format(x,rule_yaml['id'] + "_" + odv_label,x,x+2999,rule_yaml['id'] + "_" + odv_label,x+2999) oval_object = oval_object + ''' /Library/Security/PolicyBanner.rtf /Library/Security/PolicyBanner.rtfd '''.format(x,rule_yaml['id'] + "_" + odv_label,x+2999,rule_yaml['id']) x = x + 1 continue s = rule_yaml['check'] config_file = str() oval_variable_need = bool() if "grep" in s.split()[2]: oval_variable_need = True grep_search = re.search('\((.*?)\)', s).group(1) substring = grep_search.split("|")[0] regex = re.search('\'(.*?)\'', substring).group(1) try: regex = re.search('/(.*?)/', regex).group(1) except: regex = regex config_file = substring = grep_search.split("|")[0].split()[-1] oval_object = oval_object + ''' {} {}:\s*(.*)$ 1 '''.format(rule_yaml['id'] + "_" + odv_label, x+999, config_file, regex) oval_variable = oval_variable + ''' '''.format(x,rule_yaml['id'] + "_" + odv_label,x+999) else: oval_variable_need = False config_file = s.split()[2] s = rule_yaml['fix'] fix_command = re.search('-\n(.*?)\n-', s).group(1).split('$')[0] oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'].rstrip(),rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(x,rule_yaml['id'] + "_" + odv_label,x,x) if "-" in fix_command and "R" in fix_command or rule_yaml['fix'].split("\n")[2][-1] == "*": behavior = '' if "audit" in rule_yaml['id']: filename = 'current' else: behavior = "" filename = '' if oval_variable_need == True: oval_object = oval_object + ''' {} {} '''.format(rule_yaml['id'] + "_" + odv_label,x,behavior,x,filename) else: oval_object = oval_object + ''' {} {} '''.format(rule_yaml['id'] + "_" + odv_label,x,behavior,config_file) state_test = "" if "-" in fix_command and "N" in fix_command and "chmod" in fix_command: state_test = ''' false ''' elif "chgrp" in fix_command: state_test = ''' {} '''.format(rule_yaml['result']['integer']) elif "chown" in fix_command: state_test = ''' {} '''.format(rule_yaml['result']['integer']) elif "chmod" in fix_command: perms = fix_command.split()[1] if perms[0] == "0": state_test = ''' false false false''' if perms[0] == "1": state_test = ''' false false true''' elif perms[0] == "2": state_test = ''' false true false''' elif perms[0] == "3": state_test = ''' false true true''' elif perms[0] == "4": state_test = ''' true false false''' elif perms[0] == "5": state_test = ''' true false true''' elif perms[0] == "6": state_test = ''' true true false''' elif perms[0] == "7": state_test = ''' true true true''' if perms[1] == "0": state_test = state_test + ''' false false false''' elif perms[1] == "1": state_test = state_test + ''' false false true''' elif perms[1] == "2": state_test = state_test + ''' false true false''' elif perms[1] == "3": state_test = state_test + ''' false true true''' elif perms[1] == "4": state_test = state_test + ''' true false false''' elif perms[1] == "5": state_test = state_test + ''' true false true''' elif perms[1] == "6": state_test = state_test + ''' true true false''' elif perms[1] == "7": state_test = state_test + ''' true true true''' if perms[2] == "0": state_test = state_test + ''' false false false''' if perms[2] == "1": state_test = state_test + ''' false false true''' elif perms[2] == "1": state_test = state_test + ''' false false true''' elif perms[2] == "2": state_test = state_test + ''' false true false''' elif perms[2] == "3": state_test = state_test + ''' false true true''' elif perms[2] == "4": state_test = state_test + ''' true false false''' elif perms[2] == "5": state_test = state_test + ''' true false true''' elif perms[2] == "6": state_test = state_test + ''' true true false''' elif perms[2] == "7": state_test = state_test + ''' true true true''' oval_state = oval_state + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x) + state_test + ''' ''' x += 1 continue except: pass try: if "dscl" in command[3]: if "UserShell" in rule_yaml['check']: shell = rule_yaml['check'].split()[9].replace('"','') oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'],rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x,x,x) oval_object = oval_object + ''' {} '''.format(rule_yaml['id'] + "_" + odv_label,x,command[5].split()[0]) oval_state = oval_state + ''' {} '''.format(rule_yaml['id'] + "_" + odv_label,x,shell) x += 1 continue except: pass try: if "awk" in command[3]: awk_file = "" awk_search = "" field_sep = "" if "grep -qE" in rule_yaml['fix']: awk_file = rule_yaml['fix'].split(" ")[3].strip(" ") awk_search = rule_yaml['fix'].split(" ")[2].strip("\"") elif "grep" in rule_yaml['check']: awk_file = rule_yaml['check'].split("|")[0].split(" ")[-2] awk_search = rule_yaml['check'].split("|")[-1].split(" ")[-2].strip("\'") else: awk_file = rule_yaml['check'].split("'")[2].strip(" ") awk_search = rule_yaml['check'].split("'")[1].split("/")[1] try: field_sep = rule_yaml['check'].split("-F")[1].split(" ")[0].replace('\"',"") except: field_sep = " " try: awk_result = rule_yaml['result']['string'] except: awk_result = str(rule_yaml['result']['integer']) if awk_search[0] != "^": awk_search = "^" + awk_search + field_sep + awk_result else: awk_search = awk_search + field_sep + awk_result oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'].rstrip(),rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(x, rule_yaml['id'] + "_" + odv_label, x) oval_object = oval_object + ''' {} {} 1 '''.format(x,rule_yaml['id'] + "_" + odv_label,awk_file.rstrip(), awk_search) x += 1 continue except: pass try: if "grep" in command[3] and not "pgrep" in command[3]: if "bannerText" in rule_yaml['check'] or "fips_" in rule_yaml['check']: text_to_find = rule_yaml['check'].split("=")[1].split('"')[1] matches = text_to_find.replace(".","\.").replace(")","\)").replace("(","\(").replace("*","\*") oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'].rstrip(),rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(x, rule_yaml['id'] + "_" + odv_label, x) file_path = rule_yaml["check"].split(" ")[-1].rstrip() oval_object = oval_object + ''' {} {} 1 '''.format(x,rule_yaml['id'] + "_" + odv_label,file_path,matches) x += 1 continue else: s = rule_yaml['check'] try: grep_search = re.search('"(.*?)"', s).group(1) except: grep_search = re.search('\'(.*?)\'', s).group(1) grep_file = rule_yaml['check'].split(grep_search,1)[1].split(" ")[1] oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'].rstrip(),rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(x, rule_yaml['id'] + "_" + odv_label, x) oval_object = oval_object + ''' {} {} 1 '''.format(x,rule_yaml['id'] + "_" + odv_label,grep_file.rstrip(),grep_search) x += 1 continue except: pass try: if "launchctl" in command[2] or "launchctl" in rule_yaml['fix']: if "disable" in command[2] and "=> true" in rule_yaml['check'] or "unload -w" in rule_yaml['fix'] or "disable" in command[2] and "=> disabled" in rule_yaml['check']: oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'].rstrip(),rule_yaml['id'] + "_" + odv_label,x,rule_yaml['id'] + "_" + odv_label,x+999) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x,x,x,x+999,rule_yaml['id'] + "_" + odv_label,x+999) domain = str() if "launchctl" not in rule_yaml['check']: domain = rule_yaml['fix'].split()[4].split('/')[4].replace(".plist","") else: s = command[5].split()[2] domain = re.search('"(.*?)"', s).group(1) oval_object = oval_object + ''' /var/db/com.apple.xpc.launchd/disabled.plist name(//*[contains(text(), "{}")]/following-sibling::*[1]) '''.format(rule_yaml['id'] + "_" + odv_label,x,domain,x+999,rule_yaml['id'] + "_" + odv_label,domain.replace('(','').replace(')','')) status = "" if "enable" in rule_yaml["fix"]: status = "false" else: status = "true" oval_state = oval_state + ''' {} '''.format(rule_yaml['id'] + "_" + odv_label,x,status) elif "launchctl unload" in rule_yaml['fix']: oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'].rstrip(),rule_yaml['id'] + "_" + odv_label,x,rule_yaml['id'] + "_" + odv_label,x+999) oval_test = oval_test + ''' '''.format(x,rule_yaml['id'] + "_" + odv_label,x) domain = str() if "launchctl" not in rule_yaml['check']: domain = rule_yaml['fix'].split()[4].split('/')[4].replace(".plist","") else: s = command[5].split()[2] domain = re.search('"(.*?)"', s).group(1) oval_object = oval_object + ''' '''.format(x, rule_yaml['id'] + "_" + odv_label,domain.replace('(','').replace(')','')) elif "defaults write" in rule_yaml['fix']: oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'],rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x,x,x) plist = rule_yaml['fix'].split(" ")[2].replace(".plist","") # plist = rule_yaml['check'].split("read")[1].split()[0].replace(".plist","") if "ByHost" in rule_yaml['fix'] or "currentHost" in rule_yaml['fix']: oval_object = oval_object + ''' SPHardwareDataType //*[contains(text(), "platform_UUID")]/following-sibling::string[position()=1]/text() '''.format("hardware UUID",x+999) if "$CURRENT_USER" in rule_yaml['check']: key = rule_yaml['fix'].split("defaults")[1].split(" ")[3] oval_object = oval_object + ''' .* oval:mscp:ste:{} '''.format(x+1999,x+1999,rule_yaml['id'] + "_" + odv_label,x,x) if rule_yaml['fix'].split("defaults")[1].split(" ")[4] == "-bool": rule_yaml['result']['boolean'] oval_object = oval_object + ''' name(//*[contains(text(), "{}")]/following-sibling::*[1]) '''.format(key) else: oval_object = oval_object + '''//*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(key) oval_state = oval_state + ''' ^[^_\s].* 0 0 /usr/bin/false '''.format(x+1999) oval_variable = oval_variable + ''' /Library/Preferences/ByHost/{}. .plist '''.format(x,x+1999,plist,x+999) else: key = rule_yaml['fix'].split("defaults")[1].split(" ")[3] oval_object = oval_object + ''' '''.format(rule_yaml['id'] + "_" + odv_label,x,x) if rule_yaml['fix'].split("defaults")[1].split(" ")[4] == "-bool": oval_object = oval_object + ''' name(//*[contains(text(), "{}")]/following-sibling::*[1]) '''.format(key) else: oval_object = oval_object + ''' //*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(key) oval_variable = oval_variable + ''' {}. .plist '''.format(x,plist,x+999) elif "$CURRENT_USER" in rule_yaml['check']: check_length = len(rule_yaml['check'].split()) key = rule_yaml['fix'].split("defaults")[1].split(" ")[3] oval_object = oval_object + ''' .* oval:mscp:ste:{} '''.format(x+1999,x+1999,rule_yaml['id'] + "_" + odv_label,x,x) if rule_yaml['fix'].split("defaults")[1].split(" ")[4] == "-bool": oval_object = oval_object + ''' name(//*[contains(text(), "{}")]/following-sibling::*[1]) '''.format(key) else: oval_object = oval_object + '''//*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(key) oval_state = oval_state + ''' ^[^_\s].* 0 0 /usr/bin/false '''.format(x+1999) oval_variable = oval_variable + ''' /Library/Preferences/{}. plist '''.format(x,x+1999,plist,x+999) else: if plist[-6:] != ".plist": plist = plist + ".plist" plist_key = rule_yaml['fix'].split("defaults")[1].split(" ")[3] oval_object = oval_object + ''' {}'''.format(rule_yaml['id'] + "_" + odv_label,x,plist) try: rule_yaml['result']['boolean'] oval_object = oval_object + ''' name(//*[contains(text(), "{}")]/following-sibling::*[1]) '''.format(plist_key) except: oval_object = oval_object + ''' //*[contains(text(), "{}")]/following-sibling::*[1]/text() '''.format(plist_key) datatype = "" plist_key = rule_yaml['fix'].split("defaults")[1].split(" ")[3] oval_datatype = rule_yaml['fix'].split("defaults")[1].split(" ")[4].replace("-","") if oval_datatype == "integer": oval_datatype = "int" if oval_datatype == "bool": oval_datatype = "boolean" value = rule_yaml['fix'].split("defaults")[1].split(" ")[5].replace(";","") oval_state = oval_state + ''' {} '''.format(rule_yaml['id'] + "_" + odv_label,x,oval_datatype,value) oval_definition = re.sub('(?=\n\[NOTE\])(?s)(.*)\=\n<', '<', oval_definition) x = x+1 continue else: oval_definition = oval_definition + ''' {} {} '''.format(x,rule_yaml['title'],cce,rule_yaml['id'] + "_" + odv_label,rule_yaml['discussion'].rstrip(),rule_yaml['id'] + "_" + odv_label,x) oval_test = oval_test + ''' '''.format(x,rule_yaml['id'] + "_" + odv_label,x) domain = command[5].split()[2] domain = domain.replace('"','').replace("'",'') ########### label_obj = '