def get_agents_summary_status(agent_list=None): """Count the number of agents by status. Parameters ---------- agent_list : list[str] List of agents ID's Returns ------- WazuhResult """ summary = { 'active': 0, 'disconnected': 0, 'never_connected': 0, 'pending': 0, 'total': 0 } if agent_list: rbac_filters = get_rbac_filters(system_resources=get_agents_info(), permitted_resources=agent_list) # We don't consider agent 000 in order to get the summary db_query = WazuhDBQueryAgents(limit=None, select=['status'], query="id!=000", **rbac_filters) data = db_query.run() for agent in data['items']: summary[agent['status']] += 1 summary['total'] += 1 return WazuhResult({'data': summary})
def get_outdated_agents(agent_list=None, offset=0, limit=common.database_limit, sort=None, search=None, select=None, q=None): """Gets the outdated 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 search: Looks for items with the specified string. :param select: Select fields to return. Format: {"fields":["field1","field2"]}. :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: # Get manager version manager = Agent(id='000') manager.load_info_from_db() select = ['version', 'id', 'name'] if select is None else select rbac_filters = get_rbac_filters(system_resources=get_agents_info(), permitted_resources=agent_list) db_query = WazuhDBQueryAgents(offset=offset, limit=limit, sort=sort, search=search, select=select, query=f"version!={manager.version}" + (';' + q if q else ''), **rbac_filters) data = db_query.run() result.affected_items = data['items'] result.total_affected_items = data['totalItems'] return result
def get_agents_summary_os(agent_list=None): """Get a list of available OS. Parameters ---------- agent_list : list[str] List of agents ID's Returns ------- WazuhResult """ result = AffectedItemsWazuhResult( none_msg='Could not get the operative system of the agents', all_msg='Showing the operative system of all specified agents', some_msg='Could not get the operative system of some agents') if agent_list: rbac_filters = get_rbac_filters(system_resources=get_agents_info(), permitted_resources=agent_list) # We don't consider agent 000 in order to get the summary db_query = WazuhDBQueryAgents(select=['os.platform'], default_sort_field='os_platform', min_select_fields=set(), distinct=True, query="id!=000", **rbac_filters) query_data = db_query.run() query_data['items'] = [ row['os']['platform'] for row in query_data['items'] ] result.affected_items = query_data['items'] result.total_affected_items = len(result.affected_items) return result
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
def get_distinct_agents(agent_list=None, offset=0, limit=common.database_limit, sort=None, search=None, select=None, fields=None, q=None): """ Gets all the different combinations that all system agents have for the selected fields. It also indicates the total number of agents that have each combination. :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 fields: Fields to group by :return: WazuhResult """ 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: rbac_filters = get_rbac_filters(system_resources=get_agents_info(), permitted_resources=agent_list) db_query = WazuhDBQueryGroupByAgents(filter_fields=fields, offset=offset, limit=limit, sort=sort, search=search, select=select, query=q, min_select_fields=set(), count=True, get_data=True, **rbac_filters) data = db_query.run() result.affected_items.extend(data['items']) result.total_affected_items = data['totalItems'] return result
def get_agents_summary_status(agent_list=None): """Counts the number of agents by status. :param agent_list: List of agents ID's. :return: WazuhResult. """ summary = { 'active': 0, 'disconnected': 0, 'never_connected': 0, 'pending': 0, 'total': 0 } if len(agent_list) != 0: rbac_filters = get_rbac_filters(system_resources=get_agents_info(), permitted_resources=agent_list) db_query = WazuhDBQueryAgents(limit=None, select=['status'], **rbac_filters) data = db_query.run() for agent in data['items']: summary[agent['status']] += 1 summary['total'] += 1 return WazuhResult({'data': summary})
def get_agents_summary_os(agent_list=None): """Gets a list of available OS. :param agent_list: List of agents ID's. :return: WazuhResult. """ result = AffectedItemsWazuhResult( none_msg='Could not get the operative system of the agents', all_msg='Showing the operative system of all specified agents', some_msg='Could not get the operative system of some agents') if len(agent_list) != 0: rbac_filters = get_rbac_filters(system_resources=get_agents_info(), permitted_resources=agent_list) db_query = WazuhDBQueryAgents(select=['os.platform'], default_sort_field='os_platform', min_select_fields=set(), distinct=True, **rbac_filters) query_data = db_query.run() query_data['items'] = [ row['os']['platform'] for row in query_data['items'] ] result.affected_items = query_data['items'] result.total_affected_items = len(result.affected_items) return result
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
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
def get_distinct_agents(agent_list: list = None, offset: int = 0, limit: int = common.database_limit, sort: str = None, search: str = None, fields: str = None, q: str = None) -> AffectedItemsWazuhResult: """Get all the different combinations that all system agents have for the selected fields. It also indicates the total number of agents that have each combination. Parameters ---------- agent_list : list List of agents ID's. fields : str List of fields to group by. offset : int First item to return. limit : int Maximum number of items to return. sort : str Sorts the items. Format: {"fields":["field1","field2"],"order":"asc|desc"}. search : str Looks for items with the specified string. Format: {"fields": ["field1","field2"]}. q : str Query to filter results by. For example q="status=active" Returns ------- 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: rbac_filters = get_rbac_filters(system_resources=get_agents_info(), permitted_resources=agent_list) db_query = WazuhDBQueryGroupByAgents(filter_fields=fields, select=fields, offset=offset, limit=limit, sort=sort, search=search, query=q, min_select_fields=set(), count=True, get_data=True, **rbac_filters) data = db_query.run() result.affected_items.extend(data['items']) result.total_affected_items = data['totalItems'] return result
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
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: system_agents = get_agents_info() filters = {'older_than': older_than, 'status': status} rbac_filters = get_rbac_filters(system_resources=system_agents, permitted_resources=agent_list, filters=filters) db_query = WazuhDBQueryAgents(limit=None, select=["id"], **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) 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
def restart_agents(agent_list: list = None) -> AffectedItemsWazuhResult: """Restart a list of agents. Parameters ---------- agent_list : list List of agents IDs. Raises ------ WazuhError(1703) If the agent to be restarted is 000. WazuhError(1701) If the agent to be restarted is not in the system. WazuhError(1707) If the agent to be restarted is not active. Returns ------- 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') agent_list = set(agent_list) # Add agent with ID 000 to failed_items try: agent_list.remove('000') result.add_failed_item('000', WazuhError(1703)) except KeyError: pass if agent_list: system_agents = get_agents_info() rbac_filters = get_rbac_filters(system_resources=system_agents, permitted_resources=list(agent_list)) agents_with_data = WazuhDBQueryAgents( limit=None, select=["id", "status", "version"], **rbac_filters).run()['items'] # Add non existent agents to failed_items not_found_agents = agent_list - system_agents [ result.add_failed_item(id_=agent, error=WazuhResourceNotFound(1701)) for agent in not_found_agents ] # Add non active agents to failed_items non_active_agents = [ agent for agent in agents_with_data if agent['status'] != 'active' ] [ result.add_failed_item(id_=agent['id'], error=WazuhError( 1707, extra_message=f'{agent["status"]}')) for agent in non_active_agents ] eligible_agents = [agent for agent in agents_with_data if agent not in non_active_agents] if non_active_agents \ else agents_with_data wq = WazuhQueue(common.ARQUEUE) for agent in eligible_agents: try: send_restart_command(agent['id'], agent['version'], 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
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