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
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
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 run(agent_list=None): """Run syscheck scan. :param agent_list: Run syscheck in the agent. :return: AffectedItemsWazuhResult. """ result = AffectedItemsWazuhResult(all_msg='Syscheck scan was restarted on returned agents', some_msg='Syscheck scan was not restarted on some agents', none_msg='No syscheck scan was restarted') for agent_id in agent_list: try: agent_info = Agent(agent_id).get_basic_information() agent_status = agent_info.get('status', 'N/A') if agent_status.lower() != 'active': result.add_failed_item( id_=agent_id, error=WazuhError(1601, extra_message='Status - {}'.format(agent_status))) else: oq = OssecQueue(common.ARQUEUE) oq.send_msg_to_agent(OssecQueue.HC_SK_RESTART, agent_id) result.affected_items.append(agent_id) oq.close() except WazuhError as e: result.add_failed_item(id_=agent_id, error=e) result.affected_items = sorted(result.affected_items, key=int) result.total_affected_items = len(result.affected_items) return result
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
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)
def test_failed_remove_single_group_agent(agent_patch, get_groups_patch, agent_groups, agent_id, group_id, expected_exception): with pytest.raises(WazuhException, match=f'.* {expected_exception} .*'): get_groups_patch.return_value = agent_groups agent_patch.return_value = AgentMock(agent_id, agent_groups) Agent.unset_single_group_agent(agent_id, group_id, force=False)
def show_groups(): groups_data = Agent.get_all_groups(limit=None) print("Groups ({0}):".format(groups_data['totalItems'])) for g in groups_data['items']: print(" {0} ({1})".format(g['name'], g['count'])) print("Unassigned agents: {0}.".format( Agent.get_agents_without_group()['totalItems']))
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
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
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
def add_agent(name=None, agent_id=None, key=None, ip='any', force_time=-1, use_only_authd=False): """Adds a new Wazuh agent. :param name: name of the new agent. :param agent_id: id of the new agent. :param ip: IP of the new agent. It can be an IP, IP/NET or ANY. :param key: key of the new agent. :param force_time: Remove old agent with same IP if disconnected since <force_time> seconds. :param use_only_authd: Force the use of authd when adding and removing agents. :return: Agent ID and Agent key. """ # Check length of agent name if len(name) > 128: raise WazuhError(1738) new_agent = Agent(name=name, ip=ip, id=agent_id, key=key, force=force_time, use_only_authd=use_only_authd) return WazuhResult({'data': {'id': new_agent.id, 'key': new_agent.key}})
def upgrade_agents(agent_list=None, wpk_repo=None, version=None, force=False, chunk_size=None, use_http=False): """Read upgrade result output from agent. :param agent_list: List of agents ID's. :param wpk_repo: URL for WPK download. :param version: Version to upgrade to. :param force: force the update even if it is a downgrade. :param chunk_size: size of each update chunk. :param use_http: False for HTTPS protocol, True for HTTP protocol. :return: Upgrade message. """ # We access unique agent_id from list, this may change if and when we decide to add option to upgrade a list of # agents agent_id = agent_list[0] return Agent(agent_id).upgrade(wpk_repo=wpk_repo, version=version, force=True if int(force) == 1 else False, chunk_size=chunk_size, use_http=use_http)
def last_scan(agent_id): """Get the last rootcheck scan of an agent. :param agent_id: Agent ID. :return: Dictionary: end, start. """ Agent(agent_id).get_basic_information() wdb_conn = WazuhDBConnection() # end time result = wdb_conn.execute( f"agent {agent_id} sql SELECT max(date_last) FROM pm_event WHERE " "log = 'Ending rootcheck scan.'") time = list(result[0].values())[0] if result else None end = datetime.utcfromtimestamp(time).strftime( date_format) if time is not None else None # start time result = wdb_conn.execute( f"agent {agent_id} sql SELECT max(date_last) FROM pm_event " "WHERE log = 'Starting rootcheck scan.'") time = list(result[0].values())[0] if result else None start = datetime.utcfromtimestamp(time).strftime( date_format) if time is not None else None return { 'start': start, 'end': None if start is None else None if end is None or end < start else end }
def get_health(self, filter_node) -> Dict: """ Return healthcheck data :param filter_node: Node to filter by :return: Dictionary """ workers_info = { key: val.to_dict() for key, val in self.clients.items() if filter_node is None or filter_node == {} or key in filter_node } n_connected_nodes = len(workers_info) if filter_node is None or self.configuration[ 'node_name'] in filter_node: workers_info.update( {self.configuration['node_name']: self.to_dict()}) # Get active agents by node and format last keep alive date format for node_name in workers_info.keys(): workers_info[node_name]["info"][ "n_active_agents"] = Agent.get_agents_overview( filters={ 'status': 'active', 'node_name': node_name })['totalItems'] if workers_info[node_name]['info']['type'] != 'master': workers_info[node_name]['status']['last_keep_alive'] = str( datetime.fromtimestamp( workers_info[node_name]['status']['last_keep_alive'])) return {"n_connected_nodes": n_connected_nodes, "nodes": workers_info}
def get_health(self, filter_node) -> Dict: """Get nodes and synchronization information. Parameters ---------- filter_node : dict Whether to filter by a node or return all health information. Returns ------- dict Dict object containing nodes information. """ workers_info = { key: val.to_dict() for key, val in self.clients.items() if filter_node is None or filter_node == {} or key in filter_node } n_connected_nodes = len(workers_info) if filter_node is None or self.configuration[ 'node_name'] in filter_node: workers_info.update( {self.configuration['node_name']: self.to_dict()}) # Get active agents by node and format last keep alive date format active_agents = Agent.get_agents_overview(filters={ 'status': 'active', 'node_name': filter_node })['items'] for agent in active_agents: if (agent_node := agent["node_name"]) in workers_info.keys(): workers_info[agent_node]["info"]["n_active_agents"] = \ workers_info[agent_node]["info"].get("n_active_agents", 0) + 1
def get_health(self, filter_node) -> Dict: """Get nodes and synchronization information. Parameters ---------- filter_node : dict Whether to filter by a node or return all health information. Returns ------- dict Dict object containing nodes information. """ workers_info = {key: val.to_dict() for key, val in self.clients.items() if filter_node is None or filter_node == {} or key in filter_node} n_connected_nodes = len(workers_info) if filter_node is None or self.configuration['node_name'] in filter_node: workers_info.update({self.configuration['node_name']: self.to_dict()}) # Get active agents by node and format last keep alive date format for node_name in workers_info.keys(): workers_info[node_name]["info"]["n_active_agents"] = Agent.get_agents_overview(filters={'status': 'active', 'node_name': node_name})['totalItems'] if workers_info[node_name]['info']['type'] != 'master': workers_info[node_name]['status']['last_keep_alive'] = str( datetime.fromtimestamp(workers_info[node_name]['status']['last_keep_alive'])) return {"n_connected_nodes": n_connected_nodes, "nodes": workers_info}
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
def show_group(agent_id): agent_info = Agent(id=agent_id).get_basic_information() str_group = ', '.join( agent_info['group']) if 'group' in agent_info else "Null" print("The agent '{0}' with ID '{1}' belongs to groups: {2}.".format( agent_info['name'], agent_info['id'], str_group))
def send_command(msg_queue, oq, agent_id): """Send the message to the agent :param msg_queue: Message previously created, contains what is necessary to launch the active response command in the agent. :param agent_id: Run AR command in the agent. :return: WazuhResult. """ agent_info = Agent(agent_id).get_basic_information() if agent_info['status'].lower() != 'active': raise WazuhError(1651) agent_conf = Agent(agent_id).getconfig('com', 'active-response') if agent_conf['active-response']['disabled'] == 'yes': raise WazuhError(1750) oq.send_msg_to_agent(msg=msg_queue, agent_id=agent_id, msg_type=OssecQueue.AR_TYPE)
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))) # Remove agents in group of 500 elements (so wazuh-db socket is not saturated) for agents_ids_sublist in itertools.zip_longest(*itertools.repeat(iter(agent_ids_list), 500), 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/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 wdb_conn = WazuhDBConnection() query_to_execute = 'global sql delete from belongs where {}'.format(' or '.join([ 'id_agent = {}'.format(agent_id) for agent_id in agents_ids_sublist ])) wdb_conn.run_wdb_command(query_to_execute) logger.info("Agent files removed")
def get_agent_config(agent_list=None, component=None, config=None): """Read selected configuration from agent. :param agent_list: List of agents ID's. :param component: Selected component. :param config: Configuration to get, written on disk. :return: WazuhResult(Loaded configuration in JSON). """ # We access unique agent_id from list, this may change if and when we decide a final way to handle get responses # with failed ids and a list of agents agent_id = agent_list[0] my_agent = Agent(agent_id) my_agent.load_info_from_db() if my_agent.status != "active": raise WazuhError(1740) return WazuhResult({'data': my_agent.getconfig(component=component, config=config, agent_version=my_agent.version)})
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
def show_agents_with_group(group_id): agents_data = Agent.get_agent_group(group_id, limit=None) if agents_data['totalItems'] == 0: print("No agents found in group '{0}'.".format(group_id)) else: print("{0} agent(s) in group '{1}':".format(agents_data['totalItems'], group_id)) for agent in agents_data['items']: print(" ID: {0} Name: {1}.".format(agent['id'], agent['name']))
def list_outdated(): agents = Agent.get_outdated_agents() if agents['totalItems'] == 0: print("All agents are updated.") else: print("%-6s%-35s %-25s" % ("ID", "Name", "Version")) for agent in agents['items']: print("%-6s%-35s %-25s" % (agent['id'], agent['name'], agent['version'])) print("\nTotal outdated agents: {0}".format(agents['totalItems']))
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') affected_agents = set() system_groups = get_groups() for group_id in group_list: try: # Check if group exists if group_id not in system_groups: raise WazuhError(1710) if group_id == 'default': raise WazuhError(1712) agent_list = list( map( operator.itemgetter('id'), 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) result.affected_items.append(group_id) affected_agents.update(affected_agents_result.affected_items) except WazuhException as e: result.add_failed_item(id_=group_id, error=e) result['affected_agents'] = sorted(affected_agents, key=int) result.affected_items.sort() result.total_affected_items = len(result.affected_items) return result
def __init__(self, agent_id, offset=0, limit=common.database_limit, sort=None, search=None, select=None, query='', count=True, get_data=True, distinct=False, default_sort_field='name', filters=None, fields=fields): if filters is None: filters = {} # Check if the agent exists Agent(agent_id).get_basic_information() backend = WazuhDBBackend(agent_id) WazuhDBQuery.__init__(self, offset=offset, limit=limit, table='vuln_cves', sort=sort, search=search, select=select, fields=fields, default_sort_field=default_sort_field, default_sort_order='ASC', filters=filters, query=query, backend=backend, min_select_fields=set(), count=count, get_data=get_data, distinct=distinct)
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
def get_upgrade_result(agent_list=None, timeout=3): """Read upgrade result output from agent. :param agent_list: List of agents ID's. :param timeout: Maximum time for the call to be considered failed. :return: Upgrade result. """ # We access unique agent_id from list, this may change if and when we decide to add option to upgrade a list of # agents agent_id = agent_list[0] return Agent(agent_id).upgrade_result(timeout=int(timeout))
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