Exemplo n.º 1
0
    def _initialize(self):
        """
        Calculates all Wazuh installation metadata
        """
        # info DB if possible
        try:
            conn = Connection(common.database_path_global)

            query = "SELECT * FROM info"
            conn.execute(query)

            for tuple_ in conn:
                if tuple_[0] == 'max_agents':
                    self.max_agents = tuple_[1]
                elif tuple_[0] == 'openssl_support':
                    self.openssl_support = tuple_[1]
        except Exception:
            self.max_agents = "N/A"
            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()
Exemplo n.º 2
0
def last_scan(agent_list):
    """Gets the last scan of the agent.

    :param agent_list: Agent ID.
    :return: AffectedItemsWazuhResult.
    """
    my_agent = Agent(agent_list[0])
    result = AffectedItemsWazuhResult(all_msg='Last syscheck scan of the agent was returned',
                                      none_msg='No last scan information was returned')
    # If agent status is never_connected, a KeyError happens
    try:
        agent_version = my_agent.get_basic_information(select=['version'])['version']
    except KeyError:
        # If the agent is never_connected, it won't have either version (key error) or last scan information.
        result.affected_items.append({'start': None, 'end': None})
        result.total_affected_items += 1

        return result

    if WazuhVersion(agent_version) < WazuhVersion('Wazuh v3.7.0'):
        db_agent = glob('{0}/{1}-*.db'.format(common.database_path_agents, agent_list[0]))
        if not db_agent:
            raise WazuhInternalError(1600, extra_message=agent_list[0])
        else:
            db_agent = db_agent[0]
        conn = Connection(db_agent)

        data = {}
        # end time
        query = "SELECT max(date_last) FROM pm_event WHERE log = 'Ending rootcheck scan.'"
        conn.execute(query)
        for t in conn:
            data['end'] = t['max(date_last)'] if t['max(date_last)'] is not None else "ND"

        # start time
        query = "SELECT max(date_last) FROM pm_event WHERE log = 'Starting rootcheck scan.'"
        conn.execute(query)
        for t in conn:
            data['start'] = t['max(date_last)'] if t['max(date_last)'] is not None else "ND"

        result.affected_items.append(data)
    else:
        fim_scan_info = WazuhDBQuerySyscheck(agent_id=agent_list[0], query='module=fim', offset=0, sort=None,
                                             search=None, limit=common.database_limit, select={'end', 'start'},
                                             fields={'end': 'end_scan', 'start': 'start_scan', 'module': 'module'},
                                             table='scan_info', default_sort_field='start_scan').run()['items'][0]
        end = None if not fim_scan_info['end'] else fim_scan_info['end']
        start = None if not fim_scan_info['start'] else fim_scan_info['start']
        # If start is None or the scan is running, end will be None.
        result.affected_items.append(
            {'start': start, 'end': None if start is None else None if end is None or end < start else end})
    result.total_affected_items = len(result.affected_items)

    return result
Exemplo n.º 3
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")