async def print_agents(filter_status, filter_node): lc = local_client.LocalClient() result = await control.get_agents(lc, filter_node=filter_node, filter_status=filter_status) headers = {'id': 'ID', 'name': 'Name', 'ip': 'IP', 'status': 'Status', 'version': 'Version', 'node_name': 'Node name'} data = map(operator.itemgetter(*headers.keys()), result['items']) __print_table(data, list(headers.values()), True)
async def get_system_nodes(): try: lc = local_client.LocalClient() result = await get_nodes(lc) return [node['name'] for node in result['items']] except Exception: raise WazuhInternalError(3012)
async def get_system_nodes(): try: lc = local_client.LocalClient() result = await get_nodes(lc) return [node['name'] for node in result['items']] except WazuhInternalError as e: if e.code == 3012: return WazuhError(3013) raise e
def __init__(self, worker, destination_daemon, data_retriever: callable, logger=None, msg_format='{payload}', n_retries=3, retry_time=0.2, max_retry_time_allowed=10, cmd=None, expected_res='ok'): """Class constructor. Parameters ---------- worker : WorkerHandler object Instance of worker object. destination_daemon : str Daemon name on the master node to which send information. cmd : bytes Command to inform the master when the synchronization process starts and ends. data_retriever : Callable Function to be called to obtain chunks of data. It must return a list of chunks. logger : Logger object, optional Logger to use during synchronization process. msg_format : str, optional Format of the message to be executed in the master's daemon. It must contain the label '{payload}', which will be replaced with every chunk of data. I. e: 'global sync-agent-info-set {payload}' n_retries : int, optional Number of times a chunk has to be resent when it fails. retry_time : float, optional Time between resend attempts. It is multiplied by the number of retries carried out. max_retry_time_allowed : float, optional Maximum total time allowed to retry failed requests. If this time has already been elapsed, no new attempts will be made to resend all the chunks which response does not begin with {expected_res}. expected_res : str, optional Master's response that will be interpreted as correct. If it doesn't match, send retries will be made. """ self.worker = worker self.daemon = destination_daemon self.msg_format = msg_format self.data_retriever = data_retriever self.logger = logger if logger is not None else self.worker.setup_task_logger( 'Default logger') self.n_retries = n_retries self.retry_time = retry_time self.max_retry_time_allowed = max_retry_time_allowed self.cmd = cmd self.expected_res = expected_res self.lc = local_client.LocalClient()
def get_client(self) -> c_common.Handler: """ Create another LocalClient if necessary and stores it to be closed later. :return: client. Maybe an instance of LocalClient, WorkerHandler or MasterHandler """ if self.node == local_client: client = local_client.LocalClient() self.local_clients.append(client) else: client = self.node return client
async def get_system_nodes(): """Get the name of all the cluster nodes. Returns ------- list Name of each cluster node. """ try: lc = local_client.LocalClient() result = await get_nodes(lc) return [node['name'] for node in result['items']] except WazuhInternalError as e: if e.code == 3012: return WazuhError(3013) raise e
async def execute_local_request(self) -> str: """Execute an API request locally. Returns ------- str JSON response. """ def run_local(): self.debug_log("Starting to execute request locally") common.rbac.set(self.rbac_permissions) common.broadcast.set(self.broadcasting) common.cluster_nodes.set(self.nodes) common.current_user.set(self.current_user) common.origin_module.set(self.origin_module) data = self.f(**self.f_kwargs) common.reset_context_cache() self.debug_log("Finished executing request locally") return data try: if self.f_kwargs.get('agent_list') == '*': del self.f_kwargs['agent_list'] before = time.time() self.check_wazuh_status() timeout = self.api_request_timeout if not self.wait_for_complete else None # LocalClient only for control functions if self.local_client_arg is not None: lc = local_client.LocalClient() self.f_kwargs[self.local_client_arg] = lc try: if self.is_async: task = run_local() else: loop = asyncio.get_running_loop() task = loop.run_in_executor(threadpool, run_local) try: data = await asyncio.wait_for(task, timeout=timeout) except asyncio.TimeoutError: raise exception.WazuhInternalError(3021) except OperationalError: raise exception.WazuhInternalError(2008) except json.decoder.JSONDecodeError: raise exception.WazuhInternalError(3036) self.debug_log( f"Time calculating request result: {time.time() - before:.3f}s" ) return data except (exception.WazuhError, exception.WazuhResourceNotFound) as e: e.dapi_errors = self.get_error_info(e) if self.debug: raise return json.dumps(e, cls=c_common.WazuhJSONEncoder) except exception.WazuhInternalError as e: e.dapi_errors = self.get_error_info(e) # Avoid exception info if it is an asyncio timeout or JSONDecodeError self.logger.error(f"{e.message}", exc_info=e.code not in {3021, 3036}) if self.debug: raise return json.dumps(e, cls=c_common.WazuhJSONEncoder) except Exception as e: self.logger.error(f'Error executing API request locally: {str(e)}', exc_info=True) if self.debug: raise return json.dumps(exception.WazuhInternalError( 1000, dapi_errors=self.get_error_info(e)), cls=c_common.WazuhJSONEncoder)
async def print_health(config, more, filter_node): lc = local_client.LocalClient() result = await control.get_health(lc, filter_node=filter_node) msg1 = "" msg2 = "" msg1 += "Cluster name: {}\n\n".format(config['name']) if not more: msg1 += "Last completed synchronization for connected nodes ({}):\n".format( result["n_connected_nodes"]) else: msg1 += "Connected nodes ({}):".format(result["n_connected_nodes"]) for node, node_info in sorted(result["nodes"].items()): msg2 += "\n {} ({})\n".format(node, node_info['info']['ip']) msg2 += " Version: {}\n".format(node_info['info']['version']) msg2 += " Type: {}\n".format(node_info['info']['type']) msg2 += " Active agents: {}\n".format( node_info['info']['n_active_agents']) if node_info['info']['type'] != "master": if not more: msg1 += " {} ({}): Integrity: {} | Agents-info: {} | Agent-groups: {} | Last keep alive: {}.\n".format( node, node_info['info']['ip'], node_info['status'] ['last_sync_integrity']['date_end_master'], node_info['status']['last_sync_agentinfo'] ['date_end_master'], node_info['status'] ['last_sync_agentgroups']['date_end_master'], node_info['status']['last_keep_alive']) msg2 += " Status:\n" # Last Keep Alive msg2 += " Last keep Alive:\n" msg2 += " Last received: {0}.\n".format( node_info['status']['last_keep_alive']) # Integrity msg2 += " Integrity\n" msg2 += " Last synchronization: {0} - {1}.\n".format( node_info['status']['last_sync_integrity'] ['date_start_master'], node_info['status']['last_sync_integrity']['date_end_master']) n_shared = str(node_info['status']['last_sync_integrity'] ['total_files']["shared"]) n_missing = str(node_info['status']['last_sync_integrity'] ['total_files']["missing"]) n_extra = str(node_info['status']['last_sync_integrity'] ['total_files']["extra"]) n_extra_valid = str(node_info['status']['last_sync_integrity'] ['total_files']["extra_valid"]) msg2 += " Synchronized files: Shared: {} | Missing: {} | Extra: {} | Extra valid: {}.\n".format( n_shared, n_missing, n_extra, n_extra_valid) msg2 += " Permission to synchronize: {}.\n".format( str(node_info['status']['sync_integrity_free'])) # Agent info msg2 += " Agents-info\n" msg2 += " Last synchronization: {0} - {1}.\n".format( node_info['status']['last_sync_agentinfo'] ['date_start_master'], node_info['status']['last_sync_agentinfo']['date_end_master']) msg2 += " Synchronized files: {}.\n".format( str(node_info['status']['last_sync_agentinfo'] ['total_agentinfo'])) msg2 += " Permission to synchronize: {}.\n".format( str(node_info['status']['sync_agentinfo_free'])) # Agent groups msg2 += " Agents-group\n" msg2 += " Last synchronization: {0} - {1}.\n".format( node_info['status']['last_sync_agentgroups'] ['date_start_master'], node_info['status'] ['last_sync_agentgroups']['date_end_master']) msg2 += " Synchronized files: {}.\n".format( str(node_info['status']['last_sync_agentgroups'] ['total_agentgroups'])) msg2 += " Permission to synchronize: {}.\n".format( str(node_info['status']['sync_extravalid_free'])) print(msg1) if more: print(msg2)
async def print_nodes(filter_node): lc = local_client.LocalClient() result = await control.get_nodes(lc, filter_node=filter_node) headers = ["Name", "Type", "Version", "Address"] data = map(lambda x: list(x.values()), result['items']) __print_table(data, headers, True)
async def execute_local_request(self) -> str: """Execute an API request locally. Returns ------- str JSON response. """ def run_local(): self.logger.debug("Starting to execute request locally") common.rbac.set(self.rbac_permissions) common.broadcast.set(self.broadcasting) common.cluster_nodes.set(self.nodes) common.current_user.set(self.current_user) data = self.f(**self.f_kwargs) common.reset_context_cache() self.logger.debug("Finished executing request locally") return data try: before = time.time() self.check_wazuh_status() timeout = None if self.wait_for_complete \ else self.cluster_items['intervals']['communication']['timeout_api_exe'] # LocalClient only for control functions if self.local_client_arg is not None: lc = local_client.LocalClient() self.f_kwargs[self.local_client_arg] = lc else: lc = None if self.is_async: task = run_local() else: loop = asyncio.get_running_loop() task = loop.run_in_executor(self.threadpool, run_local) try: data = await asyncio.wait_for(task, timeout=timeout) except asyncio.TimeoutError: raise exception.WazuhInternalError(3021) self.logger.debug( f"Time calculating request result: {time.time() - before}s") return data except (exception.WazuhError, exception.WazuhResourceNotFound) as e: e.dapi_errors = self.get_error_info(e) if self.debug: raise return json.dumps(e, cls=c_common.WazuhJSONEncoder) except exception.WazuhInternalError as e: e.dapi_errors = self.get_error_info(e) self.logger.error(f"{e.message}", exc_info=True) if self.debug: raise return json.dumps(e, cls=c_common.WazuhJSONEncoder) except Exception as e: self.logger.error(f'Error executing API request locally: {str(e)}', exc_info=True) if self.debug: raise return json.dumps(exception.WazuhInternalError( 1000, dapi_errors=self.get_error_info(e)), cls=c_common.WazuhJSONEncoder)
async def execute_local_request(self) -> str: """Execute an API request locally. Returns ------- str JSON response. """ try: if self.f_kwargs.get('agent_list') == '*': del self.f_kwargs['agent_list'] before = time.time() self.check_wazuh_status() timeout = self.api_request_timeout if not self.wait_for_complete else None # LocalClient only for control functions if self.local_client_arg is not None: lc = local_client.LocalClient() self.f_kwargs[self.local_client_arg] = lc try: if self.is_async: task = self.run_local(self.f, self.f_kwargs, self.logger, self.rbac_permissions, self.broadcasting, self.nodes, self.current_user) else: loop = asyncio.get_event_loop() if 'thread_pool' in pools: pool = pools.get('thread_pool') elif self.f.__name__ in authentication_funcs: pool = pools.get('authentication_pool') else: pool = pools.get('process_pool') task = loop.run_in_executor( pool, partial(self.run_local, self.f, self.f_kwargs, self.logger, self.rbac_permissions, self.broadcasting, self.nodes, self.current_user)) try: data = await asyncio.wait_for(task, timeout=timeout) except asyncio.TimeoutError: raise exception.WazuhInternalError(3021) except OperationalError: raise exception.WazuhInternalError(2008) except process.BrokenProcessPool: raise exception.WazuhInternalError(901) except json.decoder.JSONDecodeError: raise exception.WazuhInternalError(3036) except process.BrokenProcessPool: raise exception.WazuhInternalError(900) self.debug_log( f"Time calculating request result: {time.time() - before:.3f}s" ) return data except (exception.WazuhError, exception.WazuhResourceNotFound) as e: e.dapi_errors = self.get_error_info(e) if self.debug: raise return json.dumps(e, cls=c_common.WazuhJSONEncoder) except exception.WazuhInternalError as e: e.dapi_errors = self.get_error_info(e) # Avoid exception info if it is an asyncio timeout or JSONDecodeError self.logger.error(f"{e.message}", exc_info=e.code not in {3021, 3036}) if self.debug: raise return json.dumps(e, cls=c_common.WazuhJSONEncoder) except Exception as e: self.logger.error(f'Error executing API request locally: {str(e)}', exc_info=True) if self.debug: raise return json.dumps(exception.WazuhInternalError( 1000, dapi_errors=self.get_error_info(e)), cls=c_common.WazuhJSONEncoder)
async def print_health(config, more, filter_node): """Print the current status of the cluster as well as additional information. Parameters ---------- config : dict Cluster current configuration. more : bool Indicate whether additional information is desired or not. filter_node : str, list Node to return. """ def calculate_seconds(start_time, end_time): """Calculate the time difference between two dates. Parameters ---------- start_time : str Start date. end_time : str End date. Returns ------- str Total seconds between the two dates. """ if end_time != 'n/a' and start_time != 'n/a': seconds = \ datetime.strptime(end_time, decimals_date_format) - datetime.strptime(start_time, decimals_date_format) total_seconds = f"{round(seconds.total_seconds(), 3) if seconds.total_seconds() >= 0.0005 else 0.001}s" else: total_seconds = 'n/a' return total_seconds lc = local_client.LocalClient() result = await control.get_health(lc, filter_node=filter_node) msg2 = "" msg1 = f"Cluster name: {config['name']}\n\n" msg1 += f"Last completed synchronization for connected nodes ({result['n_connected_nodes']}):\n" if not more \ else f"Connected nodes ({result['n_connected_nodes']}):" for node, node_info in sorted(result["nodes"].items()): msg2 += f"\n {node} ({node_info['info']['ip']})\n" msg2 += f" Version: {node_info['info']['version']}\n" msg2 += f" Type: {node_info['info']['type']}\n" msg2 += f" Active agents: {node_info['info']['n_active_agents']}\n" if node_info['info']['type'] != "master": if not more: msg1 += f" {node} ({node_info['info']['ip']}): " \ f"Integrity check: {node_info['status']['last_check_integrity']['date_end_master']} | " \ f"Integrity sync: {node_info['status']['last_sync_integrity']['date_end_master']} | " \ f"Agents-info: {node_info['status']['last_sync_agentinfo']['date_end_master']} | " \ f"Last keep alive: {node_info['status']['last_keep_alive']}.\n" msg2 += " Status:\n" # Last Keep Alive msg2 += " Last keep Alive:\n" msg2 += f" Last received: {node_info['status']['last_keep_alive']}.\n" # Integrity check total = calculate_seconds( node_info['status']['last_check_integrity'] ['date_start_master'], node_info['status']['last_check_integrity']['date_end_master']) msg2 += f" Integrity check:\n" msg2 += f" Last integrity check: {total} " \ f"({node_info['status']['last_check_integrity']['date_start_master']} - " \ f"{node_info['status']['last_check_integrity']['date_end_master']}).\n" msg2 += f" Permission to check integrity: {node_info['status']['sync_integrity_free']}.\n" # Integrity sync total = calculate_seconds( node_info['status']['last_sync_integrity'] ['date_start_master'], node_info['status']['last_sync_integrity']['date_end_master']) msg2 += " Integrity sync:\n" msg2 += f" Last integrity synchronization: {total} " \ f"({node_info['status']['last_sync_integrity']['date_start_master']} - " \ f"{node_info['status']['last_sync_integrity']['date_end_master']}).\n" n_shared = str(node_info['status']['last_sync_integrity'] ['total_files']["shared"]) n_missing = str(node_info['status']['last_sync_integrity'] ['total_files']["missing"]) n_extra = str(node_info['status']['last_sync_integrity'] ['total_files']["extra"]) n_extra_valid = str(node_info['status']['last_sync_integrity'] ['total_files']["extra_valid"]) msg2 += f" Synchronized files: Shared: {n_shared} | Missing: {n_missing} | " \ f"Extra: {n_extra} | Extra valid: {n_extra_valid}.\n" msg2 += f" Extra valid files correctly updated in master: " \ f"{node_info['status']['last_sync_integrity']['total_extra_valid']}.\n" # Agent info total = calculate_seconds( node_info['status']['last_sync_agentinfo'] ['date_start_master'], node_info['status']['last_sync_agentinfo']['date_end_master']) msg2 += " Agents-info:\n" msg2 += f" Last synchronization: {total} " \ f"({node_info['status']['last_sync_agentinfo']['date_start_master']} - " \ f"{node_info['status']['last_sync_agentinfo']['date_end_master']}).\n" msg2 += f" Number of synchronized chunks: " \ f"{node_info['status']['last_sync_agentinfo']['n_synced_chunks']}.\n" msg2 += f" Permission to synchronize agent-info: " \ f"{node_info['status']['sync_agent_info_free']}.\n" print(msg1) more and print(msg2)