def show_progress(self, stdout_data): """Function shows a progress of assessment""" try: self.width_size = int(ScanProgress.get_terminal_width()[1]) except IndexError: self.width_size = 80 logger_report.debug(stdout_data.strip()) xccdf_rule = "" dummy_result = "" try: xccdf_rule, dummy_result = stdout_data.strip().split(':') except ValueError: print (stdout_data) return self.output_data.append(u'{0}:{1}'.format(self.names[xccdf_rule], stdout_data.strip())) self.current_count += 1 old_width = self.width_size self.width_size -= 21 prev_msg = self._return_correct_msg(self.get_full_name(self.current_count - 1)) self.width_size = old_width cur_msg = self._return_correct_msg(self.get_full_name(self.current_count)) cnt_back = 7 + len(prev_msg) + 3 msg = u'%sdone (%s)' % ('\b' * cnt_back, prev_msg) log_message(msg, new_line=True) if self.total_count > self.current_count: msg = self._return_correct_msg(u'%.3d/%.3d ...running (%s)' % (self.current_count + 1, self.total_count, cur_msg)) log_message(msg, new_line=False)
def get_and_print_inplace_risk(verbose, inplace_risk): """ The function browse throw the list and find first inplace_risk and return corresponding status. If verbose mode is used then it prints out all inplace risks higher then SLIGHT. """ risks = { 'SLIGHT:': 0, 'MEDIUM:': 0, 'HIGH:': 1, 'EXTREME:': 2, } return_value = -1 for key, val in sorted(iter(risks.items()), key=itemgetter(1), reverse=False): matched = [x for x in inplace_risk if key in x] logger_report.debug(matched) if matched: # if matched and return_value the remember her if return_value < val: return_value = val # If verbose mode is used and value is bigger then 0 then # prints out if int(verbose) > 1: log_message('\n'.join(matched)) elif int(verbose) == 1 and val > 0: log_message('\n'.join(matched)) return return_value
def update_check_description(self): logger_report.debug("Update check description") for rule in self._get_all_rules(): for description in self.filter_children(rule, 'description'): lines = description.text.split('\n') details = 'Details:' expected_results = 'Expected results:' attr = ' xml:lang="en"' tag_exp_results = expected_results[:-1].lower().replace( ' ', '-') tag_details = details[:-1].lower() found = 0 for index, line in enumerate(lines): if line.strip().startswith(details): found = 1 lines[index] = line.replace( details, '<ns0:' + tag_details + attr + '>') continue if line.strip().startswith(expected_results): found = 1 lines[index] = line.replace( expected_results, '</ns0:' + tag_details + '>\n<ns0:' + tag_exp_results + attr + '>') continue if found == 1: lines.append('</ns0:' + tag_exp_results + '>') description.text = '\n'.join(lines) self.write_xml()
def show_progress(self, stdout_data): """Function shows a progress of assessment""" try: self.width_size = int(ScanProgress.get_terminal_width()[1]) except IndexError: self.width_size = 80 logger_report.debug(stdout_data.strip()) xccdf_rule = "" dummy_result = "" try: xccdf_rule, dummy_result = stdout_data.strip().split(':') except ValueError: print(stdout_data) return self.output_data.append(u'{0}:{1}'.format(self.names[xccdf_rule], stdout_data.strip())) self.current_count += 1 old_width = self.width_size self.width_size -= 21 prev_msg = self._return_correct_msg( self.get_full_name(self.current_count - 1)) self.width_size = old_width cur_msg = self._return_correct_msg( self.get_full_name(self.current_count)) cnt_back = 7 + len(prev_msg) + 3 msg = u'%sdone (%s)' % ('\b' * cnt_back, prev_msg) log_message(msg, new_line=True) if self.total_count > self.current_count: msg = self._return_correct_msg( u'%.3d/%.3d ...running (%s)' % (self.current_count + 1, self.total_count, cur_msg)) log_message(msg, new_line=False)
def update_check_description(self): logger_report.debug("Update check description") for rule in self._get_all_rules(): for description in self.filter_children(rule, 'description'): lines = description.text.split('\n') details = 'Details:' expected_results = 'Expected results:' attr = ' xml:lang="en"' tag_exp_results = expected_results[:-1].lower().replace(' ', '-') tag_details = details[:-1].lower() found = 0 for index, line in enumerate(lines): if line.strip().startswith(details): found = 1 lines[index] = line.replace(details, '<ns0:' + tag_details + attr + '>') continue if line.strip().startswith(expected_results): found = 1 lines[index] = line.replace(expected_results, '</ns0:' + tag_details + '>\n<ns0:' + tag_exp_results + attr + '>') continue if found == 1: lines.append('</ns0:' + tag_exp_results + '>') description.text = '\n'.join(lines) self.write_xml()
def add_global_tags(self, result_dir, scenario, mode, devel_mode, dist_native): for child in self.get_nodes(self.target_tree, self.profile): last_child = child for key, val in iter(xml_tags.GLOBAL_DIC_VALUES.items()): if key == "tmp_preupgrade": val = result_dir elif key == "migrate" or key == "upgrade": if not mode or 'migrate' in mode or 'upgrade' in mode: val = "1" else: val = "0" elif key == "report_dir": val = os.path.join(result_dir, scenario) elif key == "devel_mode": val = str(devel_mode) elif key == "dist_native": if dist_native is None: val = "sign" else: val = dist_native logger_report.debug("'%s:%s'", key, val) new_child = ElementTree.Element(self.element_prefix + 'Value', {'id': xml_tags.TAG_VALUE + key, 'type': 'string' }) sub_child = ElementTree.SubElement(new_child, self.element_prefix + 'value') sub_child.text = val self.target_tree.insert(self.target_tree._children.index(last_child) + 1, new_child) self.write_xml()
def modify_platform_tag(self, platform_tag): """The function updates platform tag to the assessment system tag""" for platform in self.filter_children(self.target_tree, "platform"): if "cpe:/o:redhat:enterprise_linux:" in platform.get("idref"): logger_report.debug("Update platform tag to '%s'", platform_tag) platform.set("idref", "cpe:/o:redhat:enterprise_linux:"+platform_tag) self.write_xml()
def modify_result_path(self, result_dir, scenario, mode): """Function modifies result path in XML file""" for values in self.get_nodes(self.target_tree, "Value", prefix='.//'): if '_current_dir' not in values.get('id'): continue for value in self.get_nodes(values, "value"): logger_report.debug("Replace '%s' with '%s'", value.text, os.path.join(result_dir, scenario)) value.text = value.text.replace("SCENARIO", os.path.join(result_dir, scenario)) self.write_xml()
def modify_platform_tag(self, platform_tag): """The function updates platform tag to the assessment system tag""" for platform in self.filter_children(self.target_tree, "platform"): if "cpe:/o:redhat:enterprise_linux:" in platform.get("idref"): logger_report.debug("Update platform tag to '%s'", platform_tag) platform.set("idref", "cpe:/o:redhat:enterprise_linux:" + platform_tag) self.write_xml()
def update_data(self, changed_fields): """Function updates a data""" for index, row in enumerate(self.output_data): try: title, rule_id, dummy_result = row.split(':') logger_report.debug(row) except ValueError: continue else: result_list = [x for x in changed_fields if rule_id in x] if result_list: self.output_data[index] = u"%s:%s:%s" % (title, rule_id, result_list[0].split(':')[1])
def update_data(self, changed_fields): """Function updates a data""" for index, row in enumerate(self.output_data): try: title, rule_id, dummy_result = row.split(':') logger_report.debug(row) except ValueError: continue else: result_list = [x for x in changed_fields if rule_id in x] if result_list: self.output_data[index] = u"%s:%s:%s" % ( title, rule_id, result_list[0].split(':')[1])
def select_rules(self, list_rules): """ Function marks choice a specific rules based on the content generation :return: """ for select in self.get_select_rules(): idref = select.get('idref', None) logger_report.debug(select) logger_report.debug(idref) if idref in list_rules: select.set('selected', 'true') else: select.set('selected', 'false') self.write_xml()
def find_solution_files(self, result_name, xml_solution_files): """ Function finds all text files in conten and updates XML and HTML results """ solution_files = {} self.xml_solution_files = xml_solution_files for dir_name, sub_dir, file_name in os.walk(self.dirname): files = [x for x in file_name if x.endswith(".txt")] if files: logger_report.debug(files) solution_files[dir_name] = files self.update_html(result_name, solution_files) self.update_html(result_name, solution_files, extension="xml") clean_html(os.path.join(self.dirname, result_name + ".html"))
def update_inplace_risk(self, scanning_progress, rule, res): """Function updates inplace risk""" inplace_risk = XccdfHelper.get_check_import_inplace_risk(rule) if inplace_risk: logger_report.debug("Update_inplace_risk '%s'", inplace_risk) return_value = XccdfHelper.get_and_print_inplace_risk(0, inplace_risk) logger_report.debug("Get and print inplace risk return code '%s'", return_value) if int(return_value)/2 == 1: res.text = ReportHelper.get_needs_inspection() elif int(return_value)/2 == 2: res.text = ReportHelper.get_needs_action() for index, row in enumerate(scanning_progress.output_data): if self.get_nodes_text(rule, "title") in row: scanning_progress.output_data[index] = "{0}:{1}".format( self.get_nodes_text(rule, "title"), res.text)
def get_check_import_inplace_risk(tree): """ Function returns implace risks """ inplace_risk = [] risk_regex = "preupg\.risk\.(?P<level>\w+): (?P<message>.+)" for check in tree.findall(".//" + XMLNS + "check-import"): if not check.text: continue lines = check.text.strip().split('\n') for line in lines: match = re.match(risk_regex, line) if match: logger_report.debug(line) if line not in inplace_risk: inplace_risk.append(line) return inplace_risk
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 = FileHelper.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: logger_report.debug("Solution text '%s' name '%s'", solution_text, file_name) text = FileHelper.get_file_content(os.path.join( dir_name, file_name), "rb", method=True) for cnt, line in enumerate(lines): # If in preupg.risk is a [link] then update them # to /root/pre{migrate,upgrade}/... if 'preupg.risk.' in line.strip(): logger_report.debug(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()) FileHelper.write_to_file(orig_file, "wb", lines)
def get_solution_files(self): """ Function returns a dictionary with solution_files Format is: xccdf_preupg_backup_solution_file=solution.txt """ dict_solution = {} for values in self.get_nodes(self.target_tree, "Value", prefix='.//'): value_id = values.get('id') if not value_id.endswith("_state_solution_file"): continue for value in self.get_nodes(values, "value"): logger_report.debug(value_id) value_id = value_id.replace('xccdf_preupg_value_', '').replace("_state_solution_file", '') dict_solution[value_id] = value.text logger_report.debug(dict_solution) return dict_solution
def load_solution_texts(self): """Load solution texts into a dictionary.""" for dir_name in self.paths_to_all_modules: section = dir_name.replace(self.copied_module_set_path, "").replace("/", "_") solution_placeholder = section + "_SOLUTION_MSG" logger_report.debug("Processing solution placeholder '%s'", solution_placeholder) try: solution_text = FileHelper.get_file_content( os.path.join(dir_name, settings.solution_txt), "rb") except IOError: # solution file is not mandatory solution_text = "" updated_solution_text = self.get_updated_solution(solution_text) self.solution_texts[solution_placeholder] = updated_solution_text
def load_solution_texts(self): """Load solution texts into a dictionary.""" for dir_name in self.paths_to_all_modules: section = dir_name.replace( self.copied_module_set_path, "").replace("/", "_") solution_placeholder = section + "_SOLUTION_MSG" logger_report.debug("Processing solution placeholder '%s'", solution_placeholder) try: solution_text = FileHelper.get_file_content( os.path.join(dir_name, settings.solution_txt), "rb") except IOError: # solution file is not mandatory solution_text = "" updated_solution_text = self.get_updated_solution(solution_text) self.solution_texts[solution_placeholder] = updated_solution_text
def get_solution_files(self): """ Function returns a dictionary with solution_files Format is: xccdf_preupg_backup_solution_file=solution.txt """ dict_solution = {} for values in self.get_nodes(self.target_tree, "Value", prefix='.//'): value_id = values.get('id') if not value_id.endswith("_state_solution_file"): continue for value in self.get_nodes(values, "value"): logger_report.debug(value_id) value_id = value_id.replace('xccdf_preupg_value_', '').replace( "_state_solution_file", '') dict_solution[value_id] = value.text logger_report.debug(dict_solution) return dict_solution
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 = FileHelper.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: logger_report.debug("Solution text '%s' name '%s'", solution_text, file_name) text = FileHelper.get_file_content(os.path.join(dir_name, file_name), "rb", method=True) for cnt, line in enumerate(lines): # If in preupg.risk is a [link] then update them # to /root/pre{migrate,upgrade}/... if 'preupg.risk.' in line.strip(): logger_report.debug(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()) FileHelper.write_to_file(orig_file, "wb", lines)
def _return_correct_text_file(self, section, files): """ Function returns only one text file based on section and list of txt files from content directory """ file_name = None for key, value in self.xml_solution_files.items(): # section is in format _<path_content> section_name = section[1:] + "_" if section_name not in key: continue # This will return only try: logger_report.debug(value) file_name = [txt for txt in files if txt == value][0] logger_report.debug(file_name) break except IndexError: logger_report.debug("Value '%s'", value) logger_report.debug("Found text file '%s'.", file_name) return file_name
def replace_inplace_risk(self, scanning_results=None): """ This function has aim to replace FAILED to NEEDS_INSPECTION in case that risks are SLIGHT or MEDIUM """ #Filter all rule-result in TestResult changed_fields = [] self.remove_empty_check_import() inplace_dict = { 0: ReportHelper.upd_inspection, 1: ReportHelper.upd_action, 2: ReportHelper.upd_extreme, } for rule in self.get_all_result_rules(): result = [ x for x in self.get_nodes(rule, "result") if x.text == "fail" ] # Get all affected rules and taken their names for res in result: inplace_risk = XccdfHelper.get_check_import_inplace_risk(rule) logger_report.debug(inplace_risk) # In case that report has state fail and # no log_risk than it should be needs_inspection if not inplace_risk: changed = rule.get("idref") res.text = "fail" log_message( 'The %s module exits as fail but without a risk.' % rule.get("idref")) else: inplace_num = XccdfHelper.get_and_print_inplace_risk( 0, inplace_risk) logger_report.debug("Call function '%s'", inplace_dict[inplace_num]) changed, res.text = inplace_dict[inplace_num](rule) logger_report.debug("Replace text '%s:%s'", changed, res.text) if changed is not None: changed_fields.append(changed + ":" + res.text) if scanning_results: scanning_results.update_data(changed_fields) self.write_xml()
def replace_inplace_risk(self, scanning_results=None): """ This function has aim to replace FAILED to NEEDS_INSPECTION in case that risks are SLIGHT or MEDIUM """ #Filter all rule-result in TestResult changed_fields = [] self.remove_empty_check_import() inplace_dict = { 0: ReportHelper.upd_inspection, 1: ReportHelper.upd_action, 2: ReportHelper.upd_extreme, } for rule in self.get_all_result_rules(): result = [x for x in self.get_nodes(rule, "result") if x.text == "fail"] # Get all affected rules and taken their names for res in result: inplace_risk = XccdfHelper.get_check_import_inplace_risk(rule) logger_report.debug(inplace_risk) # In case that report has state fail and # no log_risk than it should be needs_inspection if not inplace_risk: changed = rule.get("idref") res.text = "fail" log_message('The %s module exits as fail but without a risk.' % rule.get("idref")) else: inplace_num = XccdfHelper.get_and_print_inplace_risk(0, inplace_risk) logger_report.debug("Call function '%s'", inplace_dict[inplace_num]) changed, res.text = inplace_dict[inplace_num](rule) logger_report.debug("Replace text '%s:%s'", changed, res.text) if changed is not None: changed_fields.append(changed+":"+res.text) if scanning_results: scanning_results.update_data(changed_fields) self.write_xml()
def check_inplace_risk(xccdf_file, verbose): """ The function read the content of the file and finds out all "preupg.risk" rows in TestResult tree. return code is get from function get_and_print_inplace_risk """ message = "'preupg' command was not run yet. Run 'preupg' before getting list of risks." try: content = FileHelper.get_file_content(xccdf_file, 'rb', False, False) if not content: # WE NEED TO RETURN -1 FOR RED-HAT-UPGRADE-TOOL log_message(message) return -1 except IOError: # WE NEED TO RETURN -1 FOR RED-HAT-UPGRADE-TOOL log_message(message) return -1 target_tree = ElementTree.fromstring(content) results = {} for profile in target_tree.findall(XMLNS + "TestResult"): # Collect all inplace risk for each return code for rule_result in profile.findall(XMLNS + "rule-result"): result_value = None for check in rule_result.findall(XMLNS + "result"): result_value = check.text if check.text not in results: results[check.text] = [] inplace_risk = XccdfHelper.get_check_import_inplace_risk(rule_result) if not inplace_risk: continue for risk in inplace_risk: if risk not in results[result_value]: results[result_value].append(risk) logger_report.debug(results) return_val = 0 for result in settings.ORDERED_LIST: if result in results: current_val = 0 logger_report.debug('%s found in assessment' % result) current_val = settings.PREUPG_RETURN_VALUES[result] ret_val = XccdfHelper.get_and_print_inplace_risk(verbose, results[result]) """ if not results[result]: ret_val = XccdfHelper.get_and_print_inplace_risk(verbose, results[result]) if result == 'fail' and int(ret_val) == -1: current_val = settings.PREUPG_RETURN_VALUES['error'] else: current_val = settings.PREUPG_RETURN_VALUES[result] else: ret_val = XccdfHelper.get_and_print_inplace_risk(verbose, results[result]) logger_report.debug('Return value from "get_and_print_inplace_risk" is %s' % ret_val) if result == 'fail' and int(ret_val) == -1: current_val = settings.PREUPG_RETURN_VALUES['error'] elif result in settings.ERROR_RETURN_VALUES and int(ret_val) != -1: current_val = settings.PREUPG_RETURN_VALUES['error'] elif int(ret_val) == -1: current_val = settings.PREUPG_RETURN_VALUES[result] else: # EXTREME has to return 2 as FAIL if ret_val == 2: current_val = ModuleValues.FAIL else: # Needs_action has to return 1 as needs_inspection current_val = ModuleValues.NEEDS_INSPECTION """ if return_val < current_val: return_val = current_val return return_val