def main(): if len(sys.argv) < 2: print "Provide an OVAL file that contains inventory definitions." print "This script extracts these definitions and writes them to STDOUT." sys.exit(1) ovalfile = sys.argv[1] cpedictfile = sys.argv[2] idname = sys.argv[3] # parse oval file ovaltree = parse_xml_file(ovalfile) # extract inventory definitions # making (dubious) assumption that all inventory defs are CPE defs = ovaltree.find("./{%s}definitions" % oval_ns) inventory_defs = defs.findall(".//{%s}definition[@class='inventory']" % oval_ns) defs.clear() [defs.append(inventory_def) for inventory_def in inventory_defs] tests = ovaltree.find("./{%s}tests" % oval_ns) cpe_tests = extract_referred_nodes(defs, tests, "test_ref") tests.clear() [tests.append(cpe_test) for cpe_test in cpe_tests] states = ovaltree.find("./{%s}states" % oval_ns) cpe_states = extract_referred_nodes(tests, states, "state_ref") states.clear() [states.append(cpe_state) for cpe_state in cpe_states] objects = ovaltree.find("./{%s}objects" % oval_ns) cpe_objects = extract_referred_nodes(tests, objects, "object_ref") objects.clear() [objects.append(cpe_object) for cpe_object in cpe_objects] variables = ovaltree.find("./{%s}variables" % oval_ns) cpe_variables = extract_referred_nodes(ovaltree, variables, "var_ref") if cpe_variables: variables.clear() [variables.append(cpe_variable) for cpe_variable in cpe_variables] else: ovaltree.remove(variables) # turn IDs into meaningless numbers translator = idtranslate.idtranslator("./output/" + idname + ".ini", idname) ovaltree = translator.translate(ovaltree) newovalfile = ovalfile.replace("oval", "cpe-oval") newovalfile = newovalfile.replace("unlinked", idname) ET.ElementTree(ovaltree).write(newovalfile) # replace and sync IDs, href filenames in input cpe dictionary file cpedicttree = parse_xml_file(cpedictfile) newcpedictfile = idname + "-" + os.path.basename(cpedictfile) for check in cpedicttree.findall(".//{%s}check" % cpe_ns): check.set("href", os.path.basename(newovalfile)) check.text = translator.assign_id("{" + oval_ns + "}definition", check.text) ET.ElementTree(cpedicttree).write("./output/" + newcpedictfile) sys.exit(0)
def main(): global definitions global tests global objects global states global variables if len(sys.argv) < 2: print "Provide the name of an XML file, which contains the definition to test." sys.exit(1) for testfile in sys.argv[1:]: body = read_ovaldefgroup_file(testfile) defname = add_oval_elements(body) ovaltree = ET.fromstring(header + footer) # append each major element type, if it has subelements for element in [definitions, tests, objects, states, variables]: if element.getchildren(): ovaltree.append(element) # re-map all the element ids from meaningful names to meaningless numbers testtranslator = idtranslate.idtranslator( "testids.ini", "oval:scap-security-guide.testing") ovaltree = testtranslator.translate(ovaltree) (ovalfile, fname) = tempfile.mkstemp(prefix=defname, suffix=".xml") os.write(ovalfile, ET.tostring(ovaltree)) os.close(ovalfile) print "Evaluating with OVAL tempfile : " + fname # temporary workaround for fedora/redhat oscap version differences # (distname, distversion, distcodename) = platform.linux_distribution(full_distribution_name=0) # if distname == 'redhat': # subprocess.call("oscap oval eval --result-file "+ fname + "-results " + fname, shell=True) # else: # content requires OVAL 5.8 support, which is only supported by openscap 0.8 or later # for RHEL 6, this implies installing openscap from source until RPM is released subprocess.call("oscap oval eval --results " + fname + "-results " + fname, shell=True) # perhaps delete tempfile? definitions = ET.Element("definitions") tests = ET.Element("tests") objects = ET.Element("objects") states = ET.Element("states") variables = ET.Element("variables") sys.exit(0)
def main(): global definitions global tests global objects global states global variables if len(sys.argv) < 2: print "Provide the name of an XML file, which contains the definition to test." sys.exit(1) for testfile in sys.argv[1:]: body = read_ovaldefgroup_file(testfile) defname = add_oval_elements(body) ovaltree = ET.fromstring(header + footer) # append each major element type, if it has subelements for element in [definitions, tests, objects, states, variables]: if element.getchildren(): ovaltree.append(element) # re-map all the element ids from meaningful names to meaningless numbers testtranslator = idtranslate.idtranslator("testids.ini", "oval:scap-security-guide.testing") ovaltree = testtranslator.translate(ovaltree) (ovalfile, fname) = tempfile.mkstemp(prefix=defname,suffix=".xml") os.write(ovalfile, ET.tostring(ovaltree)) os.close(ovalfile) print "Evaluating with OVAL tempfile : " + fname # temporary workaround for fedora/redhat oscap version differences # (distname, distversion, distcodename) = platform.linux_distribution(full_distribution_name=0) # if distname == 'redhat': # subprocess.call("oscap oval eval --result-file "+ fname + "-results " + fname, shell=True) # else: # content requires OVAL 5.8 support, which is only supported by openscap 0.8 or later # for RHEL 6, this implies installing openscap from source until RPM is released subprocess.call("oscap oval eval --results "+ fname + "-results " + fname, shell=True) # perhaps delete tempfile? definitions = ET.Element("definitions") tests = ET.Element("tests") objects = ET.Element("objects") states = ET.Element("states") variables = ET.Element("variables") sys.exit(0)
def main(): global definitions global tests global objects global states global variables if len(sys.argv) < 2: print "Provide the name of an XML file, which contains the definition to test." sys.exit(1) for testfile in sys.argv[1:]: body = read_ovaldefgroup_file(testfile) defname = add_oval_elements(body) ovaltree = ET.fromstring(header + footer) # append each major element type, if it has subelements for element in [definitions, tests, objects, states, variables]: if element.getchildren(): ovaltree.append(element) # re-map all the element ids from meaningful names to meaningless numbers testtranslator = idtranslate.idtranslator( "testids.ini", "scap-security-guide.testing") ovaltree = testtranslator.translate(ovaltree) (ovalfile, fname) = tempfile.mkstemp(prefix=defname, suffix=".xml") os.write(ovalfile, ET.tostring(ovaltree)) os.close(ovalfile) print "Evaluating with OVAL tempfile : " + fname print "Writing results to : " + fname + "-results" subprocess.call("oscap oval eval --results " + fname + "-results " + fname, shell=True) # perhaps delete tempfile? definitions = ET.Element("definitions") tests = ET.Element("tests") objects = ET.Element("objects") states = ET.Element("states") variables = ET.Element("variables") sys.exit(0)
def main(): global definitions global tests global objects global states global variables if len(sys.argv) < 2: print "Provide the name of an XML file, which contains the definition to test." sys.exit(1) for testfile in sys.argv[1:]: body = read_ovaldefgroup_file(testfile) defname = add_oval_elements(body) ovaltree = ET.fromstring(header + footer) # append each major element type, if it has subelements for element in [definitions, tests, objects, states, variables]: if element.getchildren(): ovaltree.append(element) # re-map all the element ids from meaningful names to meaningless numbers testtranslator = idtranslate.idtranslator("testids.ini", "scap-security-guide.testing") ovaltree = testtranslator.translate(ovaltree) (ovalfile, fname) = tempfile.mkstemp(prefix=defname, suffix=".xml") os.write(ovalfile, ET.tostring(ovaltree)) os.close(ovalfile) print "Evaluating with OVAL tempfile : " + fname print "Writing results to : " + fname + "-results" subprocess.call("oscap oval eval --results " + fname + "-results " + fname, shell=True) # perhaps delete tempfile? definitions = ET.Element("definitions") tests = ET.Element("tests") objects = ET.Element("objects") states = ET.Element("states") variables = ET.Element("variables") sys.exit(0)
def main(): if len(sys.argv) < 3: print "Provide an XCCDF file and an ID name scheme." print ("This script finds check-content files (currently, OVAL " + "and OCIL) referenced from XCCDF and synchronizes all IDs.") sys.exit(1) xccdffile = sys.argv[1] idname = sys.argv[2] os.chdir("./output") # step over xccdf file, and find referenced check files xccdftree = parse_xml_file(xccdffile) # Check that OVAL IDs and XCCDF Rule IDs match if 'unlinked-ocilref' not in xccdffile: allrules = xccdftree.findall(".//{%s}Rule" % xccdf_ns) for rule in allrules: xccdf_rule = rule.get("id") if xccdf_rule is not None: checks = rule.find("./{%s}check" % xccdf_ns) if checks is not None: for check in checks: oval_id = check.get("name") if not xccdf_rule == oval_id and oval_id is not None \ and not xccdf_rule == 'sample_rule': print("The OVAL ID does not match the XCCDF Rule ID!\n" "\n OVAL ID: \'%s\'" "\n XCCDF Rule ID: \'%s\'" "\n\nBoth OVAL and XCCDF Rule IDs must match!") % (oval_id, xccdf_rule) sys.exit(1) checks = xccdftree.findall(".//{%s}check" % xccdf_ns) ovalfiles = get_checkfiles(checks, oval_cs) ocilfiles = get_checkfiles(checks, ocil_cs) if len(ovalfiles) > 1 or len(ocilfiles) > 1: sys.exit("referencing more than one file per check system " + "is not yet supported by this script.") ovalfile = ovalfiles.pop() if ovalfiles else None ocilfile = ocilfiles.pop() if ocilfiles else None translator = idtranslate.idtranslator(idname+".ini", idname) # rename all IDs in the oval file if ovalfile: ovaltree = parse_xml_file(ovalfile) ovaltree = translator.translate(ovaltree, store_defname=True) newovalfile = ovalfile.replace("unlinked", idname) ET.ElementTree(ovaltree).write(newovalfile) # rename all IDs in the ocil file if ocilfile: ociltree = parse_xml_file(ocilfile) ociltree = translator.translate(ociltree) newocilfile = ocilfile.replace("unlinked", idname) ET.ElementTree(ociltree).write(newocilfile) # rename all IDs and file refs in the xccdf file for check in checks: checkcontentref = check.find("./{%s}check-content-ref" % xccdf_ns) # Don't attempt to relabel ID on empty <check-content-ref> element if checkcontentref is None: continue # Obtain the value of the 'href' attribute of particular # <check-content-ref> element checkcontentref_hrefattr = checkcontentref.get("href") # Don't attempt to relabel ID on <check-content-ref> element having # its "href" attribute set either to "http://" or to "https://" values if checkcontentref_hrefattr.startswith("http://") or \ checkcontentref_hrefattr.startswith("https://"): continue if check.get("system") == oval_cs: checkid = translator.assign_id("{" + oval_ns + "}definition", checkcontentref.get("name")) checkcontentref.set("name", checkid) checkcontentref.set("href", newovalfile) checkexport = check.find("./{%s}check-export" % xccdf_ns) if checkexport is not None: newexportname = translator.assign_id("{" + oval_ns + "}variable", checkexport.get("export-name")) checkexport.set("export-name", newexportname) if check.get("system") == ocil_cs: checkid = translator.assign_id("{" + ocil_ns + "}questionnaire", checkcontentref.get("name")) checkcontentref.set("name", checkid) checkcontentref.set("href", newocilfile) checkexport = check.find("./{%s}check-export" % xccdf_ns) if checkexport is not None: newexportname = translator.assign_id("{" + oval_ns + "}variable", checkexport.get("export-name")) checkexport.set("export-name", newexportname) newxccdffile = xccdffile.replace("unlinked", idname) # ET.dump(xccdftree) ET.ElementTree(xccdftree).write(newxccdffile) sys.exit(0)
def main(): if len(sys.argv) < 3: print "Provide an XCCDF file and an ID name scheme." print "This script finds check-content files (currently, OVAL and OCIL) referenced from XCCDF and synchronizes all IDs." sys.exit(1) xccdffile = sys.argv[1] idname = sys.argv[2] os.chdir("./output") # step over xccdf file, and find referenced check files xccdftree = parse_xml_file(xccdffile) checks = xccdftree.findall(".//{%s}check" % xccdf_ns) ovalfiles = get_checkfiles(checks, oval_cs) ocilfiles = get_checkfiles(checks, ocil_cs) if len(ovalfiles) > 1 or len(ocilfiles) > 1: sys.exit("referencing more than one file per check system is not yet supported by this script.") ovalfile = ovalfiles.pop() if ovalfiles else None ocilfile = ocilfiles.pop() if ocilfiles else None translator = idtranslate.idtranslator(idname+".ini", idname) # rename all IDs in the oval file if ovalfile: ovaltree = parse_xml_file(ovalfile) ovaltree = translator.translate(ovaltree, store_defname=True) newovalfile = ovalfile.replace("unlinked", idname) ET.ElementTree(ovaltree).write(newovalfile) # rename all IDs in the ocil file if ocilfile: ociltree = parse_xml_file(ocilfile) ociltree = translator.translate(ociltree) newocilfile = ocilfile.replace("unlinked", idname) ET.ElementTree(ociltree).write(newocilfile) # rename all IDs and file refs in the xccdf file for check in checks: checkcontentref = check.find("./{%s}check-content-ref" % xccdf_ns) if checkcontentref is None: continue if check.get("system") == oval_cs: checkid = translator.assign_id("{" + oval_ns + "}definition", checkcontentref.get("name")) checkcontentref.set("name", checkid) checkcontentref.set("href", newovalfile) checkexport = check.find("./{%s}check-export" % xccdf_ns) if checkexport is not None: newexportname = translator.assign_id("{"+ oval_ns + "}variable", checkexport.get("export-name")) checkexport.set("export-name", newexportname) if check.get("system") == ocil_cs: checkid = translator.assign_id("{" + ocil_ns + "}questionnaire", checkcontentref.get("name")) checkcontentref.set("name", checkid) checkcontentref.set("href", newocilfile) checkexport = check.find("./{%s}check-export" % xccdf_ns) if checkexport is not None: newexportname = translator.assign_id("{"+ oval_ns + "}variable", checkexport.get("export-name")) checkexport.set("export-name", newexportname) newxccdffile = xccdffile.replace("unlinked", idname) #ET.dump(xccdftree) ET.ElementTree(xccdftree).write(newxccdffile) sys.exit(0)
def main(): if len(sys.argv) < 2: print "Provide an OVAL file that contains inventory definitions." print("This script extracts these definitions and writes them" + " to STDOUT.") sys.exit(1) ovalfile = sys.argv[1] cpedictfile = sys.argv[2] idname = sys.argv[3] # parse oval file ovaltree = parse_xml_file(ovalfile) # extract inventory definitions # making (dubious) assumption that all inventory defs are CPE defs = ovaltree.find("./{%s}definitions" % oval_ns) inventory_defs = defs.findall(".//{%s}definition[@class='inventory']" % oval_ns) defs.clear() [defs.append(inventory_def) for inventory_def in inventory_defs] tests = ovaltree.find("./{%s}tests" % oval_ns) cpe_tests = extract_referred_nodes(defs, tests, "test_ref") tests.clear() [tests.append(cpe_test) for cpe_test in cpe_tests] states = ovaltree.find("./{%s}states" % oval_ns) cpe_states = extract_referred_nodes(tests, states, "state_ref") states.clear() [states.append(cpe_state) for cpe_state in cpe_states] objects = ovaltree.find("./{%s}objects" % oval_ns) cpe_objects = extract_referred_nodes(tests, objects, "object_ref") objects.clear() [objects.append(cpe_object) for cpe_object in cpe_objects] variables = ovaltree.find("./{%s}variables" % oval_ns) if variables: cpe_variables = extract_referred_nodes(tests, variables, "var_ref") if cpe_variables: variables.clear() [variables.append(cpe_variable) for cpe_variable in cpe_variables] else: ovaltree.remove(variables) # turn IDs into meaningless numbers translator = idtranslate.idtranslator("./output/" + idname + ".ini", idname) ovaltree = translator.translate(ovaltree) newovalfile = ovalfile.replace("oval", "cpe-oval") newovalfile = newovalfile.replace("unlinked", idname) ET.ElementTree(ovaltree).write(newovalfile) # replace and sync IDs, href filenames in input cpe dictionary file cpedicttree = parse_xml_file(cpedictfile) newcpedictfile = idname + "-" + os.path.basename(cpedictfile) for check in cpedicttree.findall(".//{%s}check" % cpe_ns): check.set("href", os.path.basename(newovalfile)) check.text = translator.assign_id("{" + oval_ns + "}definition", check.text) ET.ElementTree(cpedicttree).write("./output/" + newcpedictfile) sys.exit(0)
def main(): if len(sys.argv) < 3: print "Provide an XCCDF file and an ID name scheme." print ( "This script finds check-content files (currently, OVAL " + "and OCIL) referenced from XCCDF and synchronizes all IDs." ) sys.exit(1) xccdffile = sys.argv[1] idname = sys.argv[2] os.chdir("./output") # Step over xccdf file, and find referenced check files xccdftree = parse_xml_file(xccdffile) # Create XCCDF rule ID to assigned CCE ID mapping xccdf_to_cce_id_mapping = create_xccdf_id_to_cce_id_mapping(xccdftree) # Check that OVAL IDs and XCCDF Rule IDs match if "unlinked-ocilref" not in xccdffile: allrules = xccdftree.findall(".//{%s}Rule" % xccdf_ns) for rule in allrules: xccdf_rule = rule.get("id") if xccdf_rule is not None: checks = rule.find("./{%s}check" % xccdf_ns) if checks is not None: for check in checks: check_name = check.get("name") # Verify match of XCCDF vs OVAL / OCIL IDs for # * the case of OVAL <check> # * the case of OCIL <check> if ( not xccdf_rule == check_name and check_name is not None and not xccdf_rule + "_ocil" == check_name and not xccdf_rule == "sample_rule" ): print ("The OVAL / OCIL ID does not match the XCCDF Rule ID!\n") if "_ocil" in check_name: print ("\n OCIL ID: '%s'" % check_name) else: print ("\n OVAL ID: '%s'" % check_name) print ( "\n XCCDF Rule ID: '%s'" "\n\nBoth OVAL and XCCDF Rule IDs must match!" % xccdf_rule ) sys.exit(1) checks = xccdftree.findall(".//{%s}check" % xccdf_ns) ovalfiles = get_checkfiles(checks, oval_cs) ocilfiles = get_checkfiles(checks, ocil_cs) if len(ovalfiles) > 1 or len(ocilfiles) > 1: sys.exit("referencing more than one file per check system " + "is not yet supported by this script.") ovalfile = ovalfiles.pop() if ovalfiles else None ocilfile = ocilfiles.pop() if ocilfiles else None translator = idtranslate.idtranslator(idname) # Rename all IDs in the oval file if ovalfile: ovaltree = parse_xml_file(ovalfile) # Add new <reference source="CCE" ref_id="CCE-ID" /> element to those OVAL # checks having CCE ID already assigned in XCCDF for particular rule. # But add the <reference> only in the case CCE is in valid form! # Exit with failure if the assignment wasn't successful # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1092 # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1230 # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1229 # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1228 add_cce_id_refs_to_oval_checks(ovaltree, xccdf_to_cce_id_mapping) # Verify all by XCCDF referenced (local) OVAL checks are defined in OVAL file # If not drop the <check-content> OVAL checksystem reference from XCCDF # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1092 # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1095 # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1098 ensure_by_xccdf_referenced_oval_def_is_defined_in_oval_file(xccdftree, ovaltree) # Verify the XCCDF to OVAL datatype export matching constraints # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1089 check_and_correct_xccdf_to_oval_data_export_matching_constraints(xccdftree, ovaltree) # Verify if CCE identifiers present in the XCCDF follow the required form # (either CCE-XXXX-X, or CCE-XXXXX-X). Drop from XCCDF those who don't follow it verify_correct_form_of_referenced_cce_identifiers(xccdftree) ovaltree = translator.translate(ovaltree, store_defname=True) newovalfile = ovalfile.replace("unlinked", idname) ET.ElementTree(ovaltree).write(newovalfile) # Rename all IDs in the ocil file if ocilfile: ociltree = parse_xml_file(ocilfile) ociltree = translator.translate(ociltree) newocilfile = ocilfile.replace("unlinked", idname) ET.ElementTree(ociltree).write(newocilfile) # Rename all IDs and file refs in the xccdf file for check in checks: checkcontentref = check.find("./{%s}check-content-ref" % xccdf_ns) # Don't attempt to relabel ID on empty <check-content-ref> element if checkcontentref is None: continue # Obtain the value of the 'href' attribute of particular # <check-content-ref> element checkcontentref_hrefattr = checkcontentref.get("href") # Don't attempt to relabel ID on <check-content-ref> element having # its "href" attribute set either to "http://" or to "https://" values if checkcontentref_hrefattr.startswith("http://") or checkcontentref_hrefattr.startswith("https://"): continue if check.get("system") == oval_cs: checkid = translator.generate_id("{" + oval_ns + "}definition", checkcontentref.get("name")) checkcontentref.set("name", checkid) checkcontentref.set("href", newovalfile) checkexport = check.find("./{%s}check-export" % xccdf_ns) if checkexport is not None: newexportname = translator.generate_id("{" + oval_ns + "}variable", checkexport.get("export-name")) checkexport.set("export-name", newexportname) if check.get("system") == ocil_cs: checkid = translator.generate_id("{" + ocil_ns + "}questionnaire", checkcontentref.get("name")) checkcontentref.set("name", checkid) checkcontentref.set("href", newocilfile) checkexport = check.find("./{%s}check-export" % xccdf_ns) if checkexport is not None: newexportname = translator.generate_id("{" + oval_ns + "}variable", checkexport.get("export-name")) checkexport.set("export-name", newexportname) newxccdffile = xccdffile.replace("unlinked", idname) # ET.dump(xccdftree) ET.ElementTree(xccdftree).write(newxccdffile) sys.exit(0)
def main(): if len(sys.argv) < 2: print "Provide an OVAL file that contains inventory definitions." print ("This script extracts these definitions and writes them" + " to STDOUT.") sys.exit(1) ovalfile = sys.argv[1] cpedictfile = sys.argv[2] idname = sys.argv[3] # parse oval file ovaltree = parse_xml_file(ovalfile) # extract inventory definitions # making (dubious) assumption that all inventory defs are CPE defs = ovaltree.find("./{%s}definitions" % oval_ns) inventory_defs = defs.findall(".//{%s}definition[@class='inventory']" % oval_ns) # Keep the list of 'id' attributes from untranslated inventory def elements inventory_defs_id_attrs = [] defs.clear() [defs.append(inventory_def) for inventory_def in inventory_defs] # Fill in that list [inventory_defs_id_attrs.append(inventory_def.get("id")) for \ inventory_def in inventory_defs] tests = ovaltree.find("./{%s}tests" % oval_ns) cpe_tests = extract_referred_nodes(defs, tests, "test_ref") tests.clear() [tests.append(cpe_test) for cpe_test in cpe_tests] states = ovaltree.find("./{%s}states" % oval_ns) cpe_states = extract_referred_nodes(tests, states, "state_ref") states.clear() [states.append(cpe_state) for cpe_state in cpe_states] objects = ovaltree.find("./{%s}objects" % oval_ns) cpe_objects = extract_referred_nodes(tests, objects, "object_ref") env_objects = extract_referred_nodes(objects, objects, "id") objects.clear() [objects.append(cpe_object) for cpe_object in cpe_objects] # if any subelements in an object contain var_ref, return it here local_var_ref = extract_subelement(objects, 'var_ref') variables = ovaltree.find("./{%s}variables" % oval_ns) if variables is not None: cpe_variables = extract_referred_nodes(tests, variables, "var_ref") local_variables = extract_referred_nodes(variables, variables, "id") if cpe_variables: variables.clear() [variables.append(cpe_variable) for cpe_variable in cpe_variables] elif local_var_ref: for local_var in local_variables: if local_var.get('id') == local_var_ref: variables.clear() variables.append(local_var) env_obj = extract_env_obj(env_objects, local_var) objects.append(env_obj) else: ovaltree.remove(variables) # turn IDs into meaningless numbers translator = idtranslate.idtranslator(idname) ovaltree = translator.translate(ovaltree) newovalfile = ovalfile.replace("oval", "cpe-oval") newovalfile = newovalfile.replace("unlinked", idname) ET.ElementTree(ovaltree).write(newovalfile) # replace and sync IDs, href filenames in input cpe dictionary file cpedicttree = parse_xml_file(cpedictfile) newcpedictfile = idname + "-" + os.path.basename(cpedictfile) for check in cpedicttree.findall(".//{%s}check" % cpe_ns): checkhref = check.get("href") # If CPE OVAL references another OVAL file if checkhref == 'filename': # Sanity check -- Verify the referenced OVAL is truly defined # somewhere in the (sub)directory tree below CWD. In correct # scenario is should be located: # * either in input/oval/*.xml # * or copied by former run of "combineovals.py" script from # shared/ directory into build/ subdirectory refovalfilename = check.text refovalfilefound = False for dirpath, dirnames, filenames in os.walk(os.curdir, topdown=True): # Case when referenced OVAL file exists for location in fnmatch.filter(filenames, refovalfilename + '.xml'): refovalfilefound = True break # break from the inner for loop if refovalfilefound: break # break from the outer for loop shared_dir = os.getenv("SHARED") if shared_dir is not None: for dirpath, dirnames, filenames in os.walk(shared_dir, topdown=True): # Case when referenced OVAL file exists for location in fnmatch.filter(filenames, refovalfilename + '.xml'): refovalfilefound = True break # break from the inner for loop if refovalfilefound: break # break from the outer for loop # Referenced OVAL doesn't exist in the subdirtree below CWD: # * there's either typo in the refenced OVAL filename, or # * is has been forgotten to be placed into input/oval, or # * the <platform> tag of particular shared/ OVAL wasn't modified # to include the necessary referenced file. # Therefore display an error and exit with failure in such cases if not refovalfilefound: error_msg = "\n\tError: Can't locate \"%s\" OVAL file in the \ \n\tlist of OVAL checks for this product! Exiting..\n" % refovalfilename sys.stderr.write(error_msg) # sys.exit(1) check.set("href", os.path.basename(newovalfile)) # Sanity check to verify if inventory check OVAL id is present in the # list of known "id" attributes of inventory definitions. If not it # means provided ovalfile (sys.argv[1]) doesn't contain this OVAL # definition (it wasn't included due to <platform> tag restrictions) # Therefore display an error and exit with failure, since otherwise # we might end up creating invalid $(ID)-$(PROD)-cpe-oval.xml file if check.text not in inventory_defs_id_attrs: error_msg = "\n\tError: Can't locate \"%s\" definition in \"%s\". \ \n\tEnsure <platform> element is configured properly for \"%s\". \ \n\tExiting..\n" % (check.text, ovalfile, check.text) sys.stderr.write(error_msg) # sys.exit(1) # Referenced OVAL checks passed both of the above sanity tests check.text = translator.generate_id("{" + oval_ns + "}definition", check.text) ET.ElementTree(cpedicttree).write("./output/"+newcpedictfile) sys.exit(0)
def main(): if len(sys.argv) < 2: print "Provide an OVAL file that contains inventory definitions." print ("This script extracts these definitions and writes them" + " to STDOUT.") sys.exit(1) ovalfile = sys.argv[1] cpedictfile = sys.argv[2] idname = sys.argv[3] # parse oval file ovaltree = parse_xml_file(ovalfile) # extract inventory definitions # making (dubious) assumption that all inventory defs are CPE defs = ovaltree.find("./{%s}definitions" % oval_ns) inventory_defs = defs.findall(".//{%s}definition[@class='inventory']" % oval_ns) # Keep the list of 'id' attributes from untranslated inventory def elements inventory_defs_id_attrs = [] defs.clear() [defs.append(inventory_def) for inventory_def in inventory_defs] # Fill in that list [inventory_defs_id_attrs.append(inventory_def.get("id")) for \ inventory_def in inventory_defs] tests = ovaltree.find("./{%s}tests" % oval_ns) cpe_tests = extract_referred_nodes(defs, tests, "test_ref") tests.clear() [tests.append(cpe_test) for cpe_test in cpe_tests] states = ovaltree.find("./{%s}states" % oval_ns) cpe_states = extract_referred_nodes(tests, states, "state_ref") states.clear() [states.append(cpe_state) for cpe_state in cpe_states] objects = ovaltree.find("./{%s}objects" % oval_ns) cpe_objects = extract_referred_nodes(tests, objects, "object_ref") env_objects = extract_referred_nodes(objects, objects, "id") objects.clear() [objects.append(cpe_object) for cpe_object in cpe_objects] # if any subelements in an object contain var_ref, return it here local_var_ref = extract_subelement(objects, 'var_ref') variables = ovaltree.find("./{%s}variables" % oval_ns) if variables is not None: cpe_variables = extract_referred_nodes(tests, variables, "var_ref") local_variables = extract_referred_nodes(variables, variables, "id") if cpe_variables: variables.clear() [variables.append(cpe_variable) for cpe_variable in cpe_variables] elif local_var_ref: for local_var in local_variables: if local_var.get('id') == local_var_ref: variables.clear() variables.append(local_var) env_obj = extract_env_obj(env_objects, local_var) objects.append(env_obj) else: ovaltree.remove(variables) # turn IDs into meaningless numbers translator = idtranslate.idtranslator(idname) ovaltree = translator.translate(ovaltree) newovalfile = ovalfile.replace("oval", "cpe-oval") newovalfile = newovalfile.replace("unlinked", idname) ET.ElementTree(ovaltree).write(newovalfile) # replace and sync IDs, href filenames in input cpe dictionary file cpedicttree = parse_xml_file(cpedictfile) newcpedictfile = idname + "-" + os.path.basename(cpedictfile) for check in cpedicttree.findall(".//{%s}check" % cpe_ns): checkhref = check.get("href") # If CPE OVAL references another OVAL file if checkhref == 'filename': # Sanity check -- Verify the referenced OVAL is truly defined # somewhere in the (sub)directory tree below CWD. In correct # scenario is should be located: # * either in input/oval/*.xml # * or copied by former run of "combineovals.py" script from # shared/ directory into build/ subdirectory refovalfilename = check.text refovalfilefound = False for dirpath, dirnames, filenames in os.walk(os.curdir, topdown=True): # Case when referenced OVAL file exists for location in fnmatch.filter(filenames, refovalfilename + '.xml'): refovalfilefound = True break # break from the inner for loop if refovalfilefound: break # break from the outer for loop # Referenced OVAL doesn't exist in the subdirtree below CWD: # * there's either typo in the refenced OVAL filename, or # * is has been forgotten to be placed into input/oval, or # * the <platform> tag of particular shared/ OVAL wasn't modified # to include the necessary referenced file. # Therefore display an error and exit with failure in such cases if not refovalfilefound: error_msg = "\n\tError: Can't locate \"%s\" OVAL file in the \ \n\tlist of OVAL checks for this product! Exiting..\n" % refovalfilename sys.stderr.write(error_msg) # sys.exit(1) check.set("href", os.path.basename(newovalfile)) # Sanity check to verify if inventory check OVAL id is present in the # list of known "id" attributes of inventory definitions. If not it # means provided ovalfile (sys.argv[1]) doesn't contain this OVAL # definition (it wasn't included due to <platform> tag restrictions) # Therefore display an error and exit with failure, since otherwise # we might end up creating invalid $(ID)-$(PROD)-cpe-oval.xml file if check.text not in inventory_defs_id_attrs: error_msg = "\n\tError: Can't locate \"%s\" definition in \"%s\". \ \n\tEnsure <platform> element is configured properly for \"%s\". \ \n\tExiting..\n" % (check.text, ovalfile, check.text) sys.stderr.write(error_msg) # sys.exit(1) # Referenced OVAL checks passed both of the above sanity tests check.text = translator.generate_id("{" + oval_ns + "}definition", check.text) ET.ElementTree(cpedicttree).write("./output/"+newcpedictfile) sys.exit(0)
def main(): if len(sys.argv) < 3: print "Provide an XCCDF file and an ID name scheme." print ("This script finds check-content files (currently, OVAL " + "and OCIL) referenced from XCCDF and synchronizes all IDs.") sys.exit(1) xccdffile = sys.argv[1] idname = sys.argv[2] os.chdir("./output") # Step over xccdf file, and find referenced check files xccdftree = parse_xml_file(xccdffile) # Create XCCDF rule ID to assigned CCE ID mapping xccdf_to_cce_id_mapping = create_xccdf_id_to_cce_id_mapping(xccdftree) # Check that OVAL IDs and XCCDF Rule IDs match if 'unlinked-ocilref' not in xccdffile: allrules = xccdftree.findall(".//{%s}Rule" % xccdf_ns) for rule in allrules: xccdf_rule = rule.get("id") if xccdf_rule is not None: checks = rule.find("./{%s}check" % xccdf_ns) if checks is not None: for check in checks: check_name = check.get("name") # Verify match of XCCDF vs OVAL / OCIL IDs for # * the case of OVAL <check> # * the case of OCIL <check> if (not xccdf_rule == check_name and check_name is not None \ and not xccdf_rule + '_ocil' == check_name \ and not xccdf_rule == 'sample_rule'): print("The OVAL / OCIL ID does not match the XCCDF Rule ID!\n") if '_ocil' in check_name: print("\n OCIL ID: \'%s\'" % check_name) else: print("\n OVAL ID: \'%s\'" % check_name) print("\n XCCDF Rule ID: \'%s\'" "\n\nBoth OVAL and XCCDF Rule IDs must match!" % xccdf_rule) sys.exit(1) checks = xccdftree.findall(".//{%s}check" % xccdf_ns) ovalfiles = get_checkfiles(checks, oval_cs) ocilfiles = get_checkfiles(checks, ocil_cs) if len(ovalfiles) > 1 or len(ocilfiles) > 1: sys.exit("referencing more than one file per check system " + "is not yet supported by this script.") ovalfile = ovalfiles.pop() if ovalfiles else None ocilfile = ocilfiles.pop() if ocilfiles else None translator = idtranslate.idtranslator(idname) # Rename all IDs in the oval file if ovalfile: ovaltree = parse_xml_file(ovalfile) # Add new <reference source="CCE" ref_id="CCE-ID" /> element to those OVAL # checks having CCE ID already assigned in XCCDF for particular rule. # But add the <reference> only in the case CCE is in valid form! # Exit with failure if the assignment wasn't successful # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1092 # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1230 # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1229 # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1228 add_cce_id_refs_to_oval_checks(ovaltree, xccdf_to_cce_id_mapping) # Verify all by XCCDF referenced (local) OVAL checks are defined in OVAL file # If not drop the <check-content> OVAL checksystem reference from XCCDF # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1092 # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1095 # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1098 ensure_by_xccdf_referenced_oval_def_is_defined_in_oval_file(xccdftree, ovaltree) # Verify the XCCDF to OVAL datatype export matching constraints # Fixes: https://github.com/OpenSCAP/scap-security-guide/issues/1089 check_and_correct_xccdf_to_oval_data_export_matching_constraints(xccdftree, ovaltree) # Verify if CCE identifiers present in the XCCDF follow the required form # (either CCE-XXXX-X, or CCE-XXXXX-X). Drop from XCCDF those who don't follow it verify_correct_form_of_referenced_cce_identifiers(xccdftree) ovaltree = translator.translate(ovaltree, store_defname=True) newovalfile = ovalfile.replace("unlinked", idname) ET.ElementTree(ovaltree).write(newovalfile) # Rename all IDs in the ocil file if ocilfile: ociltree = parse_xml_file(ocilfile) ociltree = translator.translate(ociltree) newocilfile = ocilfile.replace("unlinked", idname) ET.ElementTree(ociltree).write(newocilfile) # Rename all IDs and file refs in the xccdf file for check in checks: checkcontentref = check.find("./{%s}check-content-ref" % xccdf_ns) # Don't attempt to relabel ID on empty <check-content-ref> element if checkcontentref is None: continue # Obtain the value of the 'href' attribute of particular # <check-content-ref> element checkcontentref_hrefattr = checkcontentref.get("href") # Don't attempt to relabel ID on <check-content-ref> element having # its "href" attribute set either to "http://" or to "https://" values if checkcontentref_hrefattr.startswith("http://") or \ checkcontentref_hrefattr.startswith("https://"): continue if check.get("system") == oval_cs: checkid = translator.generate_id("{" + oval_ns + "}definition", checkcontentref.get("name")) checkcontentref.set("name", checkid) checkcontentref.set("href", newovalfile) checkexport = check.find("./{%s}check-export" % xccdf_ns) if checkexport is not None: newexportname = translator.generate_id("{" + oval_ns + "}variable", checkexport.get("export-name")) checkexport.set("export-name", newexportname) if check.get("system") == ocil_cs: checkid = translator.generate_id("{" + ocil_ns + "}questionnaire", checkcontentref.get("name")) checkcontentref.set("name", checkid) checkcontentref.set("href", newocilfile) checkexport = check.find("./{%s}check-export" % xccdf_ns) if checkexport is not None: newexportname = translator.generate_id("{" + oval_ns + "}variable", checkexport.get("export-name")) checkexport.set("export-name", newexportname) newxccdffile = xccdffile.replace("unlinked", idname) # ET.dump(xccdftree) ET.ElementTree(xccdftree).write(newxccdffile) sys.exit(0)
def main(): if len(sys.argv) < 3: print "Provide an XCCDF file and an ID name scheme." print("This script finds check-content files (currently, OVAL " + "and OCIL) referenced from XCCDF and synchronizes all IDs.") sys.exit(1) xccdffile = sys.argv[1] idname = sys.argv[2] os.chdir("./output") # step over xccdf file, and find referenced check files xccdftree = parse_xml_file(xccdffile) checks = xccdftree.findall(".//{%s}check" % xccdf_ns) ovalfiles = get_checkfiles(checks, oval_cs) ocilfiles = get_checkfiles(checks, ocil_cs) if len(ovalfiles) > 1 or len(ocilfiles) > 1: sys.exit("referencing more than one file per check system " + "is not yet supported by this script.") ovalfile = ovalfiles.pop() if ovalfiles else None ocilfile = ocilfiles.pop() if ocilfiles else None translator = idtranslate.idtranslator(idname + ".ini", idname) # rename all IDs in the oval file if ovalfile: ovaltree = parse_xml_file(ovalfile) ovaltree = translator.translate(ovaltree, store_defname=True) newovalfile = ovalfile.replace("unlinked", idname) ET.ElementTree(ovaltree).write(newovalfile) # rename all IDs in the ocil file if ocilfile: ociltree = parse_xml_file(ocilfile) ociltree = translator.translate(ociltree) newocilfile = ocilfile.replace("unlinked", idname) ET.ElementTree(ociltree).write(newocilfile) # rename all IDs and file refs in the xccdf file for check in checks: checkcontentref = check.find("./{%s}check-content-ref" % xccdf_ns) if checkcontentref is None: continue if check.get("system") == oval_cs: checkid = translator.assign_id("{" + oval_ns + "}definition", checkcontentref.get("name")) checkcontentref.set("name", checkid) checkcontentref.set("href", newovalfile) checkexport = check.find("./{%s}check-export" % xccdf_ns) if checkexport is not None: newexportname = translator.assign_id( "{" + oval_ns + "}variable", checkexport.get("export-name")) checkexport.set("export-name", newexportname) if check.get("system") == ocil_cs: checkid = translator.assign_id("{" + ocil_ns + "}questionnaire", checkcontentref.get("name")) checkcontentref.set("name", checkid) checkcontentref.set("href", newocilfile) checkexport = check.find("./{%s}check-export" % xccdf_ns) if checkexport is not None: newexportname = translator.assign_id( "{" + oval_ns + "}variable", checkexport.get("export-name")) checkexport.set("export-name", newexportname) newxccdffile = xccdffile.replace("unlinked", idname) # ET.dump(xccdftree) ET.ElementTree(xccdftree).write(newxccdffile) sys.exit(0)