Example #1
0
    def _initialize(self):
        """
        Calculates all Wazuh installation metadata
        """
        # info DB if possible
        try:
            wdb_conn = WazuhDBConnection()
            open_ssl = wdb_conn.execute("global sql SELECT value FROM info WHERE key = 'openssl_support'")[0]['value']
            self.openssl_support = open_ssl
        except Exception:
            self.openssl_support = "N/A"

        # Ruleset version
        ruleset_version_file = os.path.join(self.path, 'ruleset', 'VERSION')
        try:
            with open(ruleset_version_file, 'r') as f:
                line_regex = re.compile(r'(^\w+)="(.+)"')
                for line in f:
                    match = line_regex.match(line)
                    if match and len(match.groups()) == 2:
                        self.ruleset_version = match.group(2)
        except:
            raise WazuhInternalError(1005, extra_message=ruleset_version_file)

        # Timezone info
        try:
            self.tz_offset = strftime("%z")
            self.tz_name = strftime("%Z")
        except Exception:
            self.tz_offset = None
            self.tz_name = None

        return self.to_dict()
Example #2
0
def clear(agent_list=None):
    """Clear the rootcheck database for a list of agents.

    Parameters
    ----------
    agent_list : list
        List of agent ids.

    Returns
    -------
    result : AffectedItemsWazuhResult
        JSON containing the affected agents.
    """
    result = AffectedItemsWazuhResult(
        all_msg='Rootcheck database was cleared on returned agents',
        some_msg='Rootcheck database was not cleared on some agents',
        none_msg="No rootcheck database was cleared")

    wdb_conn = WazuhDBConnection()
    for agent_id in agent_list:
        if agent_id not in get_agents_info():
            result.add_failed_item(id_=agent_id,
                                   error=WazuhResourceNotFound(1701))
        else:
            try:
                wdb_conn.execute(f"agent {agent_id} rootcheck delete",
                                 delete=True)
                result.affected_items.append(agent_id)
            except WazuhError as e:
                result.add_failed_item(id_=agent_id, error=e)

    result.affected_items.sort(key=int)
    result.total_affected_items = len(result.affected_items)

    return result
Example #3
0
def last_scan(agent_id):
    """Get the last rootcheck scan of an agent.

    :param agent_id: Agent ID.
    :return: Dictionary: end, start.
    """
    Agent(agent_id).get_basic_information()
    wdb_conn = WazuhDBConnection()

    # end time
    result = wdb_conn.execute(
        f"agent {agent_id} sql SELECT max(date_last) FROM pm_event WHERE "
        "log = 'Ending rootcheck scan.'")
    time = list(result[0].values())[0] if result else None
    end = datetime.utcfromtimestamp(time).strftime(
        date_format) if time is not None else None

    # start time
    result = wdb_conn.execute(
        f"agent {agent_id} sql SELECT max(date_last) FROM pm_event "
        "WHERE log = 'Starting rootcheck scan.'")
    time = list(result[0].values())[0] if result else None
    start = datetime.utcfromtimestamp(time).strftime(
        date_format) if time is not None else None

    return {
        'start':
        start,
        'end':
        None if start is None else None if end is None or end < start else end
    }
Example #4
0
def test_run_wdb_command(connect_mock):
    with patch('wazuh.core.wdb.WazuhDBConnection._send',
               side_effect=[['due', 'chunk1'], ['due', 'chunk2'],
                            ['ok', 'chunk3'], ['due', 'chunk4']]):
        mywdb = WazuhDBConnection()
        result = mywdb.run_wdb_command("global sync-agent-info-get ")
        assert result == ['chunk1', 'chunk2', 'chunk3']
Example #5
0
def test_run_wdb_command_ko(connect_mock):
    with patch('wazuh.core.wdb.WazuhDBConnection._send',
               side_effect=[['due', 'chunk1'], ['err', 'chunk2'],
                            ['ok', 'chunk3'], ['due', 'chunk4']]):
        mywdb = WazuhDBConnection()
        with pytest.raises(exception.WazuhInternalError,
                           match=".* 2007 .* chunk2"):
            mywdb.run_wdb_command("global sync-agent-info-get ")
Example #6
0
def get_manager_name():
    """This function read the manager name from global.db"""
    wdb_conn = WazuhDBConnection()
    manager_name = wdb_conn.execute(
        "global sql SELECT name FROM agent WHERE (id = 0)")[0]['name']
    wdb_conn.close()

    return manager_name
Example #7
0
    def remove_bulk_agents(agent_ids_list: KeysView, logger):
        """
        Removes files created by agents in worker nodes. This function doesn't remove agents from client.keys since the
        client.keys file is overwritten by the master node.
        :param agent_ids_list: List of agents ids to remove.
        :param logger: Logger to use
        :return: None.
        """

        def remove_agent_file_type(agent_files: List[str]):
            """
            Removes files if they exist
            :param agent_files: Path regexes of the files to remove
            :return: None
            """
            for filetype in agent_files:

                filetype_glob = filetype.format(ossec_path=common.ossec_path, id='*', name='*', ip='*')
                filetype_agent = {filetype.format(ossec_path=common.ossec_path, id=a['id'], name=a['name'], ip=a['ip'])
                                  for a in agent_info}

                for agent_file in set(glob.iglob(filetype_glob)) & filetype_agent:
                    logger.debug2("Removing {}".format(agent_file))
                    if os.path.isdir(agent_file):
                        shutil.rmtree(agent_file)
                    else:
                        os.remove(agent_file)

        if not agent_ids_list:
            return  # the function doesn't make sense if there is no agents to remove

        logger.info("Removing files from {} agents".format(len(agent_ids_list)))
        logger.debug("Agents to remove: {}".format(', '.join(agent_ids_list)))
        # Remove agents in group of 500 elements (so wazuh-db socket is not saturated)
        for agents_ids_sublist in itertools.zip_longest(*itertools.repeat(iter(agent_ids_list), 500), fillvalue='0'):
            agents_ids_sublist = list(filter(lambda x: x != '0', agents_ids_sublist))
            # Get info from DB
            agent_info = Agent.get_agents_overview(q=",".join(["id={}".format(i) for i in agents_ids_sublist]),
                                                   select=['ip', 'id', 'name'], limit=None)['items']
            logger.debug2("Removing files from agents {}".format(', '.join(agents_ids_sublist)))

            files_to_remove = ['{ossec_path}/queue/rootcheck/({name}) {ip}->rootcheck',
                               '{ossec_path}/queue/diff/{name}', '{ossec_path}/queue/agent-groups/{id}',
                               '{ossec_path}/queue/rids/{id}',
                               '{ossec_path}/var/db/agents/{name}-{id}.db']
            remove_agent_file_type(files_to_remove)

            logger.debug2("Removing agent group assigments from database")
            # remove agent from groups
            wdb_conn = WazuhDBConnection()

            query_to_execute = 'global sql delete from belongs where {}'.format(' or '.join([
                'id_agent = {}'.format(agent_id) for agent_id in agents_ids_sublist
            ]))
            wdb_conn.run_wdb_command(query_to_execute)

        logger.info("Agent files removed")
Example #8
0
    async def sync_wazuh_db_info(self, task_id: bytes):
        """Iterate and update in the local wazuh-db the chunks of data received from a worker.

        Parameters
        ----------
        task_id : bytes
            ID of the string where the JSON chunks are stored.

        Returns
        -------
        result : bytes
            Worker's response after finishing the synchronization.
        """
        logger = self.task_loggers['Agent-info sync']
        logger.info(f"Starting")
        date_start_master = datetime.now()
        wdb_conn = WazuhDBConnection()
        result = {'updated_chunks': 0, 'error_messages': list()}

        try:
            # Chunks were stored under 'task_id' as an string.
            received_string = self.in_str[task_id].payload
            data = json.loads(received_string.decode())
        except KeyError as e:
            await self.send_request(command=b'syn_m_a_err',
                                    data=f"error while trying to access string under task_id {str(e)}.".encode())
            raise exception.WazuhClusterError(3035, extra_message=f"it should be under task_id {str(e)}, but it's empty.")
        except ValueError as e:
            await self.send_request(command=b'syn_m_a_err', data=f"error while trying to load JSON: {str(e)}".encode())
            raise exception.WazuhClusterError(3036, extra_message=str(e))

        # Update chunks in local wazuh-db
        before = time()
        for i, chunk in enumerate(data['chunks']):
            try:
                logger.debug2(f"Sending chunk {i+1}/{len(data['chunks'])} to wazuh-db: {chunk}")
                response = wdb_conn.send(f"{data['set_data_command']} {chunk}", raw=True)
                if response[0] != 'ok':
                    result['error_messages'].append(response)
                    logger.error(f"Response for chunk {i}/{len(data['chunks'])} was not 'ok': {response}")
                else:
                    result['updated_chunks'] += 1
            except Exception as e:
                result['error_messages'].append(str(e))
        logger.debug(f"All chunks updated in wazuh-db in {(time() - before):3f}s.")

        # Send result to worker
        response = await self.send_request(command=b'syn_m_a_e', data=json.dumps(result).encode())
        self.sync_agent_info_status.update({'date_start_master': date_start_master, 'date_end_master': datetime.now(),
                                            'n_synced_chunks': result['updated_chunks']})
        logger.info("Finished in {:.3f}s ({} chunks updated).".format((self.sync_agent_info_status['date_end_master'] -
                                                                       self.sync_agent_info_status['date_start_master'])
                                                                      .total_seconds(), result['updated_chunks']))

        return response
Example #9
0
def test_remove_agents_database(send_mock, connect_mock, content):
    """
    Tests delete_agents_db method handle exceptions properly
    """
    def recv_mock(size_to_receive):
        return bytes(len(content)) if size_to_receive == 4 else content

    with patch('socket.socket.recv', side_effect=recv_mock):
        mywdb = WazuhDBConnection()
        received = mywdb.delete_agents_db(['001', '002'])
        assert(isinstance(received, dict))
        assert("agents" in received)
Example #10
0
def test_wrong_character_encodings_wdb(send_mock, connect_mock):
    """
    Tests receiving a text with a bad character encoding from wazuh db
    """
    def recv_mock(size_to_receive):
        bad_string = b' {"bad": "\x96bad"}'
        return bytes(len(bad_string)) if size_to_receive == 4 else bad_string

    with patch('socket.socket.recv', side_effect=recv_mock):
        mywdb = WazuhDBConnection()
        received = mywdb._send("test")
        assert received == {"bad": "bad"}
Example #11
0
def test_failed_send_private(send_mock, connect_mock):
    """
        Tests an exception is properly raised when it's not possible to send a msg to the wdb socket
    """
    def recv_mock(size_to_receive):
        error_string = b'err {"agents": {"001": "Error"}}'
        return bytes(len(error_string)) if size_to_receive == 4 else error_string

    with patch('socket.socket.recv', side_effect=recv_mock):
        mywdb = WazuhDBConnection()
        with pytest.raises(exception.WazuhException, match=".* 2003 .*"):
            mywdb._send('test_msg')
Example #12
0
def test_null_values_are_removed(send_mock, connect_mock):
    """
    Tests '(null)' values are removed from the resulting dictionary
    """
    def recv_mock(size_to_receive):
        nulls_string = b' {"a": "a", "b": "(null)", "c": [1, 2, 3], "d": {"e": "(null)"}}'
        return bytes(len(nulls_string)) if size_to_receive == 4 else nulls_string

    with patch('socket.socket.recv', side_effect=recv_mock):
        mywdb = WazuhDBConnection()
        received = mywdb._send("test")
        assert received == {"a": "a", "c": [1, 2, 3], "d": {}}
Example #13
0
def test_failed_connection():
    """
    Tests an exception is properly raised when it's not possible to connect to wdb
    """
    # tests the socket path doesn't exists
    with patch('wazuh.core.common.wdb_socket_path', '/this/path/doesnt/exist'):
        with pytest.raises(exception.WazuhException, match=".* 2005 .*"):
            WazuhDBConnection()
    # tests an exception is properly raised when a connection error is raised
    with patch('socket.socket') as socket_patch:
        with pytest.raises(exception.WazuhException, match=".* 2005 .*"):
            socket_patch.return_value.connect.side_effect = ConnectionError
            WazuhDBConnection()
Example #14
0
def clear(agent_list=None):
    """Clear the syscheck database for a list of agents.

    :param agent_list: List of agent ids
    :return: AffectedItemsWazuhResult.
    """
    result = AffectedItemsWazuhResult(all_msg='Syscheck database was cleared on returned agents',
                                      some_msg='Syscheck database was not cleared on some agents',
                                      none_msg="No syscheck database was cleared")
    wdb_conn = WazuhDBConnection()
    for agent in agent_list:
        if agent not in get_agents_info():
            result.add_failed_item(id_=agent, error=WazuhResourceNotFound(1701))
        else:
            try:
                wdb_conn.execute("agent {} sql delete from fim_entry".format(agent), delete=True)
                # Update key fields which contains keys to value 000
                wdb_conn.execute("agent {} sql update metadata set value = '000' "
                                 "where key like 'fim_db%'".format(agent), update=True)
                wdb_conn.execute("agent {} sql update metadata set value = '000' "
                                 "where key = 'syscheck-db-completed'".format(agent), update=True)
                result.affected_items.append(agent)
            except WazuhError as e:
                result.add_failed_item(id_=agent, error=e)

    result.affected_items.sort(key=int)
    result.total_affected_items = len(result.affected_items)

    return result
Example #15
0
    async def sync_agent_info(self):
        """Obtain information from agents reporting this worker and send it to the master.

        Asynchronous task that is started when the worker connects to the master. It starts an agent-info
        synchronization process every 'sync_agent_info' seconds.

        A list of JSON chunks with the information of all local agents is retrieved from local wazuh-db socket
        and sent to the master's wazuh-db.
        """
        logger = self.task_loggers["Agent-info sync"]
        wdb_conn = WazuhDBConnection()
        synced = True
        agent_info = SyncWazuhdb(worker=self, logger=logger, cmd=b'sync_a_w_m', data_retriever=wdb_conn.run_wdb_command,
                                 get_data_command='global sync-agent-info-get ',
                                 set_data_command='global sync-agent-info-set')

        while True:
            try:
                if self.connected:
                    logger.info("Starting.")
                    start_time = time.time()
                    synced = await agent_info.sync()
                    if synced:
                        self.agent_info_sync_status['date_start'] = start_time
            except Exception as e:
                logger.error(f"Error synchronizing agent info: {e}")

            await asyncio.sleep(
                self.cluster_items['intervals']['worker']['sync_agent_info' if synced else 'sync_agent_info_ko_retry'])
Example #16
0
    def _initialize(self):
        """
        Calculates all Wazuh installation metadata
        """
        # info DB if possible
        try:
            wdb_conn = WazuhDBConnection()
            open_ssl = wdb_conn.execute("global sql SELECT value FROM info WHERE key = 'openssl_support'")[0]['value']
            self.openssl_support = open_ssl
        except Exception:
            self.openssl_support = "N/A"

        # Timezone info
        try:
            self.tz_offset = strftime("%z")
            self.tz_name = strftime("%Z")
        except Exception:
            self.tz_offset = None
            self.tz_name = None

        return self.to_dict()
Example #17
0
def test_failed_execute(send_mock, connect_mock, error_query, error_type, expected_exception, delete, update):
    mywdb = WazuhDBConnection()
    if not error_type:
        with pytest.raises(exception.WazuhException, match=f'.* {expected_exception} .*'):
            mywdb.execute(error_query, delete=delete, update=update)
    else:
        with patch("wazuh.core.wdb.WazuhDBConnection._send", return_value=[{'total': 5}]):
            with patch("wazuh.core.wdb.range", side_effect=error_type):
                with pytest.raises(exception.WazuhException, match=f'.* {expected_exception} .*'):
                    mywdb.execute(error_query, delete=delete, update=update)
Example #18
0
def test_execute_pagination(socket_send_mock, connect_mock):
    mywdb = WazuhDBConnection()

    # Test pagination
    with patch("wazuh.core.wdb.WazuhDBConnection._send",
               side_effect=[[{'total': 5}], exception.WazuhInternalError(2009), ['ok', '{"total": 5}'],
                            ['ok', '{"total": 5}']]):
        mywdb.execute("agent 000 sql select test from test offset 1 limit 500")

    # Test pagination error
    with patch("wazuh.core.wdb.WazuhDBConnection._send",
               side_effect=[[{'total': 5}], exception.WazuhInternalError(2009)]):
        with pytest.raises(exception.WazuhInternalError, match=".* 2009 .*"):
            mywdb.execute("agent 000 sql select test from test offset 1 limit 1")
Example #19
0
    def send_data_to_wdb(data, timeout):
        """Send chunks of data to Wazuh-db socket.

        Parameters
        ----------
        data : dict
            Dict containing command and list of chunks to be sent to wazuh-db.
        timeout : int
            Seconds to wait before stopping the task.

        Returns
        -------
        result : dict
            Dict containing number of updated chunks, error messages (if any) and time spent.
        """
        result = {
            'updated_chunks': 0,
            'error_messages': {
                'chunks': [],
                'others': []
            },
            'time_spent': 0
        }
        wdb_conn = WazuhDBConnection()
        before = datetime.utcnow().timestamp()

        try:
            with utils.Timeout(timeout):
                for i, chunk in enumerate(data['chunks']):
                    try:
                        wdb_conn.send(f"{data['set_data_command']} {chunk}",
                                      raw=True)
                        result['updated_chunks'] += 1
                    except TimeoutError:
                        raise e
                    except Exception as e:
                        result['error_messages']['chunks'].append((i, str(e)))
        except TimeoutError:
            result['error_messages']['others'].append(
                'Timeout while processing agent-info chunks.')
        except Exception as e:
            result['error_messages']['others'].append(
                f'Error while processing agent-info chunks: {e}')

        result['time_spent'] = datetime.utcnow().timestamp() - before
        wdb_conn.close()
        return result
Example #20
0
    async def sync_agent_info(self):
        """Obtain information from agents reporting this worker and send it to the master.

        Asynchronous task that is started when the worker connects to the master. It starts an agent-info
        synchronization process every self.cluster_items['intervals']['worker']['sync_files'] seconds.

        A list of JSON chunks with the information of all local agents is retrieved from local wazuh-db socket
        and directly sent to the master's wazuh-db socket through 'sendsync' protocol.
        """
        agent_info_logger = self.task_loggers["Agent info"]
        wdb_conn = WazuhDBConnection()
        agent_info = RetrieveAndSendToMaster(
            worker=self,
            destination_daemon='wazuh-db',
            logger=agent_info_logger,
            msg_format='global sync-agent-info-set {payload}',
            cmd=b'sync_a_w_m',
            data_retriever=wdb_conn.run_wdb_command,
            max_retry_time_allowed=self.cluster_items['intervals']['worker']
            ['sync_files'])

        while True:
            try:
                if self.connected:
                    agent_info_logger.info("Starting agent-info sync process.")
                    before = time.time()
                    await agent_info.retrieve_and_send(
                        'global sync-agent-info-get ')
                    agent_info_logger.debug2(
                        "Time synchronizing agent statuses: {} s".format(
                            time.time() - before))
            except Exception as e:
                agent_info_logger.error(
                    "Error synchronizing agent info: {}".format(e))

            await asyncio.sleep(
                self.cluster_items['intervals']['worker']['sync_files'])
Example #21
0
def clear(agent_list=None):
    """Clear the rootcheck database for a list of agents.

    Parameters
    ----------
    agent_list : list
        List of agent ids.

    Returns
    -------
    result : AffectedItemsWazuhResult
        JSON containing the affected agents.
    """
    result = AffectedItemsWazuhResult(all_msg='Rootcheck database was cleared on returned agents',
                                      some_msg='Rootcheck database was not cleared on some agents',
                                      none_msg="No rootcheck database was cleared")

    wdb_conn = WazuhDBConnection()
    system_agents = get_agents_info()
    agent_list = set(agent_list)
    not_found_agents = agent_list - system_agents
    # Add non existent agents to failed_items
    [result.add_failed_item(id_=agent_id, error=WazuhResourceNotFound(1701)) for agent_id in not_found_agents]

    eligible_agents = agent_list - not_found_agents
    for agent_id in eligible_agents:
        try:
            rootcheck_delete_agent(agent_id, wdb_conn)
            result.affected_items.append(agent_id)
        except WazuhError as e:
            result.add_failed_item(id_=agent_id, error=e)

    result.affected_items.sort(key=int)
    result.total_affected_items = len(result.affected_items)

    return result
Example #22
0
    async def sync_agent_info(self):
        """
        Asynchronous task that is started when the worker connects to the master. It starts an agent-info
        synchronization process every self.cluster_items['intervals']['worker']['sync_files'] seconds.
        :return: None
        """
        agent_info_logger = self.task_loggers["Agent info"]
        wdb_conn = WazuhDBConnection()
        agent_info = RetrieveAndSendToMaster(worker=self, destination_daemon='wazuh-db', logger=agent_info_logger,
                                             msg_format='global sync-agent-info-set {payload}', cmd=b'sync_a_w_m',
                                             data_retriever=wdb_conn.run_wdb_command, max_retry_time_allowed=
                                             self.cluster_items['intervals']['worker']['sync_files'])

        while True:
            try:
                if self.connected:
                    agent_info_logger.info("Starting agent-info sync process.")
                    before = time.time()
                    await agent_info.retrieve_and_send('global sync-agent-info-get ')
                    agent_info_logger.debug2("Time synchronizing agent statuses: {} s".format(time.time() - before))
            except Exception as e:
                agent_info_logger.error("Error synchronizing agent info: {}".format(e))

            await asyncio.sleep(self.cluster_items['intervals']['worker']['sync_files'])
Example #23
0
def clear(agent_list: list = None):
    """Clear the syscheck database of the specified agents.

    Parameters
    ----------
    agent_list : str
        Agent ID.

    Returns
    -------
    result : AffectedItemsWazuhResult
        Confirmation/Error message.
    """
    result = AffectedItemsWazuhResult(
        all_msg='Syscheck database was cleared on returned agents',
        some_msg='Syscheck database was not cleared on some agents',
        none_msg="No syscheck database was cleared")

    system_agents = get_agents_info()
    not_found_agents = set(agent_list) - system_agents
    list(
        map(
            lambda ag: result.add_failed_item(
                id_=ag, error=WazuhResourceNotFound(1701)), not_found_agents))

    wdb_conn = None
    rbac_filters = get_rbac_filters(system_resources=system_agents,
                                    permitted_resources=agent_list)
    db_query = WazuhDBQueryAgents(select=["id", "version"], **rbac_filters)
    data = db_query.run()

    for item in data['items']:
        agent_id = item['id']
        agent_version = item.get(
            'version',
            None)  # If the value was NULL in the DB the key might not exist
        if agent_version is not None:
            if WazuhVersion(agent_version) < WazuhVersion('v3.12.0'):
                try:
                    if wdb_conn is None:
                        wdb_conn = WazuhDBConnection()
                    syscheck_delete_agent(agent_id, wdb_conn)
                    result.affected_items.append(agent_id)

                except WazuhError as e:
                    result.add_failed_item(id_=agent_id, error=e)
            else:
                result.add_failed_item(
                    id_=agent_id,
                    error=WazuhError(
                        1760,
                        extra_message="Agent version should be < v3.12.0."))
        else:
            result.add_failed_item(id_=agent_id, error=WazuhError(1015))

    if wdb_conn is not None:
        wdb_conn.close()
    result.affected_items.sort(key=int)
    result.total_affected_items = len(result.affected_items)

    return result
Example #24
0
def syscheck_delete_agent(agent: str, wdb_conn: WazuhDBConnection) -> None:
    wdb_conn.execute(f"agent {agent} sql delete from fim_entry", delete=True)
Example #25
0
def test_execute(send_mock, socket_send_mock, connect_mock):
    mywdb = WazuhDBConnection()
    mywdb.execute('agent 000 sql delete from test', delete=True)
    mywdb.execute("agent 000 sql update test set value = 'test' where key = 'test'", update=True)
    with patch("wazuh.core.wdb.WazuhDBConnection._send", return_value=[{'total':5}]):
        mywdb.execute("agent 000 sql select test from test offset 1 limit 1")
        mywdb.execute("agent 000 sql select test from test offset 1 limit 1", count=True)
        mywdb.execute("agent 000 sql select test from test offset 1 count")
Example #26
0
def test_query_lower_private(send_mock, connect_mock):
    mywdb = WazuhDBConnection()
    with pytest.raises(exception.WazuhException, match=".* 2004 .*"):
        mywdb.execute("Agent sql select 'test'")
Example #27
0
def rootcheck_delete_agent(agent: str, wdb_conn: WazuhDBConnection) -> None:
    wdb_conn.execute(f"agent {agent} rootcheck delete", delete=True)
Example #28
0
def test_query_input_validation_private(send_mock, connect_mock, error_query):
    mywdb = WazuhDBConnection()
    with pytest.raises(exception.WazuhException, match=".* 2004 .*"):
        mywdb.execute(error_query)
Example #29
0
def test_execute(send_mock, socket_send_mock, connect_mock):
    def send_mock(obj, msg, raw=False):
        return ['ok', '{"total": 5}'] if raw else [{"total": 5}]

    mywdb = WazuhDBConnection()
    mywdb.execute('agent 000 sql delete from test', delete=True)
    mywdb.execute("agent 000 sql update test set value = 'test' where key = 'test'", update=True)
    with patch("wazuh.core.wdb.WazuhDBConnection._send", new=send_mock):
        mywdb.execute("agent 000 sql select test from test offset 1 limit 1")
        mywdb.execute("agent 000 sql select test from test offset 1 limit 1", count=True)
        mywdb.execute("agent 000 sql select test from test offset 1 count")
Example #30
0
    def remove_bulk_agents(agent_ids_list: KeysView, logger):
        """
        Removes files created by agents in worker nodes. This function doesn't remove agents from client.keys since the
        client.keys file is overwritten by the master node.
        :param agent_ids_list: List of agents ids to remove.
        :param logger: Logger to use
        :return: None.
        """
        def remove_agent_file_type(agent_files: List[str]):
            """
            Removes files if they exist
            :param agent_files: Path regexes of the files to remove
            :return: None
            """
            for filetype in agent_files:

                filetype_glob = filetype.format(ossec_path=common.ossec_path,
                                                id='*',
                                                name='*',
                                                ip='*')
                filetype_agent = {
                    filetype.format(ossec_path=common.ossec_path,
                                    id=a['id'],
                                    name=a['name'],
                                    ip=a['ip'])
                    for a in agent_info
                }

                for agent_file in set(
                        glob.iglob(filetype_glob)) & filetype_agent:
                    logger.debug2("Removing {}".format(agent_file))
                    if os.path.isdir(agent_file):
                        shutil.rmtree(agent_file)
                    else:
                        os.remove(agent_file)

        if not agent_ids_list:
            return  # the function doesn't make sense if there is no agents to remove

        logger.info("Removing files from {} agents".format(
            len(agent_ids_list)))
        logger.debug("Agents to remove: {}".format(', '.join(agent_ids_list)))
        # the agents must be removed in groups of 997: 999 is the limit of SQL variables per query. Limit and offset are
        # always included in the SQL query, so that leaves 997 variables as limit.
        for agents_ids_sublist in itertools.zip_longest(*itertools.repeat(
                iter(agent_ids_list), 997),
                                                        fillvalue='0'):
            agents_ids_sublist = list(
                filter(lambda x: x != '0', agents_ids_sublist))
            # Get info from DB
            agent_info = Agent.get_agents_overview(q=",".join(
                ["id={}".format(i) for i in agents_ids_sublist]),
                                                   select=['ip', 'id', 'name'],
                                                   limit=None)['items']
            logger.debug2("Removing files from agents {}".format(
                ', '.join(agents_ids_sublist)))

            files_to_remove = [
                '{ossec_path}/queue/agent-info/{name}-{ip}',
                '{ossec_path}/queue/rootcheck/({name}) {ip}->rootcheck',
                '{ossec_path}/queue/diff/{name}',
                '{ossec_path}/queue/agent-groups/{id}',
                '{ossec_path}/queue/rids/{id}',
                '{ossec_path}/var/db/agents/{name}-{id}.db'
            ]
            remove_agent_file_type(files_to_remove)

            logger.debug2("Removing agent group assigments from database")
            # remove agent from groups
            db_global = glob.glob(common.database_path_global)
            if not db_global:
                raise WazuhInternalError(1600)

            conn = Connection(db_global[0])
            agent_ids_db = {
                'id_agent{}'.format(i): int(i)
                for i in agents_ids_sublist
            }
            conn.execute(
                'delete from belongs where {}'.format(' or '.join([
                    'id_agent = :{}'.format(i) for i in agent_ids_db.keys()
                ])), agent_ids_db)
            conn.commit()

            # Tell wazuhbd to delete agent database
            wdb_conn = WazuhDBConnection()
            wdb_conn.delete_agents_db(agents_ids_sublist)

        logger.info("Agent files removed")