Пример #1
0
        async def forward(
            node_name: Tuple
        ) -> [wresults.AbstractWazuhResult, exception.WazuhException]:
            """Forward a request to a node.

            Parameters
            ----------
            node_name : tuple
                Node to forward a request to.

            Returns
            -------
            wresults.AbstractWazuhResult or exception.WazuhException
            """
            node_name, agent_list = node_name
            if agent_list:
                self.f_kwargs['agent_id' if 'agent_id' in
                              self.f_kwargs else 'agent_list'] = agent_list
            if node_name == 'unknown' or node_name == '' or node_name == self.node_info[
                    'node']:
                # The request will be executed locally if the the node to forward to is unknown, empty or the master
                # itself
                result = await self.distribute_function()
            else:
                if 'tmp_file' in self.f_kwargs:
                    await self.send_tmp_file(node_name)
                client = self.get_client()
                try:
                    result = json.loads(await client.execute(
                        b'dapi_forward', "{} {}".format(
                            node_name,
                            json.dumps(
                                self.to_dict(),
                                cls=c_common.WazuhJSONEncoder)).encode(),
                        self.wait_for_complete),
                                        object_hook=c_common.as_wazuh_object)
                except WazuhClusterError as e:
                    if e.code == 3022:
                        result = e
                    else:
                        raise e
                # Convert a non existing node into a WazuhError exception
                if isinstance(result,
                              WazuhClusterError) and result.code == 3022:
                    common.rbac.set(self.rbac_permissions)
                    try:
                        await get_nodes_info(client, filter_node=[node_name])
                    except WazuhError as e:
                        if e.code == 4000:
                            result = e
                    dikt = result.to_dict()
                    # Add node ID to error message
                    dikt['ids'] = {node_name}
                    result = WazuhError.from_dict(dikt)

            return result if isinstance(result, (wresults.AbstractWazuhResult, exception.WazuhException)) \
                else wresults.WazuhResult(result)
Пример #2
0
    async def distribute_function(self) -> [Dict, exception.WazuhException]:
        """
        Distribute an API call.

        Returns
        -------
        dict or WazuhException
            Dictionary with API response or WazuhException in case of error.
        """
        try:
            if 'password' in self.f_kwargs:
                self.debug_log(
                    f"Receiving parameters { {**self.f_kwargs, 'password': '******'} }"
                )
            elif 'token_nbf_time' in self.f_kwargs:
                self.logger.debug(f"Decoded token {self.f_kwargs}")
            else:
                self.debug_log(f"Receiving parameters {self.f_kwargs}")

            is_dapi_enabled = self.cluster_items['distributed_api']['enabled']
            is_cluster_disabled = self.node == local_client and not check_cluster_status(
            )

            # First case: execute the request locally.
            # If the distributed api is not enabled
            # If the cluster is disabled or the request type is local_any
            # if the request was made in the master node and the request type is local_master
            # if the request came forwarded from the master node and its type is distributed_master
            if not is_dapi_enabled or is_cluster_disabled or self.request_type == 'local_any' or \
                    (self.request_type == 'local_master' and self.node_info['type'] == 'master') or \
                    (self.request_type == 'distributed_master' and self.from_cluster):

                response = await self.execute_local_request()

            # Second case: forward the request
            # Only the master node will forward a request, and it will only be forwarded if its type is distributed_
            # master
            elif self.request_type == 'distributed_master' and self.node_info[
                    'type'] == 'master':
                response = await self.forward_request()

            # Last case: execute the request remotely.
            # A request will only be executed remotely if it was made in a worker node and its type isn't local_any
            else:
                response = await self.execute_remote_request()

            try:
                response = json.loads(response, object_hook=c_common.as_wazuh_object) \
                    if isinstance(response, str) else response
            except json.decoder.JSONDecodeError:
                response = {'message': response}

            return response if isinstance(response, (wresults.AbstractWazuhResult, exception.WazuhException)) \
                else wresults.WazuhResult(response)

        except json.decoder.JSONDecodeError:
            e = exception.WazuhInternalError(3036)
            e.dapi_errors = self.get_error_info(e)
            if self.debug:
                raise
            self.logger.error(f"{e.message}")
            return e
        except exception.WazuhError as e:
            e.dapi_errors = self.get_error_info(e)
            return e
        except exception.WazuhInternalError as e:
            e.dapi_errors = self.get_error_info(e)
            if self.debug:
                raise
            self.logger.error(f"{e.message}", exc_info=True)
            return e
        except Exception as e:
            if self.debug:
                raise

            self.logger.error(f'Unhandled exception: {str(e)}', exc_info=True)
            return exception.WazuhInternalError(
                1000, dapi_errors=self.get_error_info(e))