diff --git a/0002-fix-bug-and-update-the-code-of-parsing.patch b/0002-fix-bug-and-update-the-code-of-parsing.patch new file mode 100644 index 0000000000000000000000000000000000000000..2fd0f7f4e093a85e40c5226965c05474d466acb6 --- /dev/null +++ b/0002-fix-bug-and-update-the-code-of-parsing.patch @@ -0,0 +1,91 @@ +From 313271160b4826c9c2d2b3afe2f0489c4a95fef9 Mon Sep 17 00:00:00 2001 +From: wang-guangge +Date: Thu, 1 Jun 2023 21:31:58 +0800 +Subject: [PATCH] fix bug and update the code of parsing src.rpm + +--- + .../aops_apollo_tool/gen_updateinfo.py | 42 ++++++++++++++----- + 1 file changed, 32 insertions(+), 10 deletions(-) + mode change 100755 => 100644 aops-apollo-tool/aops_apollo_tool/gen_updateinfo.py + +diff --git a/aops-apollo-tool/aops_apollo_tool/gen_updateinfo.py b/aops-apollo-tool/aops_apollo_tool/gen_updateinfo.py +old mode 100755 +new mode 100644 +index 26f3226..2204b10 +--- a/aops-apollo-tool/aops_apollo_tool/gen_updateinfo.py ++++ b/aops-apollo-tool/aops_apollo_tool/gen_updateinfo.py +@@ -26,7 +26,7 @@ import rpm + import configparser + + # get updateinfo global config +-UPDATEINFO_FILE = "/etc/gen_updateinfo/updateinfo_config.ini" ++UPDATEINFO_FILE = "/etc/aops_apollo_tool/updateinfo_config.ini" + CONF = configparser.ConfigParser() + CONF.read(filenames=UPDATEINFO_FILE) + +@@ -69,6 +69,21 @@ def check_uniqueness_of_advisory_id(root: ET, advisory_id: str) -> int: + sys.exit(1) + existed_adv_id.add(update_adv_id) + ++def parse_src_rpm_info_by_filename(filename: str) -> tuple: ++ """ ++ Parse source rpm package information by filename, the filename should be 'name-version-release.src.rpm'. ++ ++ Returns: ++ name, version, release ++ """ ++ nevra_pos = filename.rindex('.src.rpm') ++ nevra = filename[:nevra_pos] ++ release_pos = nevra.rindex('-') ++ version_pos = nevra.rindex('-', 0, release_pos) ++ name, version, release = nevra[0:version_pos], nevra[ ++ version_pos+1:release_pos], nevra[release_pos+1:] ++ ++ return name, version, release + + def generate_package_list(package_dir: str) -> Element: + """ +@@ -107,21 +122,27 @@ def generate_package_list(package_dir: str) -> Element: + except rpm.error: + print("error: %s cannot be successfully parsed" % package_path) + sys.exit(1) ++ ++ filename = Element('filename') ++ if pkg.endswith('.src.rpm'): ++ # parse source rpm information by filename, and the arch information is not marked ++ name, version, release = parse_src_rpm_info_by_filename(pkg) ++ package.attrib['name'] = name ++ package.attrib['version'] = version ++ package.attrib['release'] = release ++ filename.text = pkg + +- try: ++ else: + package.attrib['arch'] = pkg_info[rpm.RPMTAG_ARCH] + package.attrib['name'] = pkg_info[rpm.RPMTAG_NAME] + package.attrib['version'] = pkg_info[rpm.RPMTAG_VERSION] + package.attrib['release'] = pkg_info[rpm.RPMTAG_R] +- except rpm.error: +- print("error: key information is lost in %s" % package_path) +- sys.exit(1) + +- filename = Element('filename') +- filename.text = "%s-%s-%s.%s.rpm" % (package.attrib['name'], +- package.attrib['release'], +- package.attrib['version'], +- package.attrib['arch']) ++ filename.text = "%s-%s-%s.%s.rpm" % (package.attrib['name'], ++ package.attrib['release'], ++ package.attrib['version'], ++ package.attrib['arch']) ++ + package.append(filename) + collection.append(package) + +@@ -306,3 +327,4 @@ def main(): + + main() + ++ +-- +Gitee diff --git a/0003-fix-hotpatch-updateinfo-for-search-hotpatch-info.patch b/0003-fix-hotpatch-updateinfo-for-search-hotpatch-info.patch new file mode 100644 index 0000000000000000000000000000000000000000..bfec3025441cfe9a3e9b6df358c3ee1b31f8ee10 --- /dev/null +++ b/0003-fix-hotpatch-updateinfo-for-search-hotpatch-info.patch @@ -0,0 +1,381 @@ +From faeec6eff1e80be893916d16fb6bd3cd8f0246c9 Mon Sep 17 00:00:00 2001 +From: wang-guangge +Date: Wed, 31 May 2023 18:06:22 +0800 +Subject: [PATCH] fix hotpatch updateinfo for search hotpatch information +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + hotpatch/baseclass.py | 14 ++-- + hotpatch/hot-updateinfo.py | 118 +++++++++----------------------- + hotpatch/hotpatch.py | 13 ++-- + hotpatch/hotpatch_updateinfo.py | 58 ++++++++++------ + 4 files changed, 83 insertions(+), 120 deletions(-) + +diff --git a/hotpatch/baseclass.py b/hotpatch/baseclass.py +index d88ef40..2542a03 100644 +--- a/hotpatch/baseclass.py ++++ b/hotpatch/baseclass.py +@@ -115,7 +115,7 @@ class Hotpatch(object): + + + class Cve(object): +- __slots__ = ['_cve_id', '_hotpatch'] ++ __slots__ = ['_cve_id', '_hotpatches'] + + def __init__(self, + id, +@@ -124,15 +124,14 @@ class Cve(object): + id: str + """ + self._cve_id = id +- self._hotpatch = None ++ self._hotpatches = [] + + @property +- def hotpatch(self): +- return self._hotpatch ++ def hotpatches(self): ++ return self._hotpatches + +- @hotpatch.setter +- def hotpatch(self, hotpatch: Hotpatch): +- self._hotpatch = hotpatch ++ def add_hotpatch(self, hotpatch: Hotpatch): ++ self._hotpatches.append(hotpatch) + + @property + def cve_id(self): +@@ -206,3 +205,4 @@ class Advisory(object): + + def add_hotpatch(self, hotpatch: Hotpatch): + self._hotpatches.append(hotpatch) ++ +diff --git a/hotpatch/hot-updateinfo.py b/hotpatch/hot-updateinfo.py +index 779337b..d1e6d58 100644 +--- a/hotpatch/hot-updateinfo.py ++++ b/hotpatch/hot-updateinfo.py +@@ -4,46 +4,6 @@ from dnf.cli.commands.updateinfo import UpdateInfoCommand + import hawkey + from .hotpatch_updateinfo import HotpatchUpdateInfo + +- +-class Versions: +- """ +- Version number processing +- """ +- +- separator = (".", "-") +- _connector = "&" +- +- def _order(self, version, separator=None): +- """ +- Version of the cutting +- Args: +- version: version +- separator: separator +- +- Returns: +- +- """ +- if not separator: +- separator = self._connector +- return tuple([int(v) for v in version.split(separator) if v.isdigit()]) +- +- def lgt(self, version, compare_version): +- """ +- Returns true if the size of the compared version is greater +- than that of the compared version, or false otherwise +- +- """ +- for separator in self.separator: +- version = self._connector.join( +- [v for v in version.split(separator)]) +- compare_version = self._connector.join( +- [v for v in compare_version.split(separator)] +- ) +- version = self._order(version) +- compare_version = self._order(compare_version) +- return version >= compare_version +- +- + @dnf.plugin.register_command + class HotUpdateinfoCommand(dnf.cli.Command): + aliases = ['hot-updateinfo'] +@@ -118,26 +78,13 @@ class HotUpdateinfoCommand(dnf.cli.Command): + + return mapping_nevra_cve + +- def _filter_and_format_list_output(self, echo_lines: list, fixed_cve_id: set, fixed_coldpatches: set): ++ def _filter_and_format_list_output(self, echo_lines: list, fixed_cve_id: set): + """ + Only show specified cve information that have not been fixed, and format output + """ +- def is_patch_fixed(coldpatch, fixed_coldpatches): +- """ +- Check whether the coldpatch is fixed +- """ +- for fixed_coldpatch in fixed_coldpatches: +- pkg_name, pkg_evr, _ = coldpatch +- fixed_pkg_name, fixed_pkg_evr, _ = fixed_coldpatch +- if pkg_name != fixed_pkg_name: +- continue +- if version.lgt(fixed_pkg_evr, pkg_evr): +- return True +- return False + + idw = tiw = ciw = 0 + format_lines = set() +- version = Versions() + for echo_line in echo_lines: + cve_id, adv_type, coldpatch, hotpatch = echo_line[0], echo_line[1], echo_line[2], echo_line[3] + if self.filter_cves is not None and cve_id not in self.filter_cves: +@@ -145,11 +92,8 @@ class HotUpdateinfoCommand(dnf.cli.Command): + if cve_id in fixed_cve_id: + continue + if not isinstance(coldpatch, str): +- if is_patch_fixed(coldpatch, fixed_coldpatches): +- continue +- else: +- pkg_name, pkg_evr, pkg_arch = coldpatch +- coldpatch = '%s-%s.%s' % (pkg_name, pkg_evr, pkg_arch) ++ pkg_name, pkg_evr, pkg_arch = coldpatch ++ coldpatch = '%s-%s.%s' % (pkg_name, pkg_evr, pkg_arch) + + idw = max(idw, len(cve_id)) + tiw = max(tiw, len(adv_type)) +@@ -178,41 +122,43 @@ class HotUpdateinfoCommand(dnf.cli.Command): + mapping_nevra_cve = self.get_mapping_nevra_cve() + echo_lines = [] + fixed_cve_id = set() +- fixed_coldpatches = set() + iterated_cve_id = set() + for ((nevra), aupdated), id2type in sorted(mapping_nevra_cve.items(), key=lambda x: x[0]): + pkg_name, pkg_evr, pkg_arch = nevra + for cve_id, atypesev in id2type.items(): + iterated_cve_id.add(cve_id) +- label = type2label(self.updateinfo, *atypesev) +- echo_line = [cve_id, label, nevra, '-'] +- echo_lines.append(echo_line) +- if cve_id not in self.hp_hawkey.hotpatch_cves: ++ label = type2label(self.updateinfo, *atypesev) ++ if cve_id not in self.hp_hawkey.hotpatch_cves or not self.hp_hawkey.hotpatch_cves[cve_id].hotpatches: ++ echo_line = [cve_id, label, nevra, '-'] ++ echo_lines.append(echo_line) + continue +- hotpatch = self.hp_hawkey.hotpatch_cves[cve_id].hotpatch +- if hotpatch is None or hotpatch.src_pkg_nevre[0] != pkg_name: +- continue +- if hotpatch.state == self.hp_hawkey.INSTALLED: +- # record the fixed cves +- for cve_id in hotpatch.cves: +- fixed_cve_id.add(cve_id) +- # record the fixed coldpatch to filter the cves of the corresponding coldpatch with the lower version +- fixed_coldpatches.add((nevra)) +- echo_lines.pop() +- elif hotpatch.state == self.hp_hawkey.INSTALLABLE: +- echo_lines[-1][3] = hotpatch.nevra ++ ++ for hotpatch in self.hp_hawkey.hotpatch_cves[cve_id].hotpatches: ++ echo_line = [cve_id, label, nevra, '-'] ++ echo_lines.append(echo_line) ++ if hotpatch.src_pkg_nevre[0] != pkg_name: ++ continue ++ if hotpatch.state == self.hp_hawkey.INSTALLED: ++ # record the fixed cves ++ for cve_id in hotpatch.cves: ++ fixed_cve_id.add(cve_id) ++ echo_lines.pop() ++ elif hotpatch.state == self.hp_hawkey.INSTALLABLE: ++ echo_lines[-1][3] = hotpatch.nevra ++ + + hp_cve_list = list(set(self.hp_hawkey.hotpatch_cves.keys()).difference(iterated_cve_id)) + for cve_id in hp_cve_list: +- hotpatch = self.hp_hawkey.hotpatch_cves[cve_id].hotpatch +- if hotpatch is None: +- continue +- echo_line = [cve_id, hotpatch.advisory.severity + '/Sec.', '-', '-'] +- if hotpatch.state == self.hp_hawkey.INSTALLED: +- continue +- elif hotpatch.state == self.hp_hawkey.INSTALLABLE: +- echo_line = [cve_id, hotpatch.advisory.severity + '/Sec.', '-', hotpatch.nevra] +- echo_lines.append(echo_line) ++ for hotpatch in self.hp_hawkey.hotpatch_cves[cve_id].hotpatches: ++ echo_line = [cve_id, hotpatch.advisory.severity + '/Sec.', '-', '-'] ++ if hotpatch.state == self.hp_hawkey.INSTALLED: ++ # record the fixed cves ++ fixed_cve_id.add(cve_id) ++ continue ++ elif hotpatch.state == self.hp_hawkey.INSTALLABLE: ++ echo_line = [cve_id, hotpatch.advisory.severity + '/Sec.', '-', hotpatch.nevra] ++ echo_lines.append(echo_line) + + self._filter_and_format_list_output( +- echo_lines, fixed_cve_id, fixed_coldpatches) ++ echo_lines, fixed_cve_id) ++ +diff --git a/hotpatch/hotpatch.py b/hotpatch/hotpatch.py +index 0704a08..ccef636 100644 +--- a/hotpatch/hotpatch.py ++++ b/hotpatch/hotpatch.py +@@ -102,12 +102,12 @@ class HotpatchCommand(dnf.cli.Command): + hotpatch_cves = self.hp_hawkey.hotpatch_cves + echo_lines = [] + for cve_id in hotpatch_cves.keys(): +- hotpatch = hotpatch_cves[cve_id].hotpatch +- status = self.hp_hawkey._get_hotpatch_status_in_syscare(hotpatch) +- if status == '': +- continue +- echo_line = [cve_id, hotpatch.syscare_name, status] +- echo_lines.append(echo_line) ++ for hotpatch in hotpatch_cves[cve_id].hotpatches: ++ status = self.hp_hawkey._get_hotpatch_status_in_syscare(hotpatch) ++ if status == '': ++ continue ++ echo_line = [cve_id, hotpatch.syscare_name, status] ++ echo_lines.append(echo_line) + + self._filter_and_format_list_output(echo_lines) + +@@ -133,3 +133,4 @@ class HotpatchCommand(dnf.cli.Command): + else: + logger.info(_("%s hot patch '%s' succeed"), operate, self.base.output.term.bold(target_patch)) + ++ +diff --git a/hotpatch/hotpatch_updateinfo.py b/hotpatch/hotpatch_updateinfo.py +index 6689553..399e05c 100644 +--- a/hotpatch/hotpatch_updateinfo.py ++++ b/hotpatch/hotpatch_updateinfo.py +@@ -67,7 +67,7 @@ class HotpatchUpdateInfo(object): + """ + Initialize hotpatch information from repos + """ +- # get xxx-hotpatch.xml.gz file paths by traversing the system_cachedir(/var/cache/dnf) ++ # get xxx-updateinfo.xml.gz file paths by traversing the system_cachedir(/var/cache/dnf) + system_cachedir = self.cli.base.conf.system_cachedir + all_repos = self.cli.base.repos + map_repo_updateinfoxml = {} +@@ -80,9 +80,9 @@ class HotpatchUpdateInfo(object): + continue + + for xml_file in os.listdir(repodata_path): +- # the hotpatch relevant updateinfo is recorded in xxx-hotpatch.xml.gz +- if "hotpatch" in xml_file: +- repo_name = file.split("-")[0] ++ # the hotpatch relevant updateinfo is recorded in xxx-updateinfo.xml.gz ++ if "updateinfo" in xml_file: ++ repo_name = file.rsplit("-")[0] + cache_updateinfo_xml_path = os.path.join( + repodata_path, xml_file) + map_repo_updateinfoxml[repo_name] = cache_updateinfo_xml_path +@@ -99,7 +99,7 @@ class HotpatchUpdateInfo(object): + Parse the pkglist information, filter the hotpatches with different arches + """ + hotpatches = [] +- hot_patch_collection = pkglist.find('collection') ++ hot_patch_collection = pkglist.find('hot_patch_collection') + arches = self.base.sack.list_arches() + if not hot_patch_collection: + return hotpatches +@@ -171,14 +171,19 @@ class HotpatchUpdateInfo(object): + advisory.cves = advisory_cves + + for hotpatch_kwargs in advisory_hotpatches: ++ # parse the id string of the package to list ++ # e.g. parse the id of "CVE-2021-2023,CVE-2021-2024" to ["CVE-2021-2023", "CVE-2021-2024"] ++ hotpatch_ref_id = hotpatch_kwargs.pop('id') ++ hotpatch_ref_id = hotpatch_ref_id.split(',') ++ + hotpatch = Hotpatch(**hotpatch_kwargs) + hotpatch.advisory = advisory +- hotpatch.cves = advisory_cves.keys() ++ hotpatch.cves = hotpatch_ref_id + + advisory.add_hotpatch(hotpatch) +- +- for cve in advisory_cves.values(): +- cve.hotpatch = hotpatch ++ ++ for ref_id in hotpatch_ref_id: ++ advisory_cves[ref_id].add_hotpatch(hotpatch) + + self._hotpatch_advisories[advisory_kwargs['id']] = advisory + +@@ -213,9 +218,9 @@ class HotpatchUpdateInfo(object): + + def _parse_and_store_from_xml(self, updateinfoxml): + """ +- Parse and store hotpatch update information from xxx-hotpatch.xml.gz ++ Parse and store hotpatch update information from xxx-updateinfo.xml.gz + +- xxx-hotpatch.xml.gz e.g. ++ xxx-updateinfo.xml.gz e.g. + + + +@@ -226,19 +231,26 @@ class HotpatchUpdateInfo(object): + openEuler + + +- ++ ++ + + patch-redis-6.2.5-1-HP001.(CVE-2022-24048) + +- ++ + openEuler +- +- patch-redis-6.2.5-1-HP001-0-1.aarch64.rpm ++ ++ patch-redis-6.2.5-1-HP001-1-1.aarch64.rpm ++ ++ ++ patch-redis-6.2.5-1-HP001-1-1.x86_64.rpm ++ ++ ++ patch-redis-6.2.5-1-HP002-1-1.aarch64.rpm + +- +- patch-redis-6.2.5-1-HP001-0-1.x86_64.rpm ++ ++ patch-redis-6.2.5-1-HP002-1-1.x86_64.rpm + +- ++ + + + ... +@@ -248,6 +260,9 @@ class HotpatchUpdateInfo(object): + tree = ET.parse(content) + root = tree.getroot() + for update in root.iter('update'): ++ # check whether the hotpatch relevant package information is in each advisory ++ if not update.find('pkglist/hot_patch_collection'): ++ continue + advisory = self._parse_advisory(update) + self._store_advisory_info(advisory) + +@@ -288,9 +303,9 @@ class HotpatchUpdateInfo(object): + mapping_cve_hotpatches[cve_id] = [] + if cve_id not in self.hotpatch_cves: + continue +- hotpatch = self.hotpatch_cves[cve_id].hotpatch +- if hotpatch is not None and hotpatch.state == self.INSTALLABLE: +- mapping_cve_hotpatches[cve_id].append(hotpatch.nevra) ++ for hotpatch in self.hotpatch_cves[cve_id].hotpatches: ++ if hotpatch.state == self.INSTALLABLE: ++ mapping_cve_hotpatches[cve_id].append(hotpatch.nevra) + return mapping_cve_hotpatches + + def get_hotpatches_from_advisories(self, advisories: list[str]) -> dict(): +@@ -317,3 +332,4 @@ class HotpatchUpdateInfo(object): + mapping_advisory_hotpatches[advisory_id].append( + hotpatch.nevra) + return mapping_advisory_hotpatches ++ +-- +Gitee diff --git a/0004-add-dnf-full-repair.patch b/0004-add-dnf-full-repair.patch new file mode 100644 index 0000000000000000000000000000000000000000..5b53a1058b0545a18c909fae66689d2e00ad5667 --- /dev/null +++ b/0004-add-dnf-full-repair.patch @@ -0,0 +1,100 @@ +From 66356dfbe509f2e9d445a2185ff68abdfaa1cd3a Mon Sep 17 00:00:00 2001 +From: gongzt +Date: Fri, 2 Jun 2023 19:24:22 +0800 +Subject: [PATCH 1/1] Add dnf full repair + +--- + hotpatch/hotupgrade.py | 57 +++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 53 insertions(+), 4 deletions(-) + +diff --git a/hotpatch/hotupgrade.py b/hotpatch/hotupgrade.py +index 4f6a6fb..6adafda 100644 +--- a/hotpatch/hotupgrade.py ++++ b/hotpatch/hotupgrade.py +@@ -20,9 +20,11 @@ from dnf.cli.option_parser import OptionParser + from dnf.cli.output import Output + from dnfpluginscore import _, logger + +-from .syscare import Syscare ++from .syscare import Syscare, cmd_output, SUCCEED + from .hotpatch_updateinfo import HotpatchUpdateInfo + ++EMPTY_TAG = "-" ++ + + @dnf.plugin.register_command + class HotupgradeCommand(dnf.cli.Command): +@@ -61,7 +63,8 @@ class HotupgradeCommand(dnf.cli.Command): + advisory_pkgs = self.get_hotpatch_based_on_advisory(self.opts.advisory) + self.hp_list = cve_pkgs + advisory_pkgs + else: +- raise dnf.exceptions.Error(_('No qualified rpm package name or cve/advisory id.')) ++ self.hp_list = self.upgrade_all() ++ logger.info(_("Gonna apply these hot patches:%s"), self.hp_list) + + hp_target_map = self._get_available_hotpatches(self.hp_list) + if not hp_target_map: +@@ -177,8 +180,8 @@ class HotupgradeCommand(dnf.cli.Command): + def _remove_hot_patches(self, target_patch_map: dict) -> None: + output = Output(self.base, dnf.conf.Conf()) + logger.info(_("Gonna remove these hot patches: %s"), list(target_patch_map.values())) +- #remove_flag = output.userconfirm() +- #if not remove_flag: ++ # remove_flag = output.userconfirm() ++ # if not remove_flag: + # raise dnf.exceptions.Error(_('Operation aborted.')) + + self.syscare.save() +@@ -266,3 +269,49 @@ class HotupgradeCommand(dnf.cli.Command): + for hp in advisory_hp_dict.values(): + hp_list += hp + return list(set(hp_list)) ++ ++ @staticmethod ++ def get_hot_updateinfo_list(): ++ """ ++ Find all hotpatches and upgrade all ++ use command : dnf hot-updateinfo list cves ++ Last metadata expiration check: 0:48:26 ago on 2023年06月01日 星期四 20时29分55秒. ++ CVE-2023-3332 Low/Sec. - - ++ CVE-2023-3331 Low/Sec. - - ++ CVE-2023-1112 Important/Sec. - patch-redis-6.2.5-1-HP001-1-1.x86_64 ++ CVE-2023-1111 Important/Sec. - patch-redis-6.2.5-1-HP001-1-1.x86_64 ++ ++ return:list ++ [["CVE-2023-3332","Low/Sec.", "-" ,"-"]] ++ ++ """ ++ cmd = ["dnf", "hot-updateinfo", "list", "cves"] ++ ++ output, return_code = cmd_output(cmd) ++ if return_code != SUCCEED: ++ return [] ++ ++ content = output.split('\n') ++ if len(content) <= 2: ++ return [] ++ result = [] ++ for item in content[1:-1]: ++ tmp = item.split() ++ result.append(tmp) ++ return result ++ ++ def upgrade_all(self): ++ """ ++ upgrade all exist cve and hot patches ++ ++ Return: ++ find all patches and return patches list ++ e.g.: ++ ['patch-redis-6.2.5-1-HP2-1-1.x86_64'] ++ """ ++ hotpatchs_info = self.get_hot_updateinfo_list() ++ hp_list = [] ++ for item in hotpatchs_info: ++ if item[-1] != EMPTY_TAG: ++ hp_list.append(item[-1]) ++ return list(set(hp_list)) +-- +2.33.0 + diff --git a/0005-fix-generate-task-is-not-verified-host-and-cve.patch b/0005-fix-generate-task-is-not-verified-host-and-cve.patch new file mode 100644 index 0000000000000000000000000000000000000000..5ae3ebff1e155c1325f96a27fb93173a763e7e90 --- /dev/null +++ b/0005-fix-generate-task-is-not-verified-host-and-cve.patch @@ -0,0 +1,105 @@ +From a032e1e0b11365a0dc5d725fd234771cd53c0858 Mon Sep 17 00:00:00 2001 +From: gongzt +Date: Fri, 2 Jun 2023 14:29:57 +0800 +Subject: [PATCH] Repair Host cve verification is not performed in a generation task +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + apollo/database/proxy/task.py | 37 +++++++++++++++++++++++++++++ + apollo/handler/task_handler/view.py | 20 ++++++++++++++++ + 2 files changed, 57 insertions(+) + +diff --git a/apollo/database/proxy/task.py b/apollo/database/proxy/task.py +index e660f02..edba161 100644 +--- a/apollo/database/proxy/task.py ++++ b/apollo/database/proxy/task.py +@@ -3208,3 +3208,40 @@ class TaskProxy(TaskMysqlProxy, TaskEsProxy): + + # insert task id and username into es + self._init_task_in_es(task_id, data["username"]) ++ ++ def validate_cves(self, cve_id: list) -> bool: ++ """ ++ Verifying cve validity ++ ++ Args: ++ cve_id: id of the cve to be validate ++ ++ Returns: ++ bool: A return of true indicates that the validation passed ++ """ ++ ++ try: ++ exists_cve_count = self.session.query(CveHostAssociation).filter( ++ CveHostAssociation.cve_id.in_(cve_id)).count() ++ ++ return True if exists_cve_count == len(cve_id) else False ++ except SQLAlchemyError as error: ++ LOGGER.error(error) ++ return False ++ ++ def validate_hosts(self, host_id: list) -> bool: ++ """ ++ Verifying host validity ++ ++ Args: ++ host_id: id of the host to be validate ++ ++ Returns: ++ bool: A return of true indicates that the validation passed ++ """ ++ try: ++ exists_host_count = self.session.query(Host).filter(Host.host_id.in_(host_id)).count() ++ return True if exists_host_count == len(host_id) else False ++ except SQLAlchemyError as error: ++ LOGGER.error(error) ++ return False +diff --git a/apollo/handler/task_handler/view.py b/apollo/handler/task_handler/view.py +index 214053c..314f7bb 100644 +--- a/apollo/handler/task_handler/view.py ++++ b/apollo/handler/task_handler/view.py +@@ -287,6 +287,14 @@ class VulGenerateCveTask(BaseResponse): + "task_id": "id1" + } + """ ++ host_ids = [host["host_id"] for hosts in params["info"] for host in hosts["host_info"]] ++ if not callback.validate_hosts(host_id=list(set(host_ids))): ++ return self.response(code=PARAM_ERROR) ++ ++ cve_ids = [cve["cve_id"] for cve in params["info"]] ++ if not callback.validate_cves(cve_id=list(set(cve_ids))): ++ return self.response(code=PARAM_ERROR) ++ + status_code, data = self._handle(callback, params) + return self.response(code=status_code, data=data) + +@@ -488,6 +496,10 @@ class VulGenerateRepoTask(BaseResponse): + "task_id": "1" + } + """ ++ host_ids = [host["host_id"] for host in params["info"]] ++ if not callback.validate_hosts(host_id=list(set(host_ids))): ++ return self.response(code=PARAM_ERROR) ++ + status_code, data = self._handle(callback, params) + return self.response(code=status_code, data=data) + +@@ -836,6 +848,14 @@ class VulGenerateCveRollback(BaseResponse): + "task_id": "1" + } + """ ++ host_ids = [host["host_id"] for host in params["info"]] ++ if not callback.validate_hosts(host_id=list(set(host_ids))): ++ return self.response(code=PARAM_ERROR) ++ ++ cve_ids = [cve["cve_id"] for host in params["info"] for cve in host["cves"]] ++ if not callback.validate_cves(cve_id=list(set(cve_ids))): ++ return self.response(code=PARAM_ERROR) ++ + status_code, data = self._handle(callback, params) + return self.response(code=status_code, data=data) + +-- +Gitee diff --git a/0006-update-hotpatch-status-related-operation-support.patch b/0006-update-hotpatch-status-related-operation-support.patch new file mode 100644 index 0000000000000000000000000000000000000000..979268b41caaee9f0063f57db9805e4e188e84d3 --- /dev/null +++ b/0006-update-hotpatch-status-related-operation-support.patch @@ -0,0 +1,218 @@ +From 5d699207efd9164bef54b10e31c2082980e37f38 Mon Sep 17 00:00:00 2001 +From: rabbitali +Date: Thu, 1 Jun 2023 15:53:34 +0800 +Subject: [PATCH] update hot patch status related operation support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + apollo/database/proxy/cve.py | 20 ++++++++++++++++---- + apollo/database/proxy/host.py | 8 +++++--- + apollo/database/proxy/task.py | 7 +++++-- + apollo/database/table.py | 3 ++- + apollo/function/schema/cve.py | 2 ++ + apollo/function/schema/host.py | 1 + + apollo/function/schema/task.py | 4 +++- + 7 files changed, 34 insertions(+), 11 deletions(-) + +diff --git a/apollo/database/proxy/cve.py b/apollo/database/proxy/cve.py +index 9dc96ae..13a1ae6 100644 +--- a/apollo/database/proxy/cve.py ++++ b/apollo/database/proxy/cve.py +@@ -224,7 +224,10 @@ class CveMysqlProxy(MysqlProxy): + Returns: + set + """ +- filters = {CveHostAssociation.fixed == filter_dict.get("fixed", False)} ++ # when fixed does not have a value, the query data is not meaningful ++ # the default query is unfixed CVE information ++ fixed = filter_dict.get("fixed", False) ++ filters = {CveHostAssociation.fixed == fixed} + if not filter_dict: + return filters + +@@ -235,6 +238,12 @@ class CveMysqlProxy(MysqlProxy): + filters.add(Host.host_group_name.in_(filter_dict["host_group"])) + if filter_dict.get("repo"): + filters.add(Host.repo_name.in_(filter_dict["repo"])) ++ if filter_dict.get("hp_status"): ++ filters.add(CveHostAssociation.hp_status.in_(filter_dict["hp_status"])) ++ if filter_dict.get("hotpatch") and fixed is True: ++ filters.add(CveHostAssociation.fixed_by_hp.in_(filter_dict["hotpatch"])) ++ elif filter_dict.get("hotpatch") and fixed is False: ++ filters.add(CveHostAssociation.support_hp.in_(filter_dict["hotpatch"])) + return filters + + def _query_cve_hosts(self, username, cve_id, filters): +@@ -250,7 +259,8 @@ class CveMysqlProxy(MysqlProxy): + """ + cve_query = self.session.query(Host.host_id, Host.host_name, Host.host_ip, Host.host_group_name, + Host.repo_name, Host.last_scan, CveHostAssociation.support_hp, +- CveHostAssociation.fixed, CveHostAssociation.fixed_by_hp) \ ++ CveHostAssociation.fixed, CveHostAssociation.fixed_by_hp, ++ CveHostAssociation.hp_status ) \ + .join(CveHostAssociation, Host.host_id == CveHostAssociation.host_id) \ + .filter(Host.user == username, CveHostAssociation.cve_id == cve_id) \ + .filter(*filters) +@@ -268,7 +278,8 @@ class CveMysqlProxy(MysqlProxy): + "host_group": row.host_group_name, + "repo": row.repo_name, + "last_scan": row.last_scan, +- "hotpatch": row.fixed_by_hp if row.fixed is True else row.support_hp ++ "hotpatch": row.fixed_by_hp if row.fixed is True else row.support_hp, ++ "hp_status": row.hp_status + } + result.append(host_info) + return result +@@ -382,7 +393,8 @@ class CveMysqlProxy(MysqlProxy): + sqlalchemy.orm.query.Query + """ + cve_query = self.session.query(CveHostAssociation.cve_id, Host.host_id, Host.host_name, Host.host_ip, +- CveHostAssociation.support_hp, CveHostAssociation.fixed_by_hp, CveHostAssociation.fixed) \ ++ CveHostAssociation.support_hp, CveHostAssociation.fixed_by_hp, ++ CveHostAssociation.fixed) \ + .join(CveHostAssociation, Host.host_id == CveHostAssociation.host_id) \ + .filter(CveHostAssociation.cve_id.in_(cve_list)) \ + .filter(*filters) +diff --git a/apollo/database/proxy/host.py b/apollo/database/proxy/host.py +index a9431a9..3fdf97b 100644 +--- a/apollo/database/proxy/host.py ++++ b/apollo/database/proxy/host.py +@@ -525,7 +525,8 @@ class HostProxy(HostMysqlProxy, CveEsProxy): + "%" + filter_dict["cve_id"] + "%")) + if filter_dict.get("severity"): + filters.add(Cve.severity.in_(filter_dict["severity"])) +- ++ if filter_dict.get("hp_status"): ++ filters.add(CveHostAssociation.hp_status.in_(filter_dict["hp_status"])) + if filter_dict.get("hotpatch") and fixed is True: + filters.add(CveHostAssociation.fixed_by_hp.in_(filter_dict["hotpatch"])) + elif filter_dict.get("hotpatch") and fixed is False: +@@ -548,7 +549,7 @@ class HostProxy(HostMysqlProxy, CveEsProxy): + """ + host_cve_query = self.session.query(CveHostAssociation.cve_id, Cve.publish_time, Cve.severity, Cve.cvss_score, + CveHostAssociation.fixed, CveHostAssociation.support_hp, +- CveHostAssociation.fixed_by_hp) \ ++ CveHostAssociation.fixed_by_hp, CveHostAssociation.hp_status) \ + .select_from(CveHostAssociation) \ + .outerjoin(Cve, CveHostAssociation.cve_id == Cve.cve_id) \ + .outerjoin(Host, Host.host_id == CveHostAssociation.host_id) \ +@@ -577,7 +578,8 @@ class HostProxy(HostMysqlProxy, CveEsProxy): + "severity": row.severity, + "description": description_dict[cve_id] if description_dict.get(cve_id) else "", + "cvss_score": row.cvss_score, +- "hotpatch": row.fixed_by_hp if row.fixed is True else row.support_hp ++ "hotpatch": row.fixed_by_hp if row.fixed is True else row.support_hp, ++ "hp_status": row.hp_status + } + result.append(cve_info) + return result +diff --git a/apollo/database/proxy/task.py b/apollo/database/proxy/task.py +index e660f02..ac15485 100644 +--- a/apollo/database/proxy/task.py ++++ b/apollo/database/proxy/task.py +@@ -265,7 +265,8 @@ class TaskMysqlProxy(MysqlProxy): + "affected": True, + "fixed": True, + "fixed_by_hp": fix_cve.get("fixed_by_hp"), +- "support_hp": None ++ "support_hp": None, ++ "hp_status": fix_cve.get("hp_status") + } + + self.session.query(CveHostAssociation) \ +@@ -1397,6 +1398,7 @@ class TaskMysqlProxy(MysqlProxy): + "task_name": basic_task.task_name, + "task_type": basic_task.task_type, + "check_items": basic_task.check_items.split(',') if basic_task.check_items else [], ++ "accepted": basic_task.accepted, + "total_hosts": [], + "tasks": [] + } +@@ -1423,7 +1425,7 @@ class TaskMysqlProxy(MysqlProxy): + Returns: + sqlalchemy.orm.Query + """ +- task_query = self.session.query(Task.task_id, Task.task_name, Task.task_type, Task.check_items) \ ++ task_query = self.session.query(Task.task_id, Task.task_name, Task.task_type, Task.check_items, Task.accepted) \ + .filter(Task.task_id == task_id) + return task_query + +@@ -2606,6 +2608,7 @@ class TaskProxy(TaskMysqlProxy, TaskEsProxy): + "auto_reboot": True, + "create_time": 1, + "check_items": "", ++ "accepted": True + "info": [ + { + "cve_id": "cve1", +diff --git a/apollo/database/table.py b/apollo/database/table.py +index 251aaeb..33f4380 100644 +--- a/apollo/database/table.py ++++ b/apollo/database/table.py +@@ -37,7 +37,7 @@ class CveHostAssociation(Base, MyBase): + fixed = Column(Boolean) + support_hp = Column(Boolean, default=None) + fixed_by_hp = Column(Boolean, default=None) +- ++ hp_status = Column(String(20)) + + class CveAffectedPkgs(Base, MyBase): + """ +@@ -144,6 +144,7 @@ class Task(Base, MyBase): + create_time = Column(Integer) + host_num = Column(Integer) + check_items = Column(String(32)) ++ accepted = Column(Boolean, default=False) + + username = Column(String(40), ForeignKey('user.username')) + +diff --git a/apollo/function/schema/cve.py b/apollo/function/schema/cve.py +index 635e5eb..6584941 100644 +--- a/apollo/function/schema/cve.py ++++ b/apollo/function/schema/cve.py +@@ -61,6 +61,8 @@ class CveHostFilterSchema(Schema): + repo = fields.List(fields.String( + validate=lambda s: len(s) != 0), required=False) + fixed = fields.Boolean(required=True, validate=validate.OneOf([True, False])) ++ hotpatch = fields.List(fields.Boolean(validate=validate.OneOf([True, False])), required=False) ++ hp_status = fields.List(fields.String(validate=validate.OneOf(["ACCEPTED", "ACTIVED"])), required=False) + + + class GetCveHostsSchema(Schema): +diff --git a/apollo/function/schema/host.py b/apollo/function/schema/host.py +index 84dcfbe..a0cc4b5 100644 +--- a/apollo/function/schema/host.py ++++ b/apollo/function/schema/host.py +@@ -93,6 +93,7 @@ class HostCvesFilterSchema(Schema): + hotpatch = fields.List(fields.Boolean( + validate=validate.OneOf([True, False])), required=False) + fixed = fields.Boolean(validate=validate.OneOf([True, False])) ++ hp_status = fields.List(fields.String(validate=validate.OneOf(["ACCEPTED", "ACTIVED"])), required=False) + + + class GetHostCvesSchema(Schema): +diff --git a/apollo/function/schema/task.py b/apollo/function/schema/task.py +index 472fd53..415c2ca 100644 +--- a/apollo/function/schema/task.py ++++ b/apollo/function/schema/task.py +@@ -89,7 +89,8 @@ class GenerateCveTaskSchema(Schema): + task_name = fields.String(required=True, validate=lambda s: len(s) != 0) + description = fields.String( + required=True, validate=lambda s: 0 < len(s) <= 50) +- auto_reboot = fields.Boolean(required=False, default=True) ++ auto_reboot = fields.Boolean(required=False, default=False) ++ accepted = fields.Boolean(required=True, validate=validate.OneOf([True, False])) + check_items = fields.String(required=False, validate=lambda s: 0 < len(s) <= 32) + info = fields.List(fields.Nested(CveInfoDictSchema), required=True, validate=lambda s: len(s) > 0) + +@@ -226,6 +227,7 @@ class InstallPcakageInfoSchema(Schema): + class FixedCveInfoSchema(Schema): + cve_id = fields.String(required=True, validate=lambda s: len(s) != 0) + fixed_by_hp = fields.Boolean(required=True, validate=validate.OneOf([True, False])) ++ hp_status = fields.String(validate=validate.OneOf(["ACCEPTED", "ACTIVED"]), required=False) + + + class CveScanCallbackSchema(Schema): +-- diff --git a/aops-apollo.spec b/aops-apollo.spec index 25eb9015573991d58d8d5ce8f777fc3de1115b01..4489b61d841e653dc0e49385f76f2a2dc42a7703 100644 --- a/aops-apollo.spec +++ b/aops-apollo.spec @@ -1,11 +1,16 @@ Name: aops-apollo Version: v1.2.1 -Release: 2 +Release: 3 Summary: Cve management service, monitor machine vulnerabilities and provide fix functions. License: MulanPSL2 URL: https://gitee.com/openeuler/%{name} Source0: %{name}-%{version}.tar.gz Patch0001: 0001-fix-some-apis-which-has-filter-fault.patch +Patch0002: 0002-fix-bug-and-update-the-code-of-parsing.patch +Patch0003: 0003-fix-hotpatch-updateinfo-for-search-hotpatch-info.patch +Patch0004: 0004-add-dnf-full-repair.patch +Patch0005: 0005-fix-generate-task-is-not-verified-host-and-cve.patch +Patch0006: 0006-update-hotpatch-status-related-operation-support.patch BuildRequires: python3-setuptools Requires: aops-vulcanus >= v1.2.0 @@ -76,6 +81,13 @@ cp -r hotpatch %{buildroot}/%{python3_sitelib}/dnf-plugins/ %{python3_sitelib}/aops_apollo_tool/* %changelog +* Fri Jun 2 2023 gongzhengtang - v1.2.1-3 +- fix bug and update the code of parsing src.rpm +- fix hotpatch updateinfo for search hotpatch information +- add dnf full repair +- the host and cve were not verified when the generate task was fixed +- update hotpatch status related operation support + * Wed May 31 2023 wenxin - v1.2.1-2 - fix issue that can not be filtered by CVE ID when query cve rollbak task info - fix issue that can not be filtered by cve rollback when query task list