diff --git a/0001-add-file-sync-func.patch b/0001-add-file-sync-func.patch deleted file mode 100644 index a5d1b6abf548110e716082e93327983945eee224..0000000000000000000000000000000000000000 --- a/0001-add-file-sync-func.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 0e2ad3cc141390e26d7a20bccf5ccc0660f7c172 Mon Sep 17 00:00:00 2001 -From: smjiao -Date: Thu, 7 Sep 2023 16:24:42 +0800 -Subject: [PATCH] add file sync func -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - ---- - zeus/conf/constant.py | 2 ++ - zeus/config_manager/view.py | 45 ++++++++++++++++++++++++++++++++-- - zeus/function/verify/config.py | 9 +++++++ - zeus/url.py | 6 ++++- - 4 files changed, 59 insertions(+), 3 deletions(-) - -diff --git a/zeus/conf/constant.py b/zeus/conf/constant.py -index 2fbf1be..3175c65 100644 ---- a/zeus/conf/constant.py -+++ b/zeus/conf/constant.py -@@ -33,6 +33,7 @@ CERES_CVE_REPO_SET = "aops-ceres apollo --set-repo '%s'" - CERES_CVE_SCAN = "aops-ceres apollo --scan '%s'" - CERES_CVE_FIX = "aops-ceres apollo --fix '%s'" - CERES_CVE_ROLLBACK = "aops-ceres apollo --rollback '%s'" -+CERES_SYNC_CONF = "aops-ceres sync --conf '%s'" - - # zeus route - ADD_HOST = "/manage/host/add" -@@ -54,6 +55,7 @@ DELETE_GROUP = "/manage/host/group/delete" - GET_GROUP = "/manage/host/group/get" - - COLLECT_CONFIG = '/manage/config/collect' -+SYNC_CONFIG = '/manage/config/sync' - - USER_LOGIN = "/manage/account/login" - LOGOUT = "/manage/account/logout" -diff --git a/zeus/config_manager/view.py b/zeus/config_manager/view.py -index cd83e35..baeef7e 100644 ---- a/zeus/config_manager/view.py -+++ b/zeus/config_manager/view.py -@@ -21,10 +21,11 @@ from typing import List, Dict - from vulcanus.multi_thread_handler import MultiThreadHandler - from vulcanus.restful.resp import state - from vulcanus.restful.response import BaseResponse --from zeus.conf.constant import CERES_COLLECT_FILE -+from zeus.conf import configuration -+from zeus.conf.constant import CERES_COLLECT_FILE, CERES_SYNC_CONF - from zeus.database.proxy.host import HostProxy - from zeus.function.model import ClientConnectArgs --from zeus.function.verify.config import CollectConfigSchema -+from zeus.function.verify.config import CollectConfigSchema, SyncConfigSchema - from zeus.host_manager.ssh import execute_command_and_parse_its_result - - -@@ -218,3 +219,43 @@ class CollectConfig(BaseResponse): - return self.response( - state.SUCCEED, None, self.generate_target_data_format(multi_thread.get_result(), host_id_with_config_file) - ) -+ -+ -+class SyncConfig(BaseResponse): -+ -+ @staticmethod -+ def sync_config_content(host_info: Dict, sync_config_info: Dict): -+ command = CERES_SYNC_CONF % json.dumps(sync_config_info) -+ status, content = execute_command_and_parse_its_result( -+ ClientConnectArgs(host_info.get("host_ip"), host_info.get("ssh_port"), -+ host_info.get("ssh_user"), host_info.get("pkey")), command) -+ return status -+ -+ @BaseResponse.handle(schema=SyncConfigSchema, token=False) -+ def put(self, **params): -+ -+ sync_config_info = dict() -+ sync_config_info['file_path'] = params.get('file_path') -+ sync_config_info['content'] = params.get('content') -+ -+ sync_result = { -+ "file_path": sync_config_info['file_path'], -+ "sync_result": False -+ } -+ -+ # Query host address from database -+ proxy = HostProxy(configuration) -+ if not proxy.connect(): -+ return self.response(code=state.DATABASE_CONNECT_ERROR, data={"resp": sync_result}) -+ -+ status, host_list = proxy.get_host_info( -+ {"username": "admin", "host_list": [params.get('host_id')]}, True) -+ if status != state.SUCCEED or len(host_list) == 1: -+ return self.response(code=status, data={"resp": sync_result}) -+ -+ host_info = host_list[0] -+ status = self.sync_config_content(host_info, sync_config_info) -+ if status == state.SUCCEED: -+ sync_result['sync_result'] = True -+ return self.response(code=state.SUCCEED, data={"resp": sync_result}) -+ return self.response(code=state.UNKNOWN_ERROR, data={"resp": sync_result}) -diff --git a/zeus/function/verify/config.py b/zeus/function/verify/config.py -index 230b65d..6e5bf64 100644 ---- a/zeus/function/verify/config.py -+++ b/zeus/function/verify/config.py -@@ -36,3 +36,12 @@ class CollectConfigSchema(Schema): - """ - - infos = fields.List(fields.Nested(ConfigSchema(), required=True), required=True, validate=lambda s: len(s) > 0) -+ -+ -+class SyncConfigSchema(Schema): -+ """ -+ validators for SyncConfigSchema -+ """ -+ host_id = fields.Integer(required=True, validate=lambda s: s > 0) -+ file_path = fields.String(required=True, validate=lambda s: len(s) > 0) -+ content = fields.String(required=True, validate=lambda s: len(s) > 0) -diff --git a/zeus/url.py b/zeus/url.py -index e0cf1de..597dcc7 100644 ---- a/zeus/url.py -+++ b/zeus/url.py -@@ -49,6 +49,7 @@ from zeus.conf.constant import ( - REFRESH_TOKEN, - UPDATE_HOST, - USER_LOGIN, -+ SYNC_CONFIG, - ) - from zeus.config_manager import view as config_view - from zeus.host_manager import view as host_view -@@ -83,7 +84,10 @@ SPECIFIC_URLS = { - (host_view.DeleteHostGroup, DELETE_GROUP), - (host_view.GetHostGroup, GET_GROUP), - ], -- "CONFIG_URLS": [(config_view.CollectConfig, COLLECT_CONFIG)], -+ "CONFIG_URLS": [ -+ (config_view.CollectConfig, COLLECT_CONFIG), -+ (config_view.SyncConfig, SYNC_CONFIG) -+ ], - 'AGENT_URLS': [ - (agent_view.AgentPluginInfo, AGENT_PLUGIN_INFO), - (agent_view.SetAgentPluginStatus, AGENT_PLUGIN_SET), --- -Gitee - diff --git a/0001-fix-metric-proxy-init-failed-error.patch b/0001-fix-metric-proxy-init-failed-error.patch new file mode 100644 index 0000000000000000000000000000000000000000..ca84d256b08f50312c9910ecd4ba85a97a7a5661 --- /dev/null +++ b/0001-fix-metric-proxy-init-failed-error.patch @@ -0,0 +1,46 @@ +From 833a9d721bed5b3e64ea49710a477a52b74c5255 Mon Sep 17 00:00:00 2001 +From: zhangdaolong +Date: Thu, 12 Oct 2023 14:28:06 +0800 +Subject: [PATCH 1/1] fix metric proxy init failed error +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + zeus/database/proxy/metric.py | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/zeus/database/proxy/metric.py b/zeus/database/proxy/metric.py +index e899e26..5fa75e9 100644 +--- a/zeus/database/proxy/metric.py ++++ b/zeus/database/proxy/metric.py +@@ -21,6 +21,7 @@ from prometheus_api_client import PrometheusApiClientException + from vulcanus.database.proxy import PromDbProxy + from vulcanus.log.log import LOGGER + from vulcanus.restful.resp.state import SUCCEED, DATABASE_QUERY_ERROR, NO_DATA, PARAM_ERROR, PARTIAL_SUCCEED ++from zeus.conf import configuration + + + class MetricProxy(PromDbProxy): +@@ -28,16 +29,15 @@ class MetricProxy(PromDbProxy): + Proxy of prometheus time series database + """ + +- def __init__(self, configuration, host=None, port=None): ++ def __init__(self, host=None, port=None): + """ + Init MetricProxy + + Args: +- configuration (Config) + host (str) + port (int) + """ +- PromDbProxy.__init__(self, configuration, host, port) ++ PromDbProxy.__init__(self, host, port) + self.default_instance_port = configuration.agent.get('DEFAULT_INSTANCE_PORT') or 9100 + self.query_range_step = configuration.prometheus.get('QUERY_RANGE_STEP') or "15s" + +-- +2.33.0 + diff --git a/0002-add-key-authentication-for-add-host-api.patch b/0002-add-key-authentication-for-add-host-api.patch new file mode 100644 index 0000000000000000000000000000000000000000..8a3c9e166e9936d4616345c3720d024990c7c2f2 --- /dev/null +++ b/0002-add-key-authentication-for-add-host-api.patch @@ -0,0 +1,298 @@ +From 7a8164696bb913a75cf79cf6b57c9973530efefa Mon Sep 17 00:00:00 2001 +From: rabbitali +Date: Sun, 15 Oct 2023 16:37:55 +0800 +Subject: [PATCH 1/1] add a way about key authentication for add host api +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + database/zeus.sql | 2 +- + zeus/conf/constant.py | 6 +-- + zeus/database/table.py | 2 +- + zeus/function/verify/host.py | 4 +- + zeus/host_manager/view.py | 99 ++++++++++++++++++++++++++++-------- + 5 files changed, 85 insertions(+), 28 deletions(-) + +diff --git a/database/zeus.sql b/database/zeus.sql +index 3dc9f3c..7db734e 100644 +--- a/database/zeus.sql ++++ b/database/zeus.sql +@@ -42,7 +42,7 @@ CREATE TABLE IF NOT EXISTS `host` ( + `os_version` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL, + `ssh_user` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL, + `ssh_port` int(11) NULL DEFAULT NULL, +- `pkey` varchar(2048) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL, ++ `pkey` varchar(4096) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL, + `status` int(11) NULL DEFAULT NULL, + `user` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL, + `host_group_id` int(11) NULL DEFAULT NULL, +diff --git a/zeus/conf/constant.py b/zeus/conf/constant.py +index 3175c65..bf8792a 100644 +--- a/zeus/conf/constant.py ++++ b/zeus/conf/constant.py +@@ -90,9 +90,9 @@ CHECK_IDENTIFY_SCENE = "/check/scene/identify" + CHECK_WORKFLOW_HOST_EXIST = '/check/workflow/host/exist' + + # host template file content +-HOST_TEMPLATE_FILE_CONTENT = """host_ip,ssh_port,ssh_user,password,host_name,host_group_name,management +-test_ip_1,22,root,password,test_host,test_host_group,False +-test_ip_2,22,root,password,test_host,test_host_group,False ++HOST_TEMPLATE_FILE_CONTENT = """host_ip,ssh_port,ssh_user,password,ssh_pkey,host_name,host_group_name,management ++test_ip_1,22,root,password,ssh_pkey,test_host,test_host_group,False ++test_ip_2,22,root,password,ssh_pkey,test_host,test_host_group,False + """ + + +diff --git a/zeus/database/table.py b/zeus/database/table.py +index 9596492..265eb45 100644 +--- a/zeus/database/table.py ++++ b/zeus/database/table.py +@@ -59,7 +59,7 @@ class Host(Base, MyBase): # pylint: disable=R0903 + os_version = Column(String(40)) + ssh_user = Column(String(40), default="root") + ssh_port = Column(Integer(), default=22) +- pkey = Column(String(2048)) ++ pkey = Column(String(4096)) + status = Column(Integer(), default=2) + + user = Column(String(40), ForeignKey('user.username')) +diff --git a/zeus/function/verify/host.py b/zeus/function/verify/host.py +index b054d62..d09eedd 100644 +--- a/zeus/function/verify/host.py ++++ b/zeus/function/verify/host.py +@@ -103,11 +103,12 @@ class AddHostSchema(Schema): + """ + + ssh_user = fields.String(required=True, validate=lambda s: len(s) > 0) +- password = fields.String(required=True, validate=lambda s: len(s) > 0) ++ password = fields.String(required=True, allow_none=True, validate=lambda s: len(s) >= 0) + host_name = fields.String( + required=True, validate=[validate.Length(min=1, max=50), ValidateRules.space_character_check] + ) + host_ip = fields.IP(required=True) ++ ssh_pkey = fields.String(required=True, allow_none=True, validate=lambda s: 4096 >= len(s) >= 0) + ssh_port = fields.Integer(required=True, validate=lambda s: 65535 >= s > 0) + host_group_name = fields.String(required=True, validate=lambda s: len(s) > 0) + management = fields.Boolean(required=True) +@@ -133,3 +134,4 @@ class UpdateHostSchema(Schema): + host_name = fields.String(required=False, validate=lambda s: len(s) > 0) + host_group_name = fields.String(required=False, validate=lambda s: len(s) > 0) + management = fields.Boolean(required=False) ++ ssh_pkey = fields.String(required=False, validate=lambda s: 4096 >= len(s) >= 0) +diff --git a/zeus/host_manager/view.py b/zeus/host_manager/view.py +index 768d2cd..95e1434 100644 +--- a/zeus/host_manager/view.py ++++ b/zeus/host_manager/view.py +@@ -16,12 +16,13 @@ Author: + Description: Restful APIs for host + """ + import json +-from io import BytesIO ++from io import BytesIO, StringIO + from typing import Iterable, List, Tuple, Union + import socket + + import gevent + import paramiko ++from paramiko.ssh_exception import SSHException + from flask import request, send_file + from marshmallow import Schema + from marshmallow.fields import Boolean +@@ -333,7 +334,8 @@ class AddHost(BaseResponse): + "host_ip":"127.0.0.1", + "ssh_port":"22", + "management":false, +- "username": "admin" ++ "username": "admin", ++ "ssh_pkey": "RSA key" + } + + Returns: +@@ -363,6 +365,7 @@ class AddHost(BaseResponse): + "ssh_port": host_info.get("ssh_port"), + "user": host_info.get("username"), + "management": host_info.get("management"), ++ "pkey": host_info.get("ssh_pkey"), + } + ) + if host in hosts: +@@ -384,7 +387,8 @@ class AddHost(BaseResponse): + "host_ip":"127.0.0.1", + "ssh_port":"22", + "management":false, +- "username": "admin" ++ "username": "admin", ++ "ssh_pkey": "RSA key" + } + + Returns: +@@ -396,15 +400,55 @@ class AddHost(BaseResponse): + if status != state.SUCCEED: + return self.response(code=status) + +- status, private_key = save_ssh_public_key_to_client( +- params.get('host_ip'), params.get('ssh_port'), params.get('ssh_user'), params.get('password') +- ) +- if status == state.SUCCEED: +- host.pkey = private_key +- host.status = HostStatus.ONLINE ++ if params.get("ssh_pkey"): ++ status = verify_ssh_login_info( ++ ClientConnectArgs( ++ params.get("host_ip"), params.get("ssh_port"), params.get("ssh_user"), params.get("ssh_pkey") ++ ) ++ ) ++ host.status = HostStatus.ONLINE if status == state.SUCCEED else HostStatus.UNESTABLISHED ++ else: ++ status, private_key = save_ssh_public_key_to_client( ++ params.get('host_ip'), params.get('ssh_port'), params.get('ssh_user'), params.get('password') ++ ) ++ if status == state.SUCCEED: ++ host.pkey = private_key ++ host.status = HostStatus.ONLINE + return self.response(code=self.proxy.add_host(host)) + + ++def verify_ssh_login_info(ssh_login_info: ClientConnectArgs) -> str: ++ """ ++ Verify that the ssh login information is correct ++ ++ Args: ++ ssh_login_info(ClientConnectArgs): e.g ++ ClientConnectArgs(host_ip='127.0.0.1', ssh_port=22, ssh_user='root', pkey=RSAKey string) ++ ++ Returns: ++ status code ++ """ ++ try: ++ client = SSH( ++ ip=ssh_login_info.host_ip, ++ username=ssh_login_info.ssh_user, ++ port=ssh_login_info.ssh_port, ++ pkey=paramiko.RSAKey.from_private_key(StringIO(ssh_login_info.pkey)), ++ ) ++ client.close() ++ except socket.error as error: ++ LOGGER.error(error) ++ return state.SSH_CONNECTION_ERROR ++ except SSHException as error: ++ LOGGER.error(error) ++ return state.SSH_AUTHENTICATION_ERROR ++ except Exception as error: ++ LOGGER.error(error) ++ return state.SSH_CONNECTION_ERROR ++ ++ return state.SUCCEED ++ ++ + def save_ssh_public_key_to_client(ip: str, port: int, username: str, password: str) -> tuple: + """ + generate RSA key pair,save public key to the target host machine +@@ -465,7 +509,7 @@ class GetHostTemplateFile(BaseResponse): + file = BytesIO() + file.write(HOST_TEMPLATE_FILE_CONTENT.encode('utf-8')) + file.seek(0) +- response = send_file(file,mimetype="application/octet-stream") ++ response = send_file(file, mimetype="application/octet-stream") + response.headers['Content-Disposition'] = 'attachment; filename=template.csv' + return response + +@@ -574,6 +618,7 @@ class AddHostBatch(BaseResponse): + continue + + password = host_info.pop("password") ++ pkey = host_info.pop("ssh_pkey", None) + host_info.update( + {"host_group_id": group_id_info.get(host_info['host_group_name']), "user": data["username"]} + ) +@@ -585,7 +630,7 @@ class AddHostBatch(BaseResponse): + ) + continue + +- valid_host.append((host, password)) ++ valid_host.append((host, password, pkey)) + return valid_host + + def save_key_to_client(self, host_connect_infos: List[tuple]) -> list: +@@ -598,8 +643,8 @@ class AddHostBatch(BaseResponse): + Returns: + host object list + """ +- # 30 connections are created at a time. +- tasks = [host_connect_infos[index : index + 30] for index in range(0, len(host_connect_infos), 30)] ++ # 100 connections are created at a time. ++ tasks = [host_connect_infos[index : index + 100] for index in range(0, len(host_connect_infos), 100)] + result = [] + + for task in tasks: +@@ -612,18 +657,23 @@ class AddHostBatch(BaseResponse): + return result + + @staticmethod +- def update_rsa_key_to_host(host: Host, password: str) -> Host: ++ def update_rsa_key_to_host(host: Host, password: str = None, pkey: str = None) -> Host: + """ + save ssh public key to client and update its private key in host + + Args: + host(Host): host object + password(str): password for ssh login ++ pkey(str): rsa key for ssh login + + Returns: + host object + """ +- status, pkey = save_ssh_public_key_to_client(host.host_ip, host.ssh_port, host.ssh_user, password) ++ if pkey: ++ status = verify_ssh_login_info(ClientConnectArgs(host.host_ip, host.ssh_port, host.ssh_user, pkey)) ++ else: ++ status, pkey = save_ssh_public_key_to_client(host.host_ip, host.ssh_port, host.ssh_user, password) ++ + if status == state.SUCCEED: + host.status = HostStatus.ONLINE + host.pkey = pkey +@@ -654,7 +704,7 @@ class AddHostBatch(BaseResponse): + new_host.update(update_info) + self.add_result.append(new_host) + else: +- for host, _ in hosts: ++ for host, _, _ in hosts: + new_host = { + "host_ip": host.host_ip, + "ssh_port": host.ssh_port, +@@ -789,9 +839,14 @@ class UpdateHost(BaseResponse): + """ + ssh_user = params.get("ssh_user") or self.host.ssh_user + ssh_port = params.get("ssh_port") or self.host.ssh_port +- status, private_key = save_ssh_public_key_to_client( +- self.host.host_ip, ssh_port, ssh_user, params.pop("password", None) +- ) ++ private_key = params.pop("ssh_pkey", None) ++ if private_key: ++ status = verify_ssh_login_info(ClientConnectArgs(self.host.host_ip, ssh_port, ssh_user, private_key)) ++ else: ++ status, private_key = save_ssh_public_key_to_client( ++ self.host.host_ip, ssh_port, ssh_user, params.pop("password", None) ++ ) ++ + params.update( + { + "ssh_user": ssh_user, +@@ -876,10 +931,10 @@ class UpdateHost(BaseResponse): + return self.response(code=state.PARAM_ERROR, message="there is a duplicate host ssh address in database!") + + if params.get("ssh_user") or params.get("ssh_port"): +- if not params.get("password"): +- return self.response(code=state.PARAM_ERROR, message="please update password") ++ if not params.get("password") or not params.get("ssh_pkey"): ++ return self.response(code=state.PARAM_ERROR, message="please update password or authentication key.") + self._save_ssh_key(params) +- elif params.get("password"): ++ elif params.get("password") or params.get("ssh_pkey"): + self._save_ssh_key(params) + + return self.response(callback.update_host_info(params.pop("host_id"), params)) +-- +2.33.0 + diff --git a/0002-update-callback-request-headers.patch b/0002-update-callback-request-headers.patch deleted file mode 100644 index b73eacad00bb12804535cede8129f1ca5f4cb84b..0000000000000000000000000000000000000000 --- a/0002-update-callback-request-headers.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 51be015c84619925873ff377a72827b7c9770632 Mon Sep 17 00:00:00 2001 -From: rabbitali -Date: Mon, 18 Sep 2023 12:18:52 +0800 -Subject: [PATCH 1/1] update callback request headers -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - ---- - zeus/vulnerability_manage/view.py | 14 +++++--------- - 1 file changed, 5 insertions(+), 9 deletions(-) - -diff --git a/zeus/vulnerability_manage/view.py b/zeus/vulnerability_manage/view.py -index 1bfed63..b5360e2 100644 ---- a/zeus/vulnerability_manage/view.py -+++ b/zeus/vulnerability_manage/view.py -@@ -119,7 +119,7 @@ def generate_tasks(tasks: list, host_infos: dict, **kwargs: dict) -> list: - - class BaseExcuteTask: - def __init__(self) -> None: -- self._header = {'content-type': 'application/json', 'access_token': request.headers.get('access_token')} -+ self._header = {"exempt_authentication": configuration.individuation.get("EXEMPT_AUTHENTICATION")} - - - class ExecuteRepoSetTask(BaseResponse, BaseExcuteTask): -@@ -234,7 +234,7 @@ class ExecuteRepoSetTask(BaseResponse, BaseExcuteTask): - return self.response(code=status_code) - - self._callback_url = params.get('callback') -- self._header = {'content-type': 'application/json', 'access_token': request.headers.get('access_token')} -+ self._header["local_account"] = params.get("username") - self._task_id = params.get("task_id") - self._task_name = params.get("task_name") - self._task_type = params.get("task_type") -@@ -337,13 +337,7 @@ class ExecuteCveScanTask(BaseResponse, BaseExcuteTask): - return self.response(code=status_code) - # parse args - self._callback_url = params.get('callback') -- if params.get("timed"): -- self._header.update( -- { -- "exempt_authentication": configuration.individuation.get("EXEMPT_AUTHENTICATION"), -- "local_account": params.get("username"), -- } -- ) -+ self._header["local_account"] = params.get("username") - self._task_id = params.get("task_id") - self._check_items = params.get('check_items') - # Execute task -@@ -465,6 +459,7 @@ class ExecuteCveFixTask(BaseResponse, BaseExcuteTask): - self._task_id = params.get("task_id") - self._task_name = params.get("task_name") - self._task_type = params.get("task_type") -+ self._header["local_account"] = params.get("username") - self._accepted = params.get('accepted') - self._takeover = params.get('takeover') - self._check_items = params.get('check_items') -@@ -582,6 +577,7 @@ class ExecuteCveRollbackTask(BaseResponse, BaseExcuteTask): - # Generate tasks - self._callback_url = params.get('callback') - self._task_id = params.get("task_id") -+ self._header["local_account"] = params.get("username") - self._task_name = params.get("task_name") - self._task_type = params.get("task_type") - --- -2.33.1.windows.1 - diff --git a/0003-fix-bash-file-sync-error.patch b/0003-fix-bash-file-sync-error.patch deleted file mode 100644 index 7a6837404fcbccba14f955d6a06b24d3a5740caf..0000000000000000000000000000000000000000 --- a/0003-fix-bash-file-sync-error.patch +++ /dev/null @@ -1,220 +0,0 @@ -From 80272352b3067ebb2cb3011cfbeeef5e9d464fa6 Mon Sep 17 00:00:00 2001 -From: smjiao -Date: Mon, 18 Sep 2023 20:37:50 +0800 -Subject: [PATCH 1/1] fix bash file sync error -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - ---- - zeus/config_manager/view.py | 48 ++++++++++++++++++++----- - zeus/host_manager/ssh.py | 72 +++++++++++++++++++++++++++++++------ - 2 files changed, 102 insertions(+), 18 deletions(-) - -diff --git a/zeus/config_manager/view.py b/zeus/config_manager/view.py -index baeef7e..6779153 100644 ---- a/zeus/config_manager/view.py -+++ b/zeus/config_manager/view.py -@@ -16,6 +16,7 @@ Author: - Description: Restful APIs for host - """ - import json -+import os - from typing import List, Dict - - from vulcanus.multi_thread_handler import MultiThreadHandler -@@ -26,7 +27,7 @@ from zeus.conf.constant import CERES_COLLECT_FILE, CERES_SYNC_CONF - from zeus.database.proxy.host import HostProxy - from zeus.function.model import ClientConnectArgs - from zeus.function.verify.config import CollectConfigSchema, SyncConfigSchema --from zeus.host_manager.ssh import execute_command_and_parse_its_result -+from zeus.host_manager.ssh import execute_command_and_parse_its_result, execute_command_sftp_result - - - class CollectConfig(BaseResponse): -@@ -222,15 +223,46 @@ class CollectConfig(BaseResponse): - - - class SyncConfig(BaseResponse): -- - @staticmethod -- def sync_config_content(host_info: Dict, sync_config_info: Dict): -- command = CERES_SYNC_CONF % json.dumps(sync_config_info) -- status, content = execute_command_and_parse_its_result( -+ def sync_config_by_execute_command_sftp(host_info: Dict, sync_config_info: Dict, local_path: str, -+ remote_path: str): -+ content = sync_config_info.get("content") -+ with open(local_path, "w", encoding="UTF-8") as f: -+ f.write(content) -+ status = execute_command_sftp_result( - ClientConnectArgs(host_info.get("host_ip"), host_info.get("ssh_port"), -- host_info.get("ssh_user"), host_info.get("pkey")), command) -+ host_info.get("ssh_user"), host_info.get("pkey")), local_path, remote_path) - return status - -+ @staticmethod -+ def sync_config_content(host_info: Dict, sync_config_info: Dict): -+ join_path = "/tmp" -+ if sync_config_info.get("file_path") == "/etc/profile": -+ local_path = os.path.join(join_path, "profile") -+ remote_path = "/etc/profile" -+ status = SyncConfig.sync_config_by_execute_command_sftp(host_info, sync_config_info, local_path, -+ remote_path) -+ return status -+ elif sync_config_info.get("file_path") == "/etc/rc.local": -+ local_path = os.path.join(join_path, "rc.local") -+ remote_path = "/etc/rc.local" -+ status = SyncConfig.sync_config_by_execute_command_sftp(host_info, sync_config_info, local_path, -+ remote_path) -+ return status -+ elif sync_config_info.get("file_path") == "/etc/bashrc": -+ local_path = os.path.join(join_path, "bashrc") -+ remote_path = "/etc/bashrc" -+ status = SyncConfig.sync_config_by_execute_command_sftp(host_info, sync_config_info, local_path, -+ remote_path) -+ return status -+ else: -+ command = CERES_SYNC_CONF % json.dumps(sync_config_info) -+ -+ status, content = execute_command_and_parse_its_result( -+ ClientConnectArgs(host_info.get("host_ip"), host_info.get("ssh_port"), -+ host_info.get("ssh_user"), host_info.get("pkey")), command) -+ return status -+ - @BaseResponse.handle(schema=SyncConfigSchema, token=False) - def put(self, **params): - -@@ -244,13 +276,13 @@ class SyncConfig(BaseResponse): - } - - # Query host address from database -- proxy = HostProxy(configuration) -+ proxy = HostProxy() - if not proxy.connect(): - return self.response(code=state.DATABASE_CONNECT_ERROR, data={"resp": sync_result}) - - status, host_list = proxy.get_host_info( - {"username": "admin", "host_list": [params.get('host_id')]}, True) -- if status != state.SUCCEED or len(host_list) == 1: -+ if status != state.SUCCEED: - return self.response(code=status, data={"resp": sync_result}) - - host_info = host_list[0] -diff --git a/zeus/host_manager/ssh.py b/zeus/host_manager/ssh.py -index 4c3a259..11f6383 100644 ---- a/zeus/host_manager/ssh.py -+++ b/zeus/host_manager/ssh.py -@@ -15,6 +15,7 @@ from io import StringIO - from typing import Tuple - - import paramiko -+from paramiko import sftp - - from vulcanus.log.log import LOGGER - from vulcanus.restful.resp import state -@@ -57,7 +58,13 @@ class SSH: - """ - - def __init__(self, ip, username, port, password=None, pkey=None): -- self._client_args = {'hostname': ip, 'username': username, 'port': port, "password": password, "pkey": pkey} -+ self._client_args = { -+ 'hostname': ip, -+ 'username': username, -+ 'port': port, -+ "password": password, -+ "pkey": pkey -+ } - self._client = self.client() - - def client(self): -@@ -71,15 +78,15 @@ class SSH: - - def execute_command(self, command: str, timeout: float = None) -> tuple: - """ -- create a ssh client, execute command and parse result -+ create a ssh client, execute command and parse result - -- Args: -- command(str): shell command -- timeout(float): the maximum time to wait for the result of command execution -+ Args: -+ command(str): shell command -+ timeout(float): the maximum time to wait for the result of command execution - -- Returns: -- tuple: -- status, result, error message -+ Returns: -+ tuple: -+ status, result, error message - """ - open_channel = self._client.get_transport().open_session(timeout=timeout) - open_channel.set_combine_stderr(False) -@@ -110,13 +117,14 @@ def execute_command_and_parse_its_result(connect_args: ClientConnectArgs, comman - status, result - """ - if not connect_args.pkey: -- return state.SSH_AUTHENTICATION_ERROR, f"ssh authentication failed when connect host " f"{connect_args.host_ip}" -+ return state.SSH_AUTHENTICATION_ERROR, f"ssh authentication failed when connect host " \ -+ f"{connect_args.host_ip}" - try: - client = SSH( - ip=connect_args.host_ip, - username=connect_args.ssh_user, - port=connect_args.ssh_port, -- pkey=paramiko.RSAKey.from_private_key(StringIO(connect_args.pkey)), -+ pkey=paramiko.RSAKey.from_private_key(StringIO(connect_args.pkey)) - ) - exit_status, stdout, stderr = client.execute_command(command, connect_args.timeout) - except socket.error as error: -@@ -131,3 +139,47 @@ def execute_command_and_parse_its_result(connect_args: ClientConnectArgs, comman - return state.SUCCEED, stdout - LOGGER.error(stderr) - return state.EXECUTE_COMMAND_ERROR, stderr -+ -+ -+def execute_command_sftp_result(connect_args: ClientConnectArgs, local_path=None, remote_path=None): -+ """ -+ create a ssh client, execute command and parse result -+ -+ Args: -+ connect_args(ClientConnectArgs): e.g -+ ClientArgs(host_ip='127.0.0.1', ssh_port=22, ssh_user='root', pkey=RSAKey string) -+ command(str): shell command -+ -+ Returns: -+ tuple: -+ status, result -+ """ -+ global sftp_client, client -+ if not connect_args.pkey: -+ return state.SSH_AUTHENTICATION_ERROR, f"ssh authentication failed when connect host " \ -+ f"{connect_args.host_ip}" -+ try: -+ client = SSH( -+ ip=connect_args.host_ip, -+ username=connect_args.ssh_user, -+ port=connect_args.ssh_port, -+ pkey=paramiko.RSAKey.from_private_key(StringIO(connect_args.pkey)) -+ ) -+ sftp_client = client.client().open_sftp() -+ -+ # Specifies the path to the local file and the remote file -+ # Upload files to a remote server -+ sftp_client.put(local_path, remote_path) -+ return state.SUCCEED -+ except socket.error as error: -+ LOGGER.error(error) -+ return state.SSH_CONNECTION_ERROR, "SSH.Connection.Error" -+ except paramiko.ssh_exception.SSHException as error: -+ LOGGER.error(error) -+ return state.SSH_AUTHENTICATION_ERROR, "SSH.Authentication.Error" -+ except Exception as error: -+ LOGGER.error(error) -+ return state.SSH_AUTHENTICATION_ERROR, "SSH.Authentication.Error" -+ finally: -+ sftp_client.close() -+ client.close() --- -2.33.1.windows.1 - diff --git a/0004-bugfix-cve-fix-result-parsing-error.patch b/0004-bugfix-cve-fix-result-parsing-error.patch deleted file mode 100644 index 40248bef7e5b75672ee4d8ce69ab609dfa6c7702..0000000000000000000000000000000000000000 --- a/0004-bugfix-cve-fix-result-parsing-error.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 21a8a9db54175547675bda5214d98ffa5a654d03 Mon Sep 17 00:00:00 2001 -From: rabbitali -Date: Tue, 19 Sep 2023 16:58:56 +0800 -Subject: [PATCH 1/1] bugfix: cve fix result parsing error - ---- - zeus/vulnerability_manage/view.py | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/zeus/vulnerability_manage/view.py b/zeus/vulnerability_manage/view.py -index b5360e2..345978f 100644 ---- a/zeus/vulnerability_manage/view.py -+++ b/zeus/vulnerability_manage/view.py -@@ -416,10 +416,11 @@ class ExecuteCveFixTask(BaseResponse, BaseExcuteTask): - cve_fix_result_json = json.loads(cve_fix_result) - if cve_fix_result_json.pop("code") != state.SUCCEED: - request_body["status"] = CveTaskStatus.FAIL -+ else: -+ request_body["status"] = CveTaskStatus.SUCCEED - - request_body.update( - { -- "status": CveTaskStatus.SUCCEED, - "check_items": cve_fix_result_json.get("check_items"), - "cves": cve_fix_result_json.get("cves"), - } --- -2.33.0 - diff --git a/aops-zeus-v1.3.0.tar.gz b/aops-zeus-v1.3.1.tar.gz similarity index 52% rename from aops-zeus-v1.3.0.tar.gz rename to aops-zeus-v1.3.1.tar.gz index 6882ff18ce1c90f986aea04bb1c1bd31f9061dd4..da95fe85b025d16ed980909ec8644da992876a23 100644 Binary files a/aops-zeus-v1.3.0.tar.gz and b/aops-zeus-v1.3.1.tar.gz differ diff --git a/aops-zeus.spec b/aops-zeus.spec index 00f2c2eb984d988d40a9d45409a5d24e0b523fd3..55fa73c8ce7f9a434bd2b226a81bf56f964fc1fe 100644 --- a/aops-zeus.spec +++ b/aops-zeus.spec @@ -1,18 +1,16 @@ Name: aops-zeus -Version: v1.3.0 -Release: 4 +Version: v1.3.1 +Release: 2 Summary: A host and user manager service which is the foundation of aops. License: MulanPSL2 URL: https://gitee.com/openeuler/%{name} Source0: %{name}-%{version}.tar.gz -Patch0001: 0001-add-file-sync-func.patch -Patch0002: 0002-update-callback-request-headers.patch -Patch0003: 0003-fix-bash-file-sync-error.patch -Patch0004: 0004-bugfix-cve-fix-result-parsing-error.patch +Patch0001: 0001-fix-metric-proxy-init-failed-error.patch +Patch0002: 0002-add-key-authentication-for-add-host-api.patch BuildRequires: python3-setuptools -Requires: aops-vulcanus >= v1.2.0 +Requires: aops-vulcanus >= v1.3.0 Requires: python3-marshmallow >= 3.13.0 python3-flask python3-flask-restful python3-gevent Requires: python3-requests python3-uWSGI python3-sqlalchemy python3-werkzeug python3-PyMySQL Requires: python3-paramiko >= 2.11.0 python3-redis python3-prometheus-api-client @@ -49,6 +47,14 @@ cp -r database %{buildroot}/opt/aops/ %changelog +* Wed Oct 18 2023 wenxin - v1.3.1-2 +- fix bug: metric proxy init failed +- add a way about key authentication for add host api + +* Thu Sep 21 2023 wenxin - v1.3.1-1 +- update spec requires +- update version info in setup.py file + * Tue Sep 19 2023 wenxin - v1.3.0-4 - bugfix: cve fix result parsing error