def update_html(self, result_name, solution_files, extension="html"): """ Function updates a XML or HTML file with relevant solution texts """ orig_file = os.path.join(self.dirname, result_name + "." + extension) lines = get_file_content(orig_file, "rb", method=True) for dir_name, files in six.iteritems(solution_files): section = dir_name.replace(os.path.join(self.dirname, self.scenario), "").replace("/", "_") solution_text = section + "_SOLUTION_MSG" file_name = self._return_correct_text_file(section, files) if not file_name or file_name is None: continue else: text = get_file_content(os.path.join(dir_name, file_name), "rb", method=True) for cnt, line in enumerate(lines): # If in INPLACERISK: is a [link] then update them # to /root/pre{migrate,upgrade}/... if "INPLACERISK:" in line.strip(): lines[cnt] = tag_formating([line], extension)[0] continue # Find correct block if solution_text not in line.strip(): continue # Get updated text if it is HTML or TEXT lines[cnt] = self.get_updated_text(solution_text, text, line, extension) if extension == "xml": for cnt, line in enumerate(lines): if "SOLUTION_MSG" in line.strip(): lines[cnt] = re.sub(r">.*SOLUTION_MSG.*<", "><", line.strip()) write_to_file(orig_file, "wb", lines)
def write_xml(self): """Function writes XML document to file""" self.target_tree.set('xmlns:xhtml', 'http://www.w3.org/1999/xhtml/') # we really must set encoding here! and suppress it in write_to_file data = ElementTree.tostring(self.target_tree, "utf-8") write_to_file(self.path, 'wb', data, False) self.target_tree = ElementTree.parse(self.path).getroot()
def setUp(self): self.dir_name = "tests/FOOBAR6_7/incorrect_ini" os.makedirs(self.dir_name) self.filename = os.path.join(self.dir_name, 'test.ini') self.rule = [] self.test_solution = "test_solution.sh" self.check_script = "check_script.sh" self.loaded_ini = {} self.loaded_ini[self.filename] = [] self.test_ini = {'content_title': 'Testing content title', 'content_description': 'Some content description', 'author': 'test <*****@*****.**>', 'config_file': '/etc/named.conf', 'check_script': self.check_script, 'solution': self.test_solution, 'applies_to': 'test'} solution_text = """ A solution text for test suite" """ check_sh = """#!/bin/bash #END GENERATED SECTION #This is testing check script """ write_to_file(os.path.join(self.dir_name, self.test_solution), "wb", solution_text) write_to_file(os.path.join(self.dir_name, self.check_script), "wb", check_sh)
def clean_html(report_path): """ Function cleans a report """ file_content = get_file_content(report_path, 'rb') s_testres = ( '[\t ]*<div id="intro">[\t ]*\n[\t ]*<h2>Introduction</h2>[\t ]*\n', False) e_testres = ( '[\t ]*</table>[\t ]*\n[\t ]*</div>[\t ]*\n[\t ]*</div>[\t ]*\n', False) s_score = ('[\t ]*<div>[\t ]*\n[\t ]*<h3>Score</h3>\s*', True) e_score = ('[\t ]*</div>[\t ]*\n[\t ]*<div id="results-overview">[\t ]*\n', False) # remove test results nl = remove_lines(file_content, s_testres, e_testres) # remove score table #nl = remove_lines(nl, s_score, e_score) # sed XCCDF test results nl = re.sub('XCCDF test result', 'Preupgrade Assistant', nl) # add preupg nvr nl = re.sub('[\t ]*<h2>Introduction</h2>[\t ]*\n', add_preupg_scanner_info(), nl) write_to_file(report_path, 'wb', nl)
def update_check_script(dir_name, updates, script_name=None, author=""): """ The function updates check script with license file and with API functions like check_rpm_to and check_applies_to """ script_type = get_script_type(dir_name, script_name) if author == "": author = "<empty_line>" generated_section, functions = generate_common_stuff(settings.license.format(author), updates, script_type) full_path_script = get_full_path(dir_name, script_name) lines = get_file_content(full_path_script, "rb", method=True) if not [x for x in lines if re.search(r'#END GENERATED SECTION', x)]: print_error_msg("#END GENERATED SECTION is missing in check_script {0}".format(full_path_script)) raise MissingHeaderCheckScriptError for func in functions: lines = [x for x in lines if func not in x.strip()] output_text = "" for line in lines: if '#END GENERATED SECTION' in line: new_line = '\n'.join(generated_section) new_line = new_line.replace('<empty_line>', '').replace('<new_line>', '') output_text += new_line+'\n' if 'check_applies' in updates: component = updates['check_applies'] else: component = "distribution" if script_type == "sh": output_text += 'COMPONENT="'+component+'"\n' else: output_text += 'set_component("'+component+'")\n' output_text += line write_to_file(full_path_script, "wb", output_text)
def test_secret_check_script(self): """Check occurrence of secret file for check script""" self.test_ini['check_script'] = '.minicheck' text = """#!/usr/bin/sh\necho 'ahojky'\n""" write_to_file(os.path.join(self.dir_name, self.check_script), "wb", text) self.loaded_ini[self.filename].append(self.test_ini) self.xml_utils = XmlUtils(self.dir_name, self.loaded_ini) self.assertRaises(SystemExit, lambda: list(self.xml_utils.prepare_sections()))
def _create_check_script(self): if self.check_script: utils.write_to_file( os.path.join(self.get_content_path(), self.get_check_script()), 'wb', settings.temp_check_script) os.chmod( os.path.join(self.get_content_path(), self.get_check_script()), 0755)
def _copy_xccdf_file(self, update_text): temp_dir = tempfile.mkdtemp() xccdf_file = os.path.join(os.getcwd(), 'tests', 'FOOBAR6_7', 'dummy_preupg', 'all-xccdf.xml') temp_file = os.path.join(temp_dir, 'all_xccdf.xml') shutil.copyfile(xccdf_file, temp_file) content = utils.get_file_content(temp_file, 'rb', decode_flag=False) content = content.replace(b'INPLACE_TAG', update_text) utils.write_to_file(temp_file, 'wb', content) return temp_file
def test_hashes(self): text_to_hash=""" This is preupgrade assistant test has string" """ self.dir_name = "tests/hashes" os.mkdir(self.dir_name) utils.write_to_file(os.path.join(self.dir_name, "post_script"), 'wb', text_to_hash) remediate.hash_postupgrade_file(False, self.dir_name) return_value = remediate.hash_postupgrade_file(False, self.dir_name, check=True) self.assertTrue(return_value)
def test_hashes(self): text_to_hash = """ This is preupgrade assistant test has string" """ self.dir_name = "tests/hashes" os.mkdir(self.dir_name) utils.write_to_file(os.path.join(self.dir_name, "post_script"), "wb", text_to_hash) remediate.hash_postupgrade_file(False, self.dir_name) return_value = remediate.hash_postupgrade_file(False, self.dir_name, check=True) self.assertTrue(return_value)
def test_incorrect_tag(self): """ Check occurrence of incorrect tag Tests issue #30 """ text_ini = '[preupgrade]\n' text_ini += '\n'.join([key + " = " + self.test_ini[key] for key in self.test_ini]) text_ini += '\n[]\neliskk\n' write_to_file(self.filename, "wb", text_ini) oscap = OscapGroupXml(self.dir_name) self.assertRaises(SystemExit, oscap.find_all_ini)
def write_profile_xml(self, target_tree): """The function stores all-xccdf.xml file into content directory""" file_name = os.path.join(self.dirname, "all-xccdf.xml") print ('File which can be used by Preupgrade-Assistant is:\n', ''.join(file_name)) try: # encoding must be set! otherwise ElementTree return non-ascii characters # as html entities instead, which are unsusable for us data = ElementTree.tostring(target_tree, "utf-8") write_to_file(file_name, "wb", data, False) except IOError as ioe: print ('Problem with writing to file ', file_name, ioe.message)
def write_xml(self): """The function is used for storing a group.xml file""" self.find_all_ini() self.write_list_rules() xml_utils = XmlUtils(self.dirname, self.loaded) self.rule = xml_utils.prepare_sections() file_name = os.path.join(self.dirname, "group.xml") try: write_to_file(file_name, "wb", ["%s" % item for item in self.rule]) except IOError as ior: print ('Problem with write data to the file ', file_name, ior.message)
def write_profile_xml(self, target_tree): """The function stores all-xccdf.xml file into content directory""" file_name = os.path.join(self.dirname, "all-xccdf.xml") print('File which can be used by Preupgrade-Assistant is:\n', ''.join(file_name)) try: # encoding must be set! otherwise ElementTree return non-ascii characters # as html entities instead, which are unsusable for us data = ElementTree.tostring(target_tree, "utf-8") write_to_file(file_name, "wb", data, False) except IOError as ioe: print('Problem with writing to file ', file_name, ioe.message)
def write_xml(self): """The function is used for storing a group.xml file""" self.find_all_ini() self.write_list_rules() xml_utils = XmlUtils(self.dirname, self.loaded) self.rule = xml_utils.prepare_sections() file_name = os.path.join(self.dirname, "group.xml") try: write_to_file(file_name, "wb", ["%s" % item for item in self.rule]) except IOError as ior: print('Problem with write data to the file ', file_name, ior.message)
def write_xccdf_version(file_name, direction=False): """ Function updates XCCDF version because of separate HTML generation and our own XSL stylesheet """ namespace_1 = 'http://checklists.nist.gov/xccdf/1.1' namespace_2 = 'http://checklists.nist.gov/xccdf/1.2' content = get_file_content(file_name, "rb") if direction: content = re.sub(namespace_2, namespace_1, content) else: content = re.sub(namespace_1, namespace_2, content) write_to_file(file_name, 'wb', content)
def write_list_rules(self): rule_name = '_'.join(self.dirname.split('/')[1:]) file_list_rules = os.path.join(settings.UPGRADE_PATH, settings.file_list_rules) lines = [] if os.path.exists(file_list_rules): lines = get_file_content(file_list_rules, "rb", method=True) else: lines = [] for values in six.itervalues(self.loaded): check_script = [v for k, v in six.iteritems(values[0]) if k == 'check_script'] if check_script: check_script = os.path.splitext(''.join(check_script))[0] lines.append(settings.xccdf_tag + rule_name + '_' + check_script + '\n') write_to_file(file_list_rules, "wb", lines)
def update_files(self, file_name, content): """Function updates file_name <migrate or update> according to INI file.""" """ :param file_name: specified in INI file like mode: upgrade, migrate :param content: name of the content like xccdf_rule_... :return: Nothing """ path_name = os.path.join(settings.UPGRADE_PATH, file_name) lines = [] if os.path.exists(path_name): lines = get_file_content(path_name, 'rb', method=True) test_content = [x.strip() for x in lines if content in x.strip()] if not test_content: lines.append(content + '\n') write_to_file(path_name, 'wb', lines)
def write_list_rules(self): rule_name = '_'.join(self.dirname.split('/')[1:]) file_list_rules = os.path.join(settings.UPGRADE_PATH, settings.file_list_rules) lines = [] if os.path.exists(file_list_rules): lines = get_file_content(file_list_rules, "rb", method=True) else: lines = [] for values in six.itervalues(self.loaded): check_script = [ v for k, v in six.iteritems(values[0]) if k == 'check_script' ] if check_script: check_script = os.path.splitext(''.join(check_script))[0] lines.append(settings.xccdf_tag + rule_name + '_' + check_script + '\n') write_to_file(file_list_rules, "wb", lines)
def remove_html_information(self): report_path = os.path.join(self.dirname, self.result_base + ".html") file_content = get_file_content(report_path, 'rb', method=True) detail_start = '<br /><br /><strong class="bold">Details:</strong><br />' detail_end = '[\t ]*<div class="xccdf-fixtext">' new_content = [] found_section = False for line in file_content: if detail_start in line: found_section = True continue if detail_end in line: found_section = False if not found_section: new_content.append(line) write_to_file(report_path, 'wb', new_content)
def remove_html_information(self): report_path = os.path.join(self.dirname, self.result_base + ".html") file_content = get_file_content(report_path, "rb", method=True) detail_start = '<br /><br /><strong class="bold">Details:</strong><br />' detail_end = '[\t ]*<div class="xccdf-fixtext">' new_content = [] found_section = False for line in file_content: if detail_start in line: found_section = True continue if detail_end in line: found_section = False if not found_section: new_content.append(line) write_to_file(report_path, "wb", new_content)
def hash_postupgrade_file(verbose, dirname, check=False): """ The function creates hash file over all scripts in postupgrade.d directory. In case of remediation it checks whether checksums are different and print what scripts were changed. """ if not os.path.exists(dirname): message = 'Directory %s does not exist for creating checksum file' log_message(message, settings.postupgrade_dir, level=logging.ERROR) return postupg_scripts = get_all_postupgrade_files(verbose, dirname) if not postupg_scripts: return filename = settings.base_hashed_file if check: filename = settings.base_hashed_file + "_new" lines = [] for post_name in postupg_scripts: lines.append(post_name + "=" + get_hash_file(post_name, sha1()) + "\n") full_path_name = os.path.join(dirname, filename) write_to_file(full_path_name, "wb", lines) if check: hashed_file = get_hashes( os.path.join(dirname, settings.base_hashed_file)) if hashed_file is None: message = 'Hashed_file is missing. Postupgrade scripts will not be executed' log_message(message, level=logging.WARNING) return False hashed_file_new = get_hashes(full_path_name) different_hashes = list( set(hashed_file).difference(set(hashed_file_new))) for file_name in [settings.base_hashed_file, filename]: os.remove(os.path.join(dirname, file_name)) if different_hashes or len(different_hashes) > 0: message = 'Checksums are different in these postupgrade scripts: %s' log_message(message % different_hashes, level=logging.WARNING) return False return True
def hash_postupgrade_file(verbose, dirname, check=False): """ The function creates hash file over all scripts in postupgrade.d directory. In case of remediation it checks whether checksums are different and print what scripts were changed. """ if not os.path.exists(dirname): message = 'Directory %s does not exist for creating checksum file' log_message(message, settings.postupgrade_dir, level=logging.ERROR) return postupg_scripts = get_all_postupgrade_files(verbose, dirname) if not postupg_scripts: return filename = settings.base_hashed_file if check: filename = settings.base_hashed_file + "_new" lines = [] for post_name in postupg_scripts: lines.append(post_name + "=" + get_hash_file(post_name, sha1())+"\n") full_path_name = os.path.join(dirname, filename) write_to_file(full_path_name, "wb", lines) if check: hashed_file = get_hashes(os.path.join(dirname, settings.base_hashed_file)) if hashed_file is None: message = 'Hashed_file is missing. Postupgrade scripts will not be executed' log_message(message, level=logging.WARNING) return False hashed_file_new = get_hashes(full_path_name) different_hashes = list(set(hashed_file).difference(set(hashed_file_new))) for file_name in [settings.base_hashed_file, filename]: os.remove(os.path.join(dirname, file_name)) if different_hashes or len(different_hashes) > 0: message = 'Checksums are different in these postupgrade scripts: %s' log_message(message % different_hashes, level=logging.WARNING) return False return True
def update_html(self, result_name, solution_files, extension="html"): """ Function updates a XML or HTML file with relevant solution texts """ orig_file = os.path.join(self.dirname, result_name + "." + extension) lines = get_file_content(orig_file, "rb", method=True) for dir_name, files in six.iteritems(solution_files): section = dir_name.replace( os.path.join(self.dirname, self.scenario), "").replace("/", "_") solution_text = section + "_SOLUTION_MSG" file_name = self._return_correct_text_file(section, files) if not file_name or file_name is None: continue else: text = get_file_content(os.path.join(dir_name, file_name), "rb", method=True) for cnt, line in enumerate(lines): # If in INPLACERISK: is a [link] then update them # to /root/pre{migrate,upgrade}/... if 'INPLACERISK:' in line.strip(): lines[cnt] = tag_formating([line], extension)[0] continue # Find correct block if solution_text not in line.strip(): continue # Get updated text if it is HTML or TEXT lines[cnt] = self.get_updated_text(solution_text, text, line, extension) if extension == 'xml': for cnt, line in enumerate(lines): if 'SOLUTION_MSG' in line.strip(): lines[cnt] = re.sub(r'>.*SOLUTION_MSG.*<', '><', line.strip()) write_to_file(orig_file, "wb", lines)
def setUp(self): self.dirname = os.path.join("tests", "FOOBAR6_7" + variables.result_prefix, "test") if os.path.exists(self.dirname): shutil.rmtree(self.dirname) os.makedirs(self.dirname) self.filename = os.path.join(self.dirname, 'test.ini') self.rule = [] self.test_solution = "test_solution.txt" self.check_script = "check_script.sh" self.loaded_ini = {} test_ini = {'content_title': 'Testing content title', 'content_description': ' some content description', 'author': 'test <*****@*****.**>', 'config_file': '/etc/named.conf', 'check_script': self.check_script, 'solution': self.test_solution, 'applies_to': 'test', 'requires': 'bash', 'binary_req': 'sed'} self.loaded_ini[self.filename] = [] self.loaded_ini[self.filename].append(test_ini) self.check_sh = """#!/bin/bash #END GENERATED SECTION #This is testing check script """ check_name = os.path.join(self.dirname, self.check_script) write_to_file(check_name, "wb", self.check_sh) os.chmod(check_name, stat.S_IEXEC | stat.S_IRWXG | stat.S_IRWXU) self.solution_text = """ A solution text for test suite" """ test_solution_name = os.path.join(self.dirname, self.test_solution) write_to_file(test_solution_name, "wb", self.solution_text) os.chmod(check_name, stat.S_IEXEC | stat.S_IRWXG | stat.S_IRWXU) self.xml_utils = XmlUtils(self.dirname, self.loaded_ini) self.rule = self.xml_utils.prepare_sections()
def clean_html(report_path): """ Function cleans a report """ file_content = get_file_content(report_path, "rb") s_testres = ('[\t ]*<div id="intro">[\t ]*\n[\t ]*<h2>Introduction</h2>[\t ]*\n', False) e_testres = ("[\t ]*</table>[\t ]*\n[\t ]*</div>[\t ]*\n[\t ]*</div>[\t ]*\n", False) s_score = ("[\t ]*<div>[\t ]*\n[\t ]*<h3>Score</h3>\s*", True) e_score = ('[\t ]*</div>[\t ]*\n[\t ]*<div id="results-overview">[\t ]*\n', False) # remove test results nl = remove_lines(file_content, s_testres, e_testres) # remove score table # nl = remove_lines(nl, s_score, e_score) # sed XCCDF test results nl = re.sub("XCCDF test result", "Preupgrade Assistant", nl) # add preupg nvr nl = re.sub("[\t ]*<h2>Introduction</h2>[\t ]*\n", add_preupg_scanner_info(), nl) write_to_file(report_path, "wb", nl)
def generate_xml(self, generate_from_ini=True): dir_util.copy_tree(self.result_dir, self.dir_name) result_dirname = self.dir_name template_file = ComposeXML.get_template_file() try: target_tree = ElementTree.parse(template_file).getroot() except IOError: print ('Problem with reading template.xml file') sys.exit(1) target_tree = ComposeXML.run_compose(target_tree, self.dir_name, generate_from_ini=generate_from_ini) report_filename = os.path.join(result_dirname, settings.content_file) try: write_to_file(report_filename, "wb", ElementTree.tostring(target_tree, "utf-8"), False) if generate_from_ini: print ('Generate report file for preupgrade-assistant is:', ''.join(report_filename)) except IOError as e: print ("Problem with writing file ", report_filename) raise return self.dir_name
def generate_xml(self, generate_from_ini=True): dir_util.copy_tree(self.result_dir, self.dir_name) result_dirname = self.dir_name template_file = ComposeXML.get_template_file() try: target_tree = ElementTree.parse(template_file).getroot() except IOError: print('Problem with reading template.xml file') sys.exit(1) target_tree = ComposeXML.run_compose( target_tree, self.dir_name, generate_from_ini=generate_from_ini) report_filename = os.path.join(result_dirname, settings.content_file) try: write_to_file(report_filename, "wb", ElementTree.tostring(target_tree, "utf-8"), False) if generate_from_ini: print('Generate report file for preupgrade-assistant is:', ''.join(report_filename)) except IOError as e: print("Problem with writing file ", report_filename) raise return self.dir_name
def update_check_script(dir_name, updates, script_name=None, author=""): """ The function updates check script with license file and with API functions like check_rpm_to and check_applies_to """ script_type = get_script_type(dir_name, script_name) if author == "": author = "<empty_line>" generated_section, functions = generate_common_stuff( settings.license.format(author), updates, script_type) full_path_script = get_full_path(dir_name, script_name) lines = get_file_content(full_path_script, "rb", method=True) if not [x for x in lines if re.search(r'#END GENERATED SECTION', x)]: print_error_msg( "#END GENERATED SECTION is missing in check_script {0}".format( full_path_script)) raise MissingHeaderCheckScriptError for func in functions: lines = [x for x in lines if func not in x.strip()] output_text = "" for line in lines: if '#END GENERATED SECTION' in line: new_line = '\n'.join(generated_section) new_line = new_line.replace('<empty_line>', '').replace('<new_line>', '') output_text += new_line + '\n' if 'check_applies' in updates: component = updates['check_applies'] else: component = "distribution" if script_type == "sh": output_text += 'COMPONENT="' + component + '"\n' else: output_text += 'set_component("' + component + '")\n' output_text += line write_to_file(full_path_script, "wb", output_text)
def save_kickstart(self): kickstart_data = self.ks.handler.__str__() kickstart_data = kickstart_data.replace( '%pre', '%%include %s\n\n%%pre\n' % self.temp_file) write_to_file(self.kick_start_name, 'wb', kickstart_data)
def _create_solution_file(self): if self.solution_file: utils.write_to_file(os.path.join(self.get_content_path(), self.get_solution_file()), 'wb', '')
def _create_check_script(self): if self.check_script: utils.write_to_file(os.path.join(self.get_content_path(), self.get_check_script()), 'wb', settings.temp_check_script) os.chmod(os.path.join(self.get_content_path(), self.get_check_script()), 0755)
def solution_file(message): write_to_file(os.path.join(os.environ['CURRENT_DIRECTORY'], SOLUTION_FILE), "a+b", message)
def _create_solution_file(self): if self.solution_file: utils.write_to_file( os.path.join(self.get_content_path(), self.get_solution_file()), 'wb', '')
def save_kickstart(self): kickstart_data = self.ks.handler.__str__() kickstart_data = kickstart_data.replace('%pre', '%%include %s\n\n%%pre\n' % self.temp_file) write_to_file(self.kick_start_name, 'wb', kickstart_data)