Exemple #1
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)
Exemple #2
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')
Exemple #3
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"}
Exemple #4
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": {}}
Exemple #5
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.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()
Exemple #6
0
def clear(agent_id=None, all_agents=False):
    """
    Clears the database.

    :param agent_id: For an agent.
    :param all_agents: For all agents.
    :return: Message.
    """
    agents = [agent_id] if not all_agents else map(
        itemgetter('id'),
        Agent.get_agents_overview(select={'fields': ['id']})['items'])

    wdb_conn = WazuhDBConnection()
    for agent in agents:
        Agent(agent).get_basic_information()  # check if the agent exists
        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)

    return "Syscheck database deleted"
    def __init__(self, agent_id, offset, limit, sort, search, select, query, count,
                 get_data, default_sort_field='policy_id', filters={}, fields=fields_translation_sca,
                 default_query=default_query_sca, count_field='policy_id'):
        self.agent_id = agent_id
        self._default_query_str = default_query
        self.count_field = count_field
        Agent(agent_id).get_basic_information()  # check if the agent exists

        WazuhDBQuery.__init__(self, offset=offset, limit=limit, table='sca_policy', sort=sort,
                              search=search, select=select, fields=fields, default_sort_field=default_sort_field,
                              default_sort_order='DESC', filters=filters, query=query, db_path=None,
                              min_select_fields=set(), count=count, get_data=get_data,
                              date_fields={'end_scan', 'start_scan'})
        self.conn = WazuhDBConnection()
Exemple #8
0
    def __init__(self,
                 agent_id,
                 offset,
                 limit,
                 sort,
                 search,
                 select,
                 query,
                 count,
                 get_data,
                 default_sort_field='policy_id',
                 filters={},
                 fields=fields_translation_ca,
                 default_query=default_query_ca,
                 count_field='policy_id'):
        self.agent_id = agent_id
        self._default_query_str = default_query
        self.count_field = count_field
        Agent(agent_id).get_basic_information()  # check if the agent exists
        db_path = glob('{0}/{1}.db'.format(common.wdb_path, agent_id))
        if not db_path:
            raise WazuhException(1600)

        WazuhDBQuery.__init__(self,
                              offset=offset,
                              limit=limit,
                              table='configuration_assessment_policy',
                              sort=sort,
                              search=search,
                              select=select,
                              fields=fields,
                              default_sort_field=default_sort_field,
                              default_sort_order='DESC',
                              filters=filters,
                              query=query,
                              db_path=db_path[0],
                              min_select_fields=set(),
                              count=count,
                              get_data=get_data,
                              date_fields={'end_scan', 'start_scan'})
        self.conn = WazuhDBConnection()
Exemple #9
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.wdb.WazuhDBConnection._send", return_value=[{'total': 5}]):
            with patch("wazuh.wdb.range", side_effect=error_type):
                with pytest.raises(exception.WazuhException, match=f'.* {expected_exception} .*'):
                    mywdb.execute(error_query, delete=delete, update=update)
Exemple #10
0
 def connect_to_db(self):
     return WazuhDBConnection()
Exemple #11
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={'fields': ['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 WazuhException(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")
Exemple #12
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.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")
Exemple #13
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'")
Exemple #14
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)
Exemple #15
0
class WazuhDBQueryPM(WazuhDBQuery):
    def __init__(self,
                 agent_id,
                 offset,
                 limit,
                 sort,
                 search,
                 select,
                 query,
                 count,
                 get_data,
                 default_sort_field='policy_id',
                 filters={},
                 fields=fields_translation_ca,
                 default_query=default_query_ca,
                 count_field='policy_id'):
        self.agent_id = agent_id
        self._default_query_str = default_query
        self.count_field = count_field
        Agent(agent_id).get_basic_information()  # check if the agent exists
        db_path = glob('{0}/{1}.db'.format(common.wdb_path, agent_id))
        if not db_path:
            raise WazuhException(1600)

        WazuhDBQuery.__init__(self,
                              offset=offset,
                              limit=limit,
                              table='configuration_assessment_policy',
                              sort=sort,
                              search=search,
                              select=select,
                              fields=fields,
                              default_sort_field=default_sort_field,
                              default_sort_order='DESC',
                              filters=filters,
                              query=query,
                              db_path=db_path[0],
                              min_select_fields=set(),
                              count=count,
                              get_data=get_data,
                              date_fields={'end_scan', 'start_scan'})
        self.conn = WazuhDBConnection()

    def _default_query(self):
        return self._default_query_str

    def _substitute_params(self):
        for k, v in self.request.items():
            self.query = self.query.replace(f':{k}', f"'{v}'")

    def _get_total_items(self):
        self._substitute_params()
        total_items = self.conn.execute(
            f'agent {self.agent_id} sql ' +
            self.query.format(self._default_count_query()))
        self.total_items = total_items if isinstance(
            total_items, int) else total_items[0][self._default_count_query()]

    def _default_count_query(self):
        return f"COUNT(DISTINCT {self.count_field})"

    def _get_data(self):
        self._substitute_params()
        self._data = self.conn.execute(
            f'agent {self.agent_id} sql ' + self.query.format(','.join(
                map(lambda x: self.fields[x], self.select['fields']
                    | self.min_select_fields))))

    def _format_data_into_dictionary(self):
        return {"totalItems": self.total_items, "items": self._data}

    def _add_limit_to_query(self):
        if self.limit:
            if self.limit > common.maximum_database_limit:
                raise WazuhException(1405, str(self.limit))
            self.query += f' LIMIT {self.limit} OFFSET {self.offset}'
        elif self.limit == 0:  # 0 is not a valid limit
            raise WazuhException(1406)

    def run(self):

        self._add_select_to_query()
        self._add_filters_to_query()
        self._add_search_to_query()
        if self.count:
            self._get_total_items()
        self._add_sort_to_query()
        self._add_limit_to_query()
        if self.data:
            self._get_data()
            return self._format_data_into_dictionary()