Example #1
0
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)
Example #2
0
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)
Example #3
0
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
Example #4
0
    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()
Example #5
0
    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
Example #6
0
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
Example #7
0
    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)
Example #8
0
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)
Example #9
0
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)
Example #10
0
    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)
Example #11
0
    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)
Example #12
0
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)