Exemple #1
0
def send_restart_command(agent_id: str = '',
                         agent_version: str = '',
                         wq: WazuhQueue = None) -> str:
    """Send restart command to an agent.

    Parameters
    ----------
    agent_id : str
        ID specifying the agent where the restart command will be sent to
    agent_version : str
        Agent version to compare with the required version. The format is vX.Y.Z.
    wq : WazuhQueue
        WazuhQueue used for the active response messages.

    Returns
    -------
    str
        Message generated by Wazuh.
    """
    # If the Wazuh agent version is newer or equal to the AR legacy version,
    # the message sent will have JSON format
    if WazuhVersion(agent_version) >= WazuhVersion(common.AR_LEGACY_VERSION):
        ret_msg = wq.send_msg_to_agent(WazuhQueue.RESTART_AGENTS_JSON,
                                       agent_id)
    else:
        ret_msg = wq.send_msg_to_agent(WazuhQueue.RESTART_AGENTS, agent_id)

    return ret_msg
Exemple #2
0
    def get_stats(self, component):
        """Read the agent's component stats.

        Parameters
        ----------
        component : string
            Name of the component to get stats from.

        Returns
        -------
        Dict
            Object with component's stats.
        """
        # Check if agent version is compatible with this feature
        self.load_info_from_db()
        if self.version is None:
            raise WazuhInternalError(1015)
        agent_version = WazuhVersion(self.version.split(" ")[1])
        required_version = WazuhVersion(
            AGENT_COMPONENT_STATS_REQUIRED_VERSION.get(component))
        if agent_version < required_version:
            raise WazuhInternalError(
                1735,
                extra_message="Minimum required version is " +
                str(required_version))

        return stats.get_daemons_stats_from_socket(self.id, component)
Exemple #3
0
    def getconfig(self,
                  component: str = '',
                  config: str = '',
                  agent_version: str = '') -> dict:
        """Read agent's loaded configuration.

        Parameters
        ----------
        component : str
            Selected component of the agent configuration.
        config : str
            Agent's active configuration to get.
        agent_version : str
            Agent version to compare with the required version. The format is vX.Y.Z or Wazuh vX.Y.Z.

        Raises
        ------
        WazuhError(1735)
            The agent version is older than the minimum required version.

        Returns
        -------
        dict
            Agent's active configuration.
        """
        if WazuhVersion(agent_version) < WazuhVersion(
                common.ACTIVE_CONFIG_VERSION):
            raise WazuhInternalError(
                1735,
                extra_message=
                f"Minimum required version is {common.ACTIVE_CONFIG_VERSION}")

        return configuration.get_active_configuration(self.id, component,
                                                      config)
Exemple #4
0
def send_ar_message(agent_id: str = '',
                    oq: OssecQueue = None,
                    command: str = '',
                    arguments: list = None,
                    custom: bool = False,
                    alert: dict = None) -> None:
    """Send the active response message to the agent.

    Parameters
    ----------
    agent_id : str
        ID specifying the agent where the msg_queue will be sent to.
    oq : OssecQueue
        OssecQueue used for the active response messages.
    command : str
        Command running in the agents. If this value starts with !, then it refers to a script name instead of a
        command name.
    custom : bool
        Whether the specified command is a custom command or not.
    arguments : list
        Command arguments.
    alert : dict
        Alert information depending on the AR executed.

    Raises
    ------
    WazuhError(1651)
        If the agent with ID agent_id is not active.
    """
    # Agent basic information
    agent_info = Agent(agent_id).get_basic_information()

    # Check if agent is active
    if agent_info['status'].lower() != 'active':
        raise WazuhError(1651,
                         extra_message='{0}'.format(agent_info['status']))

    # Once we know the agent is active, store version
    agent_version = agent_info['version']

    # Check if AR is enabled
    agent_conf = Agent(agent_id).getconfig('com', 'active-response',
                                           agent_version)
    if agent_conf['active-response']['disabled'] == 'yes':
        raise WazuhError(1750)

    # Create classic msg or JSON msg depending on the agent version
    if WazuhVersion(agent_version) >= WazuhVersion(common.AR_LEGACY_VERSION):
        msg_queue = create_json_message(command=command,
                                        arguments=arguments,
                                        alert=alert)
    else:
        msg_queue = create_message(command=command,
                                   arguments=arguments,
                                   custom=custom)

    oq.send_msg_to_agent(msg=msg_queue,
                         agent_id=agent_id,
                         msg_type=OssecQueue.AR_TYPE)
Exemple #5
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
Exemple #6
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