Пример #1
0
def remove_agents_from_group(agent_list=None, group_list=None):
    """Remove a list of agents assignment from a specified group.

    :param agent_list: List of agents ID's.
    :param group_list: List of Group names.
    :return: AffectedItemsWazuhResult.
    """
    group_id = group_list[0]
    result = AffectedItemsWazuhResult(
        all_msg=f'All selected agents were removed from group {group_id}',
        some_msg=f'Some agents were not removed from group {group_id}',
        none_msg=f'No agent was removed from group {group_id}')

    system_groups = get_groups()
    system_agents = get_agents_info()
    # Check if group exists
    if group_id not in system_groups:
        raise WazuhResourceNotFound(1710)

    for agent_id in agent_list:
        try:
            if agent_id == '000':
                raise WazuhError(1703)
            elif agent_id not in system_agents:
                raise WazuhResourceNotFound(1701)
            Agent.unset_single_group_agent(agent_id=agent_id,
                                           group_id=group_id,
                                           force=True)
            result.affected_items.append(agent_id)
        except WazuhException as e:
            result.add_failed_item(id_=agent_id, error=e)
    result.total_affected_items = len(result.affected_items)
    result.affected_items.sort(key=int)

    return result
Пример #2
0
def assign_agents_to_group(group_list=None, agent_list=None, replace=False, replace_list=None):
    """Assign a list of agents to a group.

    :param group_list: List of Group names.
    :param agent_list: List of Agent IDs.
    :param replace: Whether to append new group to current agent's group or replace it.
    :param replace_list: List of Group names that can be replaced.
    :return: AffectedItemsWazuhResult.
    """
    group_id = group_list[0]
    result = AffectedItemsWazuhResult(all_msg=f'All selected agents were assigned to {group_id}'
                                              f'{" and removed from the other groups" if replace else ""}',
                                      some_msg=f'Some agents were not assigned to {group_id}'
                                               f'{" and removed from the other groups" if replace else ""}',
                                      none_msg='No agents were assigned to {0}'.format(group_id)
                                      )
    # Check if the group exists
    if not Agent.group_exists(group_id):
        raise WazuhResourceNotFound(1710)
    system_agents = get_agents_info()
    for agent_id in agent_list:
        try:
            if agent_id not in system_agents:
                raise WazuhResourceNotFound(1701)
            if agent_id == "000":
                raise WazuhError(1703)
            Agent.add_group_to_agent(group_id, agent_id, force=True, replace=replace, replace_list=replace_list)
            result.affected_items.append(agent_id)
        except WazuhException as e:
            result.add_failed_item(id_=agent_id, error=e)

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

    return result
Пример #3
0
def get_agent_conf_multigroup(multigroup_id=None, offset=0, limit=common.database_limit, filename=None):
    """
    Returns agent.conf as dictionary.

    :return: agent.conf as dictionary.
    """
    # Check if a multigroup_id is provided and it exists
    if multigroup_id and not os_path.exists(os_path.join(common.multi_groups_path, multigroup_id)) or not multigroup_id:
        raise WazuhResourceNotFound(1710, extra_message=multigroup_id if multigroup_id else "No multigroup provided")

    agent_conf_name = filename if filename else 'agent.conf'
    agent_conf = os_path.join(common.multi_groups_path, multigroup_id, agent_conf_name)

    if not os_path.exists(agent_conf):
        raise WazuhError(1006, extra_message=os_path.join("WAZUH_PATH", "var", "multigroups", agent_conf))

    try:
        # Read XML
        xml_data = load_wazuh_xml(agent_conf)

        # Parse XML to JSON
        data = _agentconf2json(xml_data)
    except Exception:
        raise WazuhError(1101)

    return {'totalItems': len(data), 'items': cut_array(data, offset=offset, limit=limit)}
Пример #4
0
def delete_agents(agent_list=None, backup=False, purge=False, use_only_authd=False, filters=None, q=None):
    """Delete a list of agents.

    Parameters
    ----------
    agent_list : list
        List of agents ID's to be deleted.
    backup : bool
        Create backup before removing the agent.
    purge : bool
        Delete definitely from key store.
    use_only_authd : bool
        Force the use of authd when adding and removing agents.
    filters : dict
        Define required field filters. Format: {"field1":"value1", "field2":["value2","value3"]}
    q : str
        Define query to filter in DB.

    Returns
    -------
    result : AffectedItemsWazuhResult
        Result with affected agents.
    """
    result = AffectedItemsWazuhResult(all_msg='All selected agents were deleted',
                                      some_msg='Some agents were not deleted',
                                      none_msg='No agents were deleted'
                                      )
    if agent_list:
        system_agents = get_agents_info()
        rbac_filters = get_rbac_filters(system_resources=system_agents, permitted_resources=agent_list,
                                        filters=filters)

        db_query = WazuhDBQueryAgents(limit=None, select=["id"], query=q, **rbac_filters)
        data = db_query.run()
        can_purge_agents = list(map(operator.itemgetter('id'), data['items']))
        for agent_id in agent_list:
            try:
                if agent_id == "000":
                    raise WazuhError(1703)
                elif agent_id not in system_agents:
                    raise WazuhResourceNotFound(1701)
                elif agent_id not in can_purge_agents:
                    raise WazuhError(
                        1731,
                        extra_message="some of the requirements are not met -> {}".format(
                            ', '.join(f"{key}: {value}" for key, value in filters.items() if key != 'rbac_ids') +
                            (f', q: {q}' if q else '')
                        )
                    )
                else:
                    my_agent = Agent(agent_id)
                    my_agent.load_info_from_db()
                    my_agent.remove(backup=backup, purge=purge, use_only_authd=use_only_authd)
                    result.affected_items.append(agent_id)
            except WazuhException as e:
                result.add_failed_item(id_=agent_id, error=e)
        result.total_affected_items = len(result.affected_items)
        result.affected_items.sort(key=int)

    return result
Пример #5
0
def restart_agents(agent_list=None):
    """Restart a list of agents.

    :param agent_list: List of agents ID's.
    :return: AffectedItemsWazuhResult.
    """
    result = AffectedItemsWazuhResult(all_msg='Restart command was sent to all agents',
                                      some_msg='Restart command was not sent to some agents',
                                      none_msg='Restart command was not sent to any agent'
                                      )

    system_agents = get_agents_info()
    for agent_id in agent_list:
        try:
            if agent_id not in system_agents:
                raise WazuhResourceNotFound(1701)
            if agent_id == "000":
                raise WazuhError(1703)
            Agent(agent_id).restart()
            result.affected_items.append(agent_id)
        except WazuhException as e:
            result.add_failed_item(id_=agent_id, error=e)

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

    return result
Пример #6
0
def reconnect_agents(agent_list: Union[list, str] = None) -> AffectedItemsWazuhResult:
    """Force reconnect a list of agents.

    Parameters
    ----------
    agent_list : Union[list, str]
        List of agent IDs. All possible values from 000 onwards. Default `*`

    Returns
    -------
    AffectedItemsWazuhResult
    """
    result = AffectedItemsWazuhResult(all_msg='Force reconnect command was sent to all agents',
                                      some_msg='Force reconnect command was not sent to some agents',
                                      none_msg='Force reconnect command was not sent to any agent'
                                      )

    system_agents = get_agents_info()
    wq = WazuhQueue(common.ARQUEUE)
    for agent_id in agent_list:
        try:
            if agent_id not in system_agents:
                raise WazuhResourceNotFound(1701)
            if agent_id == "000":
                raise WazuhError(1703)
            Agent(agent_id).reconnect(wq)
            result.affected_items.append(agent_id)
        except WazuhException as e:
            result.add_failed_item(id_=agent_id, error=e)
    wq.close()

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

    return result
Пример #7
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
Пример #8
0
def delete_agents(agent_list=None,
                  backup=False,
                  purge=False,
                  status="all",
                  older_than="7d",
                  use_only_authd=False):
    """Deletes a list of agents.

    :param agent_list: List of agents ID's.
    :param backup: Create backup before removing the agent.
    :param purge: Delete definitely from key store.
    :param older_than:  Filters out disconnected agents for longer than specified. Time in seconds | "[n_days]d" |
    "[n_hours]h" | "[n_minutes]m" | "[n_seconds]s". For never_connected agents, uses the register date.
    :param status: Filters by agent status: active, disconnected or never_connected. Multiples statuses separated
    by commas.
    :param use_only_authd: Force the use of authd when adding and removing agents.
    :return: AffectedItemsWazuhResult.
    """
    result = AffectedItemsWazuhResult(
        all_msg='All selected agents were deleted',
        some_msg='Some agents were not deleted',
        none_msg='No agents were deleted')
    if len(agent_list) != 0:
        db_query = WazuhDBQueryAgents(limit=None,
                                      select=["id"],
                                      filters={
                                          'older_than': older_than,
                                          'status': status,
                                          'id': agent_list
                                      })
        data = db_query.run()
        can_purge_agents = list(map(operator.itemgetter('id'), data['items']))
        system_agents = get_agents_info()
        for agent_id in agent_list:
            try:
                if agent_id == "000":
                    raise WazuhError(1703)
                elif agent_id not in system_agents:
                    raise WazuhResourceNotFound(1701)
                else:
                    my_agent = Agent(agent_id)
                    my_agent.load_info_from_db()
                    if agent_id not in can_purge_agents:
                        raise WazuhError(
                            1731,
                            extra_message=
                            "The agent has a status different to '{0}' or the specified time "
                            "frame 'older_than {1}' does not apply".format(
                                status, older_than))
                    my_agent.remove(backup=backup,
                                    purge=purge,
                                    use_only_authd=use_only_authd)
                    result.affected_items.append(agent_id)
            except WazuhException as e:
                result.add_failed_item(id_=agent_id, error=e)
        result.total_affected_items = len(result.affected_items)
        result.affected_items.sort(key=int)
        result['older_than'] = older_than

    return result
Пример #9
0
def get_agents_component_stats_json(agent_list=None, component=None):
    """Get statistics of an agent's component.

    Parameters
    ----------
    agent_list: list, optional
        List of agents ID's, by default None.
    component: str, optional
        Name of the component to get stats from, by default None.

    Returns
    -------
    AffectedItemsWazuhResult
        Component stats.
    """
    result = AffectedItemsWazuhResult(
        all_msg='Statistical information for each agent was successfully read',
        some_msg='Could not read statistical information for some agents',
        none_msg='Could not read statistical information for any agent')
    system_agents = get_agents_info()
    for agent_id in agent_list:
        try:
            if agent_id not in system_agents:
                raise WazuhResourceNotFound(1701)
            result.affected_items.append(
                Agent(agent_id).get_stats(component=component))
        except WazuhException as e:
            result.add_failed_item(id_=agent_id, error=e)
    result.total_affected_items = len(result.affected_items)

    return result
Пример #10
0
def delete_groups(group_list=None):
    """Delete a list of groups and remove it from every agent assignments.

    :param group_list: List of Group names.
    :return: AffectedItemsWazuhResult.
    """
    result = AffectedItemsWazuhResult(all_msg='All selected groups were deleted',
                                      some_msg='Some groups were not deleted',
                                      none_msg='No group was deleted')

    system_groups = get_groups()
    for group_id in group_list:
        try:
            # Check if group exists
            if group_id not in system_groups:
                raise WazuhResourceNotFound(1710)
            elif group_id == 'default':
                raise WazuhError(1712)
            agent_list = [agent['id'] for agent in WazuhDBQueryMultigroups(group_id=group_id, limit=None).run()['items']]
            try:
                affected_agents_result = remove_agents_from_group(agent_list=agent_list, group_list=[group_id])
                if affected_agents_result.total_failed_items != 0:
                    raise WazuhError(4015)
            except WazuhError:
                raise WazuhError(4015)
            Agent.delete_single_group(group_id)
            affected_agents_result.affected_items.sort(key=int)
            result.affected_items.append({group_id: affected_agents_result.affected_items})
        except WazuhException as e:
            result.add_failed_item(id_=group_id, error=e)

    result.affected_items.sort(key=lambda x: next(iter(x)))
    result.total_affected_items = len(result.affected_items)

    return result
Пример #11
0
def get_agents_in_group(group_list,
                        offset=0,
                        limit=common.database_limit,
                        sort=None,
                        search=None,
                        select=None,
                        filters=None,
                        q=None):
    """Gets a list of available agents with basic attributes.

    :param group_list: Group ID.
    :param offset: First item to return.
    :param limit: Maximum number of items to return.
    :param sort: Sorts the items. Format: {"fields":["field1","field2"],"order":"asc|desc"}.
    :param select: Select fields to return. Format: {"fields":["field1","field2"]}.
    :param search: Looks for items with the specified string. Format: {"fields": ["field1","field2"]}.
    :param filters: Defines required field filters. Format: {"field1":"value1", "field2":["value2","value3"]}.
    :param q: Defines query to filter in DB.
    :return: AffectedItemsWazuhResult.
    """
    system_groups = get_groups()

    if group_list[0] not in system_groups:
        raise WazuhResourceNotFound(1710)

    q = 'group=' + group_list[0] + (';' + q if q else '')

    return get_agents(offset=offset,
                      limit=limit,
                      sort=sort,
                      search=search,
                      select=select,
                      filters=filters,
                      q=q)
Пример #12
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
Пример #13
0
def get_agent_conf(group_id=None, offset=0, limit=common.database_limit, filename='agent.conf', return_format=None):
    """
    Returns agent.conf as dictionary.

    :return: agent.conf as dictionary.
    """
    if not os_path.exists(os_path.join(common.shared_path, group_id)):
        raise WazuhResourceNotFound(1710, group_id)
    agent_conf = os_path.join(common.shared_path, group_id if group_id is not None else '', filename)

    if not os_path.exists(agent_conf):
        raise WazuhError(1006, agent_conf)

    try:
        # Read RAW file
        if filename == 'agent.conf' and return_format and 'xml' == return_format.lower():
            with open(agent_conf, 'r') as xml_data:
                data = xml_data.read()
                return data
        # Parse XML to JSON
        else:
            # Read XML
            xml_data = load_wazuh_xml(agent_conf)

            data = _agentconf2json(xml_data)
    except Exception as e:
        raise WazuhError(1101, str(e))

    return {'total_affected_items': len(data), 'affected_items': cut_array(data, offset=offset, limit=limit)}
Пример #14
0
def run(agent_list: Union[list, None] = None) -> AffectedItemsWazuhResult:
    """Run a rootcheck scan in the specified agents.

    Parameters
    ----------
    agent_list : Union[list, None]
         List of the agents IDs to run the scan for.

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

    system_agents = get_agents_info()
    rbac_filters = get_rbac_filters(system_resources=system_agents,
                                    permitted_resources=agent_list)
    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, error=WazuhResourceNotFound(1701))
        for agent in not_found_agents
    ]

    # Add non eligible agents to failed_items
    non_eligible_agents = WazuhDBQueryAgents(limit=None,
                                             select=["id", "status"],
                                             query=f'status!=active',
                                             **rbac_filters).run()['items']
    [
        result.add_failed_item(
            id_=agent['id'],
            error=WazuhError(1601,
                             extra_message=f'Status - {agent["status"]}'))
        for agent in non_eligible_agents
    ]

    wq = WazuhQueue(common.ARQUEUE)
    eligible_agents = agent_list - not_found_agents - {
        d['id']
        for d in non_eligible_agents
    }
    for agent_id in eligible_agents:
        try:
            wq.send_msg_to_agent(WazuhQueue.HC_SK_RESTART, agent_id)
            result.affected_items.append(agent_id)
        except WazuhError as e:
            result.add_failed_item(id_=agent_id, error=e)
    wq.close()
    result.affected_items.sort(key=int)
    result.total_affected_items = len(result.affected_items)

    return result
Пример #15
0
    def add_group_to_agent(group_id,
                           agent_id,
                           force=False,
                           replace=False,
                           replace_list=None):
        """Adds an existing group to an agent

        :param group_id: name of the group.
        :param agent_id: ID of the agent.
        :param force: Do not check if agent exists
        :param replace: Whether to append new group to current agent's group or replace it.
        :param replace_list: List of Group names that can be replaced
        :return: Agent ID.
        """
        agent = Agent(agent_id)
        if replace_list is None:
            replace_list = []
        if not force:
            # Check if agent exists, it is not 000 and the group exists
            if agent_id == "000":
                raise WazuhError(1703)

            if not Agent.group_exists(group_id):
                raise WazuhResourceNotFound(1710)

        # Get agent's group
        group_path = path.join(common.groups_path, agent_id)
        try:
            with open(group_path) as f:
                multigroup_name = f.read().strip()
        except Exception as e:
            # Check if agent is never_connected.
            agent.load_info_from_db()
            if agent.status == 'never_connected':
                raise WazuhError(1753)
            raise WazuhInternalError(1005, extra_message=str(e))
        agent_groups = set(multigroup_name.split(','))

        if replace:
            if agent_groups.issubset(set(replace_list)):
                multigroup_name = group_id
            else:
                raise WazuhError(1752)
        else:
            # Check if the group already belongs to the agent
            if group_id in agent_groups:
                raise WazuhError(1751)

            multigroup_name = f'{multigroup_name}{"," if multigroup_name else ""}{group_id}'

        # Check multigroup limit
        if len(agent_groups) > common.max_groups_per_multigroup:
            raise WazuhError(1737)

        # Update group file
        Agent.set_agent_group_file(agent_id, multigroup_name)

        return f"Agent {agent_id} assigned to {group_id}"
Пример #16
0
def get_agent_groups(group_list=None,
                     offset=0,
                     limit=None,
                     sort=None,
                     search=None,
                     hash_algorithm='md5'):
    """Gets the existing groups.

    :param group_list: List of Group names.
    :param offset: First item to return.
    :param limit: Maximum number of items to return.
    :param sort: Fields to sort the items by.
    :param search: Text to search.
    :param hash_algorithm: hash algorithm used to get mergedsum and configsum.
    :return: AffectedItemsWazuhResult.
    """
    affected_groups = list()
    result = AffectedItemsWazuhResult(
        all_msg='All selected groups information was returned',
        some_msg='Some groups information was not returned',
        none_msg='No group information was returned')
    if group_list:

        # Add failed items
        for invalid_group in set(group_list) - get_groups():
            result.add_failed_item(id_=invalid_group,
                                   error=WazuhResourceNotFound(1710))

        rbac_filters = get_rbac_filters(system_resources=get_groups(),
                                        permitted_resources=group_list)

        group_query = WazuhDBQueryGroup(offset=offset,
                                        limit=limit,
                                        sort=sort,
                                        search=search,
                                        **rbac_filters)
        query_data = group_query.run()

        for group in query_data['items']:
            full_entry = path.join(common.shared_path, group['name'])

            # merged.mg and agent.conf sum
            merged_sum = get_hash(path.join(full_entry, "merged.mg"),
                                  hash_algorithm)
            conf_sum = get_hash(path.join(full_entry, "agent.conf"),
                                hash_algorithm)

            if merged_sum:
                group['mergedSum'] = merged_sum

            if conf_sum:
                group['configSum'] = conf_sum
            affected_groups.append(group)

        result.affected_items = affected_groups
        result.total_affected_items = query_data['totalItems']

    return result
Пример #17
0
def get_group_files(group_list=None, offset=0, limit=None, search_text=None, search_in_fields=None,
                    complementary_search=False, sort_by=None, sort_ascending=True, hash_algorithm='md5'):
    """Gets the group files.

    :param group_list: List of Group names.
    :param offset: First item to return.
    :param limit: Maximum number of items to return.
    :param sort_by: Fields to sort the items by.
    :param sort_ascending: Sort in ascending (true) or descending (false) order.
    :param search_text: Text to search.
    :param complementary_search: Find items without the text to search.
    :param search_in_fields: Fields to search in.
    :param hash_algorithm: hash algorithm used to get mergedsum and configsum.
    :return: WazuhResult.
    """
    # We access unique group_id from list, this may change if and when we decide to add option to get files for
    # a list of groups
    group_id = group_list[0]
    group_path = common.shared_path
    result = AffectedItemsWazuhResult(all_msg='All selected groups files were returned',
                                      some_msg='Some groups files were not returned',
                                      none_msg='No groups files were returned'
                                      )
    if group_id:
        if not Agent.group_exists(group_id):
            result.add_failed_item(id_=group_id, error=WazuhResourceNotFound(1710))
            return result
        group_path = path.join(common.shared_path, group_id)

    if not path.exists(group_path):
        result.add_failed_item(id_=group_path, error=WazuhError(1006))
        return result

    try:
        data = []
        for entry in listdir(group_path):
            item = dict()
            item['filename'] = entry
            item['hash'] = get_hash(path.join(group_path, entry), hash_algorithm)
            data.append(item)

        # ar.conf
        ar_path = path.join(common.shared_path, 'ar.conf')
        data.append({'filename': "ar.conf", 'hash': get_hash(ar_path, hash_algorithm)})
        data = process_array(data, search_text=search_text, search_in_fields=search_in_fields,
                             complementary_search=complementary_search, sort_by=sort_by,
                             sort_ascending=sort_ascending, offset=offset, limit=limit)
        result.affected_items = data['items']
        result.total_affected_items = data['totalItems']
    except WazuhError as e:
        result.add_failed_item(id_=group_path, error=e)
        raise e
    except Exception as e:
        raise WazuhInternalError(1727, extra_message=str(e))

    return result
Пример #18
0
def remove_agent_from_group(group_list=None, agent_list=None):
    """Removes an agent assignment from a specified group.

    :param group_list: List of Group names.
    :param agent_list: List of Agent IDs.
    :return: Confirmation message.
    """
    group_id = group_list[0]
    agent_id = agent_list[0]

    # Check if agent and group exist and it is not 000
    if agent_id not in get_agents_info():
        raise WazuhResourceNotFound(1701)
    if agent_id == '000':
        raise WazuhError(1703)
    if group_id not in get_groups():
        raise WazuhResourceNotFound(1710)

    return WazuhResult({'message': Agent.unset_single_group_agent(agent_id=agent_id, group_id=group_id, force=True)})
Пример #19
0
def get_ciscat_results(agent_list=None, offset=0, limit=common.database_limit, select=None, search=None, sort=None,
                       filters=None, nested=True, array=True, q=''):
    """ Get CIS-CAT results for a list of agents

    :param agent_list: list of Agent ID to get scan results from. Currently, only first item will be considered
    :param offset: First element to return in the collection
    :param limit: Maximum number of elements to return
    :param select: Select which fields to return
    :param search: Looks for items with the specified string. Begins with '-' for a complementary search
    :param sort: Sorts the items. Format: {"fields":["field1","field2"],"order":"asc|desc"}
    :param filters: Fields to filter by
    :param nested: Nested fields
    :param array: Array
    :param q: Defines query to filter in DB.
    :return: AffectedItemsWazuhResult
    """
    result = AffectedItemsWazuhResult(
        all_msg='All CISCAT results were returned',
        some_msg='Some CISCAT results were not returned',
        none_msg='No CISCAT results were returned',
        sort_fields=['agent_id'] if sort is None else sort['fields'],
        sort_casting=['str'],
        sort_ascending=[sort['order'] == 'asc' for _ in sort['fields']] if sort is not None else ['True']
    )

    valid_select_fields = {'scan.id': 'scan_id', 'scan.time': 'scan_time', 'benchmark': 'benchmark',
                           'profile': 'profile', 'pass': '******', 'fail': 'fail', 'error': 'error',
                           'notchecked': 'notchecked', 'unknown': 'unknown', 'score': 'score'}
    table = 'ciscat_results'

    system_agents = get_agents_info()
    for agent in agent_list:
        try:
            if agent not in system_agents:
                raise WazuhResourceNotFound(1701)
            db_query = WazuhDBQuerySyscollector(agent_id=agent, offset=offset, limit=limit, select=select,
                                                search=search,
                                                sort=sort, filters=filters, fields=valid_select_fields, table=table,
                                                array=array, nested=nested, query=q)
            data = db_query.run()

            if len(data['items']) > 0:
                for item in data['items']:
                    item['agent_id'] = agent
                    result.affected_items.append(item)
                result.total_affected_items += data['totalItems']
        except WazuhResourceNotFound as e:
            result.add_failed_item(id_=agent, error=e)

    result.affected_items = merge(*[[res] for res in result.affected_items],
                                  criteria=result.sort_fields,
                                  ascending=result.sort_ascending,
                                  types=result.sort_casting)

    return result
Пример #20
0
def remove_agent_from_groups(agent_list=None, group_list=None):
    """Removes an agent assigment from a list of groups.

    :param agent_list: List of agents ID's.
    :param group_list: List of Group names.
    :return: AffectedItemsWazuhResult.
    """
    agent_id = agent_list[0]
    result = AffectedItemsWazuhResult(
        all_msg='Specified agent was removed from returned groups',
        some_msg='Specified agent was not removed from some groups',
        none_msg='Specified agent was not removed from any group')

    # Check if agent exists and it is not 000
    if agent_id == '000':
        raise WazuhError(1703)
    if agent_id not in get_agents_info():
        raise WazuhResourceNotFound(1701)

    # We move default group to last position in case it is contained in group_list. When an agent is removed from all
    # groups it is reverted to 'default'. We try default last to avoid removing it and then adding again.
    try:
        group_list.append(group_list.pop(group_list.index('default')))
    except ValueError:
        pass

    system_groups = get_groups()
    for group_id in group_list:
        try:
            if group_id not in system_groups:
                raise WazuhResourceNotFound(1710)
            Agent.unset_single_group_agent(agent_id=agent_id,
                                           group_id=group_id,
                                           force=True)
            result.affected_items.append(group_id)
        except WazuhException as e:
            result.add_failed_item(id_=group_id, error=e)
    result.total_affected_items = len(result.affected_items)
    result.affected_items.sort()

    return result
Пример #21
0
def test_check_experimental_feature_value(mock_exc):
    @check_experimental_feature_value
    def func_():
        pass

    with patch('api.configuration.api_conf',
               new={'experimental_features': False}):
        func_()
        mock_exc.assert_called_once_with(WazuhResourceNotFound(code=1122))
    with patch('api.configuration.api_conf',
               new={'experimental_features': True}):
        func_()
Пример #22
0
def get_file_conf(filename, group_id=None, type_conf=None, return_format=None):
    """
    Returns the configuration file as dictionary.

    :return: configuration file as dictionary.
    """
    if not os_path.exists(os_path.join(common.shared_path, group_id)):
        raise WazuhResourceNotFound(1710, group_id)

    file_path = os_path.join(common.shared_path,
                             group_id if not filename == 'ar.conf' else '',
                             filename)

    if not os_path.exists(file_path):
        raise WazuhError(1006, file_path)

    types = {
        'conf': get_agent_conf,
        'rootkit_files': _rootkit_files2json,
        'rootkit_trojans': _rootkit_trojans2json,
        'rcl': _rcl2json
    }

    if type_conf:
        if type_conf in types:
            if type_conf == 'conf':
                data = types[type_conf](group_id,
                                        limit=None,
                                        filename=filename,
                                        return_format=return_format)
            else:
                data = types[type_conf](file_path)
        else:
            raise WazuhError(
                1104, "{0}. Valid types: {1}".format(type_conf, types.keys()))
    else:
        if filename == "agent.conf":
            data = get_agent_conf(group_id,
                                  limit=None,
                                  filename=filename,
                                  return_format=return_format)
        elif filename == "rootkit_files.txt":
            data = _rootkit_files2json(file_path)
        elif filename == "rootkit_trojans.txt":
            data = _rootkit_trojans2json(file_path)
        elif filename == "ar.conf":
            data = _ar_conf2json(file_path)
        else:
            data = _rcl2json(file_path)

    return data
Пример #23
0
def get_agents(agent_list=None,
               offset=0,
               limit=common.database_limit,
               sort=None,
               search=None,
               select=None,
               filters=None,
               q=None):
    """Gets a list of available agents with basic attributes.

    :param agent_list: List of agents ID's.
    :param offset: First item to return.
    :param limit: Maximum number of items to return.
    :param sort: Sorts the items. Format: {"fields":["field1","field2"],"order":"asc|desc"}.
    :param select: Select fields to return. Format: {"fields":["field1","field2"]}.
    :param search: Looks for items with the specified string. Format: {"fields": ["field1","field2"]}
    :param filters: Defines required field filters. Format: {"field1":"value1", "field2":["value2","value3"]}
    :param q: Defines query to filter in DB.
    :return: AffectedItemsWazuhResult.
    """
    result = AffectedItemsWazuhResult(
        all_msg='All selected agents information was returned',
        some_msg='Some agents information was not returned',
        none_msg='No agent information was returned')
    if agent_list:
        if filters is None:
            filters = dict()

        system_agents = get_agents_info()

        for agent_id in agent_list:
            if agent_id not in system_agents:
                result.add_failed_item(id_=agent_id,
                                       error=WazuhResourceNotFound(1701))

        rbac_filters = get_rbac_filters(system_resources=system_agents,
                                        permitted_resources=agent_list,
                                        filters=filters)

        db_query = WazuhDBQueryAgents(offset=offset,
                                      limit=limit,
                                      sort=sort,
                                      search=search,
                                      select=select,
                                      query=q,
                                      **rbac_filters)
        data = db_query.run()
        result.affected_items.extend(data['items'])
        result.total_affected_items = data['totalItems']

    return result
Пример #24
0
def get_item_agent(agent_list, offset=0, limit=common.database_limit, select=None, search=None, sort=None, filters=None,
                   q='', array=True, nested=True, element_type='os'):
    """ Get syscollector information about a list of agents.

    :param agent_list: List of agents ID's.
    :param offset: First item to return.
    :param limit: Maximum number of items to return.
    :param sort: Sorts the items. Format: {"fields":["field1","field2"],"order":"asc|desc"}.
    :param select: Select fields to return. Format: {"fields":["field1","field2"]}.
    :param search: Looks for items with the specified string. Format: {"fields": ["field1","field2"]}
    :param q: Defines query to filter in DB.
    :param filters: Fields to filter by
    :param nested: Nested fields
    :param array: Array
    :param element_type: Type of element to get syscollector information from
    :return: AffectedItemsWazuhResult
    """
    result = AffectedItemsWazuhResult(
        none_msg='No syscollector information was returned',
        some_msg='Some syscollector information was not returned',
        all_msg='All specified syscollector information was returned',
        sort_fields=['agent_id'] if sort is None else sort['fields'],
        sort_casting=['str'],
        sort_ascending=[sort['order'] == 'asc' for _ in sort['fields']] if sort is not None else ['True']
    )

    for agent in agent_list:
        try:
            if agent not in get_agents_info():
                raise WazuhResourceNotFound(1701)
            table, valid_select_fields = get_valid_fields(Type(element_type), agent_id=agent)
            db_query = WazuhDBQuerySyscollector(agent_id=agent, offset=offset, limit=limit, select=select,
                                                search=search,
                                                sort=sort, filters=filters, fields=valid_select_fields, table=table,
                                                array=array, nested=nested, query=q)
            data = db_query.run()
            for item in data['items']:
                item['agent_id'] = agent
                result.affected_items.append(item)
            result.total_affected_items += data['totalItems']
        except WazuhResourceNotFound as e:
            result.add_failed_item(id_=agent, error=e)

    result.affected_items = merge(*[[res] for res in result.affected_items],
                                  criteria=result.sort_fields,
                                  ascending=result.sort_ascending,
                                  types=result.sort_casting)

    return result
Пример #25
0
def run_command(agent_list: list = None,
                command: str = '',
                arguments: list = None,
                custom: bool = False,
                alert: dict = None) -> AffectedItemsWazuhResult:
    """Run AR command in a specific agent.

    Parameters
    ----------
    agent_list : list
        Agents list that will run the AR command.
    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.

    Returns
    -------
    AffectedItemsWazuhResult.
    """
    result = AffectedItemsWazuhResult(
        all_msg='AR command was sent to all agents',
        some_msg='AR command was not sent to some agents',
        none_msg='AR command was not sent to any agent')
    if agent_list:
        wq = WazuhQueue(common.ARQUEUE)
        system_agents = get_agents_info()
        for agent_id in agent_list:
            try:
                if agent_id not in system_agents:
                    raise WazuhResourceNotFound(1701)
                if agent_id == "000":
                    raise WazuhError(1703)
                active_response.send_ar_message(agent_id, wq, command,
                                                arguments, custom, alert)
                result.affected_items.append(agent_id)
                result.total_affected_items += 1
            except WazuhException as e:
                result.add_failed_item(id_=agent_id, error=e)
        result.affected_items.sort(key=int)
        wq.close()

    return result
Пример #26
0
def get_agents_sync_group(agent_list=None):
    """Get agents configuration sync status.

    :param agent_list: List of agents ID's.
    :return AffectedItemsWazuhResult.
    """
    result = AffectedItemsWazuhResult(
        all_msg='Sync info was returned for all selected agents',
        some_msg='Sync info was not returned for some selected agents',
        none_msg='No sync info was returned',
    )

    system_agents = get_agents_info()
    for agent_id in agent_list:
        try:
            if agent_id == "000":
                raise WazuhError(1703)
            if agent_id not in system_agents:
                raise WazuhResourceNotFound(1701)
            else:
                # Check if agent exists and it is active
                agent_info = Agent(agent_id).get_basic_information()
                # Check if it has a multigroup
                if len(agent_info['group']) > 1:
                    multi_group = ','.join(agent_info['group'])
                    multi_group = hashlib.sha256(
                        multi_group.encode()).hexdigest()[:8]
                    group_merged_path = path.join(common.multi_groups_path,
                                                  multi_group, "merged.mg")
                else:
                    group_merged_path = path.join(common.shared_path,
                                                  agent_info['group'][0],
                                                  "merged.mg")
                result.affected_items.append({
                    'id':
                    agent_id,
                    'synced':
                    md5(group_merged_path) == agent_info['mergedSum']
                })
        except (IOError, KeyError):
            # The file couldn't be opened and therefore the group has not been synced
            result.affected_items.append({'id': agent_id, 'synced': False})
        except WazuhException as e:
            result.add_failed_item(id_=agent_id, error=e)

    result.total_affected_items = len(result.affected_items)

    return result
Пример #27
0
def get_sca_list(agent_list=None,
                 q="",
                 offset=0,
                 limit=common.database_limit,
                 sort=None,
                 search=None,
                 select=None,
                 filters=None):
    """ Get a list of policies analyzed in the configuration assessment for a given agent

    :param agent_list: agent id to get policies from
    :param q: Defines query to filter in DB.
    :param offset: First item to return.
    :param limit: Maximum number of items to return.
    :param sort: Sorts the items. Format: {"fields":["field1","field2"],"order":"asc|desc"}.
    :param search: Looks for items with the specified string. Format: {"fields": ["field1","field2"]}
    :param select: Select fields to return. Format: {"fields":["field1","field2"]}.
    :param filters: Define field filters required by the user. Format: {"field1":"value1", "field2":["value2","value3"]}
    :return: AffectedItemsWazuhResult
    """
    result = AffectedItemsWazuhResult(
        all_msg='All selected sca information was returned',
        some_msg='Some sca information was not returned',
        none_msg='No sca information was returned')

    if len(agent_list) != 0:
        if agent_list[0] in get_agents_info():
            select = list(
                fields_translation_sca.keys()) if select is None else select

            db_query = WazuhDBQuerySCA(agent_id=agent_list[0],
                                       offset=offset,
                                       limit=limit,
                                       sort=sort,
                                       search=search,
                                       select=select,
                                       count=True,
                                       get_data=True,
                                       query=q,
                                       filters=filters)
            data = db_query.run()
            result.affected_items.extend(data['items'])
            result.total_affected_items = data['totalItems']
        else:
            result.add_failed_item(id_=agent_list[0],
                                   error=WazuhResourceNotFound(1701))

    return result
Пример #28
0
async def test_get_nodes_info():
    """Verify that get_nodes_info returns the information of all nodes."""
    async def valid_node(lc=None, filter_node=None):
        return {'items': ['master', 'worker1'], 'totalItems': 2}

    local_client = LocalClient()
    common.cluster_nodes.set(['master', 'worker1', 'worker2'])
    with patch('wazuh.cluster.get_nodes', side_effect=valid_node):
        result = await cluster.get_nodes_info(
            lc=local_client, filter_node=['master', 'worker1', 'noexists'])
    expected = await valid_node()

    assert result.affected_items == expected['items']
    assert result.total_affected_items == expected['totalItems']
    assert result.failed_items[WazuhResourceNotFound(1730)] == {'noexists'}
    assert result.total_failed_items == 1
Пример #29
0
def remove_user_role(user_id, role_ids):
    """Remove a relationship between a user and a role.

    Parameters
    ----------
    user_id : list
        User ID
    role_ids : list of int
        List of role ids

    Returns
    -------
    Dict
        User-Roles information
    """
    username = get_username(user_id=user_id)
    if username == 'unknown':
        raise WazuhResourceNotFound(5001)

    result = AffectedItemsWazuhResult(
        none_msg=f'No role was unlinked from user {username}',
        some_msg=f'Some roles were not unlinked from user {username}',
        all_msg=f'All roles were unlinked from user {username}')
    success = False
    with UserRolesManager() as urm:
        for role_id in role_ids:
            user_role = urm.remove_role_in_user(user_id=int(user_id[0]),
                                                role_id=role_id)
            if user_role == SecurityError.INVALID:
                result.add_failed_item(id_=int(role_id),
                                       error=WazuhError(4016))
            elif user_role == SecurityError.ROLE_NOT_EXIST:
                result.add_failed_item(id_=int(role_id),
                                       error=WazuhError(4002))
            elif user_role == SecurityError.ADMIN_RESOURCES:
                result.add_failed_item(id_=int(user_id[0]),
                                       error=WazuhError(4008))
            else:
                success = True
                result.total_affected_items += 1
        if success:
            with AuthenticationManager() as auth:
                result.affected_items.append(auth.get_user_id(int(user_id[0])))
            result.affected_items.sort(key=str)
            invalid_users_tokens(users=user_id)

    return result
Пример #30
0
def get_agent_by_name(name=None, select=None):
    """Gets an agent by its name.

    :param name: Agent_name.
    :param select: Select fields to return. Format: {"fields":["field1","field2"]}.
    :return: AffectedItemsWazuhResult.
    """
    db_query = WazuhDBQueryAgents(filters={'name': name})
    data = db_query.run()
    try:
        agent = data['items'][0]['id']
        return get_agents(agent_list=[agent], select=select)
    except IndexError:
        raise WazuhResourceNotFound(1754)
    except Exception as e:
        if e.code == 4000:
            raise WazuhPermissionError(4000)
        raise e