fix query fixed cves info error by dnf

(cherry picked from commit d2db1fecf66ba5615bb985a25a7b89b143373007)
This commit is contained in:
rabbitali 2023-09-20 16:24:17 +08:00 committed by openeuler-sync-bot
parent 838cab9015
commit 93a352fe86
7 changed files with 6 additions and 441 deletions

View File

@ -1,64 +0,0 @@
From d6be0a82ace5d07d31a91a628369f71534834441 Mon Sep 17 00:00:00 2001
From: rabbitali <shusheng.wen@outlook.com>
Date: Wed, 13 Sep 2023 10:58:16 +0800
Subject: [PATCH 1/1] update func named set_hotpatch_status_by_dnf_plugin
---
ceres/manages/vulnerability_manage.py | 30 ++++++++++++++++++++-------
1 file changed, 22 insertions(+), 8 deletions(-)
diff --git a/ceres/manages/vulnerability_manage.py b/ceres/manages/vulnerability_manage.py
index f45c1f2..ab4b41c 100644
--- a/ceres/manages/vulnerability_manage.py
+++ b/ceres/manages/vulnerability_manage.py
@@ -615,12 +615,11 @@ class VulnerabilityManage:
if not self.takeover and self.accepted:
try:
hotpatch_name = hotpatch_pkg.rsplit(".", 1)[0].split("-", 1)[1]
- status_set_result, log = self._set_hotpatch_status_by_dnf_plugin(hotpatch_name, "accept")
- if not status_set_result:
- stdout += "\n" + log
+ _, log = self._set_hotpatch_status_by_dnf_plugin(hotpatch_name, "accept")
+ stdout += f"\n\n{log}"
except IndexError as error:
LOGGER.error(error)
- stdout += "\n" + "hotpatch status set failed due to can't get correct hotpatch name!"
+ stdout += f"\n\nhotpatch status set failed due to can't get correct hotpatch name!"
return TaskExecuteRes.SUCCEED, stdout
@@ -637,12 +636,27 @@ class VulnerabilityManage:
Tuple[bool, str]
a tuple containing two elements (operation result, operation log).
"""
- code, stdout, stderr = execute_shell_command(f"dnf hotpatch --{operation} {hotpatch}")
- if code != CommandExitCode.SUCCEED:
+
+ # replace -ACC to /ACC or -SGL to /SGL
+ # Example: kernel-5.10.0-153.12.0.92.oe2203sp2-ACC-1-1 >> kernel-5.10.0-153.12.0.92.oe2203sp2/ACC-1-1
+ wait_to_remove_patch = re.sub(r'-(ACC|SGL)', r'/\1', hotpatch)
+ # Example of command execution result:
+ # Succeed:
+ # [root@openEuler ~]# dnf hotpatch --remove kernel-5.10.0-153.12.0.92.oe2203sp2/ACC-1-1
+ # Last metadata expiration check: 3:24:16 ago on Wed 13 Sep 2023 08:16:17 AM CST.
+ # Gonna remove this hot patch: kernel-5.10.0-153.12.0.92.oe2203sp2/ACC-1-1
+ # remove hot patch 'kernel-5.10.0-153.12.0.92.oe2203sp2/ACC-1-1' succeed
+ # Fail:
+ # [root@openEuler ~]# dnf hotpatch --accept kernel-5.10.0-153.12.0.92.oe2203sp2/ACC-1-1
+ # Last metadata expiration check: 3:25:24 ago on Wed 13 Sep 2023 08:16:17 AM CST.
+ # Gonna accept this hot patch: kernel-5.10.0-153.12.0.92.oe2203sp2/ACC-1-1
+ # accept hot patch 'kernel-5.10.0-153.12.0.92.oe2203sp2/ACC-1-1' failed, remain original status
+ code, stdout, stderr = execute_shell_command(f"dnf hotpatch --{operation} {wait_to_remove_patch}")
+ if code != CommandExitCode.SUCCEED or 'failed' in stdout:
LOGGER.error(f"hotpatch {hotpatch} set status failed!")
- return False, stderr
+ return False, stdout + stderr
- return True, stdout
+ return True, stdout + stderr
def cve_rollback(self, cves: List[dict]) -> Tuple[str, list]:
"""
--
2.33.0

View File

@ -1,155 +0,0 @@
From b0f71927a3bdb3096757ca8cdedb233d2b886a4d Mon Sep 17 00:00:00 2001
From: smjiao <smjiao@isoftstone.com>
Date: Thu, 7 Sep 2023 16:28:49 +0800
Subject: [PATCH] add file sync func
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
ceres/__main__.py | 6 ++++
ceres/function/command.py | 11 ++++++++
ceres/function/schema.py | 12 ++++++++
ceres/manages/sync_manage.py | 55 ++++++++++++++++++++++++++++++++++++
4 files changed, 84 insertions(+)
create mode 100644 ceres/manages/sync_manage.py
diff --git a/ceres/__main__.py b/ceres/__main__.py
index d1bbee3..a93ec49 100644
--- a/ceres/__main__.py
+++ b/ceres/__main__.py
@@ -17,6 +17,7 @@ from ceres.function.command import (
cve_command_manage,
plugin_command_manage,
register_on_manager,
+ sync_conf_manage,
)
from ceres.function.log import LOGGER
@@ -55,6 +56,11 @@ def main():
cve_group.add_argument("--rollback", type=str)
subparsers_cve.set_defaults(function=cve_command_manage)
+ subparsers_sync = subparsers.add_parser("sync", help='sync conf file')
+ sync_group = subparsers_sync.add_mutually_exclusive_group(required=True)
+ sync_group.add_argument("--conf", type=str)
+ subparsers_sync.set_defaults(function=sync_conf_manage)
+
args = parser.parse_args()
try:
args.function(args)
diff --git a/ceres/function/command.py b/ceres/function/command.py
index e4d367a..7324f23 100644
--- a/ceres/function/command.py
+++ b/ceres/function/command.py
@@ -25,11 +25,13 @@ from ceres.function.schema import (
HOST_INFO_SCHEMA,
REPO_SET_SCHEMA,
STRING_ARRAY,
+ CONF_SYNC_SCHEMA,
)
from ceres.function.status import SUCCESS, StatusCode
from ceres.function.util import convert_string_to_json, get_dict_from_file, plugin_status_judge, validate_data
from ceres.manages import plugin_manage
from ceres.manages.collect_manage import Collect
+from ceres.manages.sync_manage import SyncManage
from ceres.manages.vulnerability_manage import VulnerabilityManage
@@ -191,3 +193,12 @@ def cve_command_manage(args):
else:
print("Please check the input parameters!")
exit(1)
+
+
+def sync_conf_manage(args):
+ if args.conf:
+ config = convert_string_to_json(args.conf)
+ if not validate_data(config, CONF_SYNC_SCHEMA):
+ exit(1)
+ res = StatusCode.make_response_body(SyncManage.sync_contents_to_conf(config))
+ print(json.dumps(res))
diff --git a/ceres/function/schema.py b/ceres/function/schema.py
index ada35c3..794152d 100644
--- a/ceres/function/schema.py
+++ b/ceres/function/schema.py
@@ -113,3 +113,15 @@ CVE_ROLLBACK_SCHEMA = {
}
},
}
+
+CONF_SYNC_SCHEMA = {
+ "type": "object",
+ "required": [
+ "file_path",
+ "content"
+ ],
+ "properties": {
+ "file_path": {"type": "string", "minLength": 1},
+ "content": {"type": "string", "minLength": 1}
+ }
+}
diff --git a/ceres/manages/sync_manage.py b/ceres/manages/sync_manage.py
new file mode 100644
index 0000000..9be2a47
--- /dev/null
+++ b/ceres/manages/sync_manage.py
@@ -0,0 +1,55 @@
+#!/usr/bin/python3
+# ******************************************************************************
+# Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
+# licensed under the Mulan PSL v2.
+# You can use this software according to the terms and conditions of the Mulan PSL v2.
+# You may obtain a copy of Mulan PSL v2 at:
+# http://license.coscl.org.cn/MulanPSL2
+# THIS SOFTWARE IS PROVIDED ON AN 'AS IS' BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+# PURPOSE.
+# See the Mulan PSL v2 for more details.
+# ******************************************************************************/
+# Author: Lay
+# Description: default
+# Date: 2023/6/14 16:31
+import os
+from ceres.function.log import LOGGER
+from ceres.function.status import (
+ FILE_NOT_FOUND,
+ UNKNOWN_ERROR,
+ SUCCESS
+)
+
+
+class SyncManage:
+ """
+ Sync managed conf to the host
+ """
+
+ @staticmethod
+ def sync_contents_to_conf(config: dict) -> str:
+ """
+ Write conf into file
+ Args:
+ config(dict): filepath and content for file sync, only. eg:
+ {
+ "file_path" = "/tmp/test"
+ "content" = "contents for this file"
+ }
+ Returns:
+ str: status code
+ """
+ file_path = config.get('file_path')
+
+ contents = config.get('content')
+ lines = contents.split('\n')
+ try:
+ with open(file_path, "w", encoding="utf-8") as file:
+ for line in lines:
+ file.write(line + "\n")
+ except Exception as e:
+ LOGGER.error("write sync content to conf failed, with msg{}".format(e))
+ return UNKNOWN_ERROR
+
+ return SUCCESS
--
Gitee

View File

@ -1,153 +0,0 @@
From f947f2b46c52bc453858bf4e030ec9388c29b52d Mon Sep 17 00:00:00 2001
From: rabbitali <shusheng.wen@outlook.com>
Date: Mon, 18 Sep 2023 17:31:06 +0800
Subject: [PATCH 1/1] update method of querying fixed cves by dnf plugin
---
ceres/manages/vulnerability_manage.py | 80 ++++++++++++++++++++-------
1 file changed, 60 insertions(+), 20 deletions(-)
diff --git a/ceres/manages/vulnerability_manage.py b/ceres/manages/vulnerability_manage.py
index ab4b41c..ab10381 100644
--- a/ceres/manages/vulnerability_manage.py
+++ b/ceres/manages/vulnerability_manage.py
@@ -132,7 +132,7 @@ class VulnerabilityManage:
{
"check_items": items_check_log,
"unfixed_cves": self._query_unfixed_cves_by_dnf_plugin() or self._query_unfixed_cves_by_dnf(),
- "fixed_cves": self._query_fixed_cves(),
+ "fixed_cves": self._query_fixed_cves_by_dnf_plugin() or self._query_fixed_cves_by_dnf(),
}
)
return SUCCESS, cve_scan_result
@@ -339,7 +339,7 @@ class VulnerabilityManage:
return cve_info_list
- def _query_fixed_cves(self) -> list:
+ def _query_fixed_cves_by_dnf(self) -> list:
"""
parse the fixed kernel vulnerability info by dnf
@@ -348,7 +348,6 @@ class VulnerabilityManage:
list: cve info e.g
[
{"cve_id": "CVE-XXXX-XXXX","installed_rpm": "kernel-version-release.arch", "fix_way":"coldpatch"},
- {"cve_id": "CVE-XXXX-XXXX","installed_rpm": "xxxx", "fix_way": "hotpatch", "hp_status": "ACCEPTED"}
]
"""
@@ -380,17 +379,70 @@ class VulnerabilityManage:
fixed_cves.append(
{"cve_id": cve_id, "installed_rpm": self.installed_rpm_info.get(rpm_name), "fix_way": "coldpatch"}
)
- fixed_cves.extend(self._query_applied_hotpatch())
return fixed_cves
- def _query_applied_hotpatch(self) -> list:
+ def _query_fixed_cves_by_dnf_plugin(self) -> list:
"""
- parse kernel hotpatch info which has been applied by dnf hotpatch plugin (hotpatch)
+ parse the fixed kernel vulnerability info by dnf plugin
Return:
list: hotpatch info list. e.g
[{"cve_id": "CVE-XXXX-XXXX", "fix_way": "hotpatch", "hp_status": "ACCEPTED", "installed_rpm":"xxxx"}]
+ """
+ # Example of command execution result:
+ # Last metadata expiration check: 0:31:50 ago on Mon 07 Aug 2023 10:26:32 AM CST.
+ # CVE-2023-1981 Moderate/Sec. avahi-libs-0.8-9.oe1.x86_64 -
+ # CVE-2021-42574 Important/Sec. binutils-2.34-19.oe1.x86_64 -
+ # CVE-2023-1513 Important/Sec. kernel-4.19.90-2304.1.0.0196.oe1.x86_64 patch-kernel-4.19.90-2112...
+
+ code, stdout, stderr = execute_shell_command("dnf hot-updateinfo list cves --installed")
+ if code != CommandExitCode.SUCCEED:
+ LOGGER.error("query unfixed cve info failed by dnf!")
+ LOGGER.error(stderr)
+ return []
+
+ # Example of regex matching result:
+ # [
+ # ("CVE-2023-1513", "Important/Sec.", "kernel-4.19.90-2304.1.0.0196.oe1.x86_64", "patch-kernel-4.19.90-2112.."),
+ # ("CVE-2021-xxxx", "Important/Sec.", "-", "patch-redis-6.2.5-1-SGL_CVE_2023_1111_CVE_2023_1112-1-1.x86_64")
+ # ]
+ hotpatch_status = self._query_applied_hotpatch_status()
+ all_cve_info = re.findall(r"(CVE-\d{4}-\d+)\s+([\w+/.]+)\s+(kernel\S+|-)\s+(patch-kernel\S+|-)", stdout)
+
+ cve_info_fixed_by_coldpatch, cve_info_fixed_by_hotpatch, hotpatch_dic = [], [], defaultdict(str)
+ for cve_id, _, coldpatch, hotpatch in all_cve_info:
+ if hotpatch == "-":
+ cve_info_fixed_by_coldpatch.append(
+ {
+ "cve_id": cve_id,
+ "installed_rpm": self.installed_rpm_info.get(coldpatch.rsplit("-", 2)[0]),
+ "fix_way": "coldpatch",
+ }
+ )
+ else:
+ cve_info_fixed_by_hotpatch.append({"cve_id": cve_id, "fix_way": "hotpatch", "installed_rpm": hotpatch})
+
+ hotpatch_dic_key = hotpatch.rsplit("-", 2)[0]
+ if hotpatch_dic_key.endswith("ACC"):
+ hotpatch_dic[hotpatch_dic_key] = max(hotpatch, hotpatch_dic.get(hotpatch_dic_key, hotpatch))
+
+ for cve_info in cve_info_fixed_by_hotpatch:
+ hotpatch_dic_key = cve_info["installed_rpm"].rsplit("-", 2)[0]
+
+ if hotpatch_dic_key in hotpatch_dic:
+ cve_info["installed_rpm"] = hotpatch_dic[hotpatch_dic_key]
+ cve_info["hp_status"] = hotpatch_status.get(cve_info["installed_rpm"].rsplit(".", 1)[0], "")
+
+ return cve_info_fixed_by_coldpatch + cve_info_fixed_by_hotpatch
+
+ def _query_applied_hotpatch_status(self) -> Dict[str, str]:
+ """
+ query applied hotpatch with its status
+
+ Return:
+ dict: key is hotpatch name, value is its status. e.g {"patch-redis-6.2.5-1-ACC-1-3": "ACTIVED"}
+
"""
# Example of command execution result:
# Last metadata expiration check: 0:28:36 ago on Mon 07 Aug 2023 10:26:32 AM CST.
@@ -409,7 +461,7 @@ class VulnerabilityManage:
# CVE-2023-1112 redis-6.2.5-1/SGL_CVE_2023_1111_CVE_2023_1112-1-1/redis-cli NOT-APPLIED
# CVE-2023-1111 redis-6.2.5-1/SGL_CVE_2023_1111_CVE_2023_1112-1-1/redis-server NOT-APPLIED
# CVE-2023-1112 redis-6.2.5-1/SGL_CVE_2023_1111_CVE_2023_1112-1-1/redis-server NOT-APPLIED
- result = []
+ result = {}
code, stdout, stderr = execute_shell_command("dnf hotpatch --list cves")
if code != CommandExitCode.SUCCEED:
LOGGER.error("query applied hotpatch info failed!")
@@ -426,11 +478,6 @@ class VulnerabilityManage:
if not applied_hotpatch_info_list:
return result
- code, arch, _ = execute_shell_command("uname -m")
- if code != CommandExitCode.SUCCEED:
- LOGGER.debug("Failed to query host arch info!")
- arch = "unknown_arch"
-
record_key_set = set()
for cve_id, patch_name, hotpatch_status in applied_hotpatch_info_list:
rpm = patch_name.split("-", 1)[0]
@@ -445,14 +492,7 @@ class VulnerabilityManage:
and (hotpatch_status in ("ACTIVED", "ACCEPTED"))
and record_key not in record_key_set
):
- result.append(
- {
- "cve_id": cve_id,
- "installed_rpm": f"patch-{patch_name.rsplit('/',1)[0].replace('/','-')}.{arch}",
- "fix_way": "hotpatch",
- "hp_status": hotpatch_status,
- }
- )
+ result[f"patch-{patch_name.rsplit('/',1)[0].replace('/','-')}"] = hotpatch_status
record_key_set.add(record_key)
return result
--
2.33.1.windows.1

View File

@ -1,62 +0,0 @@
From 3e8e26b0b1b4b18ab45048069fc2f6a89b852802 Mon Sep 17 00:00:00 2001
From: rabbitali <shusheng.wen@outlook.com>
Date: Tue, 19 Sep 2023 20:02:44 +0800
Subject: [PATCH 1/1] update func about querying applied hotpatch info
---
ceres/manages/vulnerability_manage.py | 33 +++++++++++++++------------
1 file changed, 18 insertions(+), 15 deletions(-)
diff --git a/ceres/manages/vulnerability_manage.py b/ceres/manages/vulnerability_manage.py
index ab10381..1591d74 100644
--- a/ceres/manages/vulnerability_manage.py
+++ b/ceres/manages/vulnerability_manage.py
@@ -806,27 +806,30 @@ class VulnerabilityManage:
"CVE-XXXX-XXX": {"patch 1", "patch 2"}
}
"""
- # Run the dnf command to query the hotpatch list,e.g
- # Last metadata expiration check:
- # CVE id base-pkg/hotpatch status
- # CVE-1 A-1.1-1/ACC-1-1/binary_file1 ACTIVED
- # CVE-2 A-1.1-1/ACC-1-1/binary_file2 ACTIVED
- code, hotpatch_list_output, _ = execute_shell_command(f"dnf hotpatch --list cve")
+ code, stdout, _ = execute_shell_command(f"dnf hot-updateinfo list cves --installed|grep patch")
if code != CommandExitCode.SUCCEED:
LOGGER.error(f"Failed to hotpatch list cve.")
return None
- if not re.search("base-pkg/hotpatch", hotpatch_list_output):
+ all_cve_info = re.findall(r"(CVE-\d{4}-\d+)\s+([\w+/.]+)\s+(\S+|-)\s+(patch\S+)", stdout)
+ if not all_cve_info:
+ LOGGER.error(f"Failed to hotpatch list cve.")
return None
+
+ applied_hotpatch_info = {}
+ hotpatch_dic = {}
+ for cve_id, _, _, hotpatch in all_cve_info:
+ applied_hotpatch_info[cve_id] = hotpatch
+ hotpatch_dic_key = hotpatch.rsplit("-", 2)[0]
+ if hotpatch_dic_key.endswith("ACC"):
+ hotpatch_dic[hotpatch_dic_key] = max(hotpatch, hotpatch_dic.get(hotpatch_dic_key, hotpatch))
+
+ for cve_id, cmd_output_hotpatch in applied_hotpatch_info.items():
+ applied_hotpatch_info[cve_id] = hotpatch_dic.get(cmd_output_hotpatch.rsplit("-", 2)[0], cmd_output_hotpatch)
+
hotpatch_list = defaultdict(set)
- for hotpatch_info in [line for line in hotpatch_list_output.split(os.linesep) if line]:
- if not hotpatch_info.startswith("CVE"):
- continue
- cve_id, base_pkg, status = [info.strip() for info in hotpatch_info.split()]
- if status != "ACTIVED" and status != "ACCEPTED":
- continue
- hotpatch_name = "patch-%s-%s" % tuple(base_pkg.rsplit("/", 2)[:2])
- hotpatch_list[cve_id].add(hotpatch_name)
+ for cve_id, hotpatch in applied_hotpatch_info.items():
+ hotpatch_list[cve_id].add(hotpatch)
return hotpatch_list
--
2.33.0

Binary file not shown.

BIN
aops-ceres-v1.3.2.tar.gz Normal file

Binary file not shown.

View File

@ -1,14 +1,10 @@
Name: aops-ceres Name: aops-ceres
Version: v1.3.1 Version: v1.3.2
Release: 5 Release: 1
Summary: An agent which needs to be adopted in client, it managers some plugins, such as gala-gopher(kpi collection), fluentd(log collection) and so on. Summary: An agent which needs to be adopted in client, it managers some plugins, such as gala-gopher(kpi collection), fluentd(log collection) and so on.
License: MulanPSL2 License: MulanPSL2
URL: https://gitee.com/openeuler/%{name} URL: https://gitee.com/openeuler/%{name}
Source0: %{name}-%{version}.tar.gz Source0: %{name}-%{version}.tar.gz
Patch0001: 0001-update-func-named-set-hotpatch-status-by-dnf-plugin.patch
Patch0002: 0002-add-file-sync-func.patch
Patch0003: 0003-update-method-of-querying-fixed-cves-by-dnf-plugin.patch
Patch0004: 0004-update-func-about-querying-applied-hotpatch-info.patch
BuildRequires: python3-setuptools BuildRequires: python3-setuptools
@ -23,7 +19,7 @@ An agent which needs to be adopted in client, it managers some plugins, such as
%prep %prep
%autosetup -n %{name}-%{version} -p1 %autosetup -n %{name}-%{version}
# build for aops-ceres # build for aops-ceres
@ -44,6 +40,9 @@ An agent which needs to be adopted in client, it managers some plugins, such as
%changelog %changelog
* Wed Sep 20 2023 wenxin<shusheng.wen@outlook.com> - v1.3.2-1
- fix query fixed cves info error by dnf
* Tue Sep 19 2023 wenxin<shusheng.wen@outlook.com> - v1.3.1-5 * Tue Sep 19 2023 wenxin<shusheng.wen@outlook.com> - v1.3.1-5
- update func about querying applied hotpatch info - update func about querying applied hotpatch info