def get_last_scan(agent_list): """Get the last rootcheck scan of the agent. Parameters ---------- agent_list : list Agent ID to get the last scan date from. Returns ------- result : AffectedItemsWazuhResult JSON containing the scan date. """ result = AffectedItemsWazuhResult( all_msg='Last rootcheck scan of the agent was returned', none_msg='No last scan information was returned') result.affected_items.append(last_scan(agent_list[0])) result.total_affected_items = len(result.affected_items) return result
def get_agents_keys(agent_list=None): """Get the key of existing agents. :param agent_list: List of agents ID's. :return: AffectedItemsWazuhResult. """ result = AffectedItemsWazuhResult(all_msg='Obtained keys for all selected agents', some_msg='Some agent keys were not obtained', none_msg='No agent keys were obtained' ) 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({'id': agent_id, 'key': Agent(agent_id).get_key()}) except WazuhException as e: result.add_failed_item(id_=agent_id, error=e) result.total_affected_items = len(result.affected_items) return result
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() system_agents = get_agents_info() 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_id, error=WazuhResourceNotFound(1701)) for agent_id in not_found_agents ] eligible_agents = agent_list - not_found_agents for agent_id in eligible_agents: 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
def files(agent_list=None, offset=0, limit=common.database_limit, sort=None, search=None, select=None, filters=None, q='', summary=False, distinct=False): """Return a list of files from the database that match the filters :param agent_list: Agent ID. :param filters: Fields to filter by :param summary: Returns a summary grouping by filename. :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: ["field1","field2"]. :param q: Query to filter by :param distinct: Look for distinct values :return: AffectedItemsWazuhResult. """ if filters is None: filters = {} parameters = {"date": "date", "mtime": "mtime", "file": "file", "size": "size", "perm": "perm", "uname": "uname", "gname": "gname", "md5": "md5", "sha1": "sha1", "sha256": "sha256", "inode": "inode", "gid": "gid", "uid": "uid", "type": "type", "changes": "changes", "attributes": "attributes"} summary_parameters = {"date": "date", "mtime": "mtime", "file": "file"} result = AffectedItemsWazuhResult(all_msg='FIM findings of the agent were returned', none_msg='No FIM information was returned') if 'hash' in filters: q = f'(md5={filters["hash"]},sha1={filters["hash"]},sha256={filters["hash"]})' + ('' if not q else ';' + q) del filters['hash'] db_query = WazuhDBQuerySyscheck(agent_id=agent_list[0], offset=offset, limit=limit, sort=sort, search=search, filters=filters, query=q, select=select, table='fim_entry', distinct=distinct, fields=summary_parameters if summary else parameters) db_query = db_query.run() result.affected_items = db_query['items'] result.total_affected_items = db_query['totalItems'] return result
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 totals(date): """Retrieve statistical information for the current or specified date. Parameters ---------- date: date Date object with the date value of the stats. Returns ------- AffectedItemsWazuhResult Array of dictionaries. Each dictionary represents an hour. """ result = AffectedItemsWazuhResult( all_msg='Statistical information for each node was successfully read', some_msg='Could not read statistical information for some nodes', none_msg='Could not read statistical information for any node') affected = totals_(date) result.affected_items = affected result.total_affected_items = len(result.affected_items) return result
def read_ossec_conf(section=None, field=None): """ Wrapper for get_ossec_conf :param section: Filters by section (i.e. rules). :param field: Filters by field in section (i.e. included). :return: AffectedItemsWazuhResult. """ result = AffectedItemsWazuhResult( all_msg=f"Configuration was successfully read" f"{' in specified node' if node_id != 'manager' else ''}", some_msg='Could not read configuration in some nodes', none_msg=f"Could not read configuration" f"{' in specified node' if node_id != 'manager' else ''}") try: result.affected_items.append( get_ossec_conf(section=section, field=field)) except WazuhError as e: result.add_failed_item(id_=node_id, error=e) result.total_affected_items = len(result.affected_items) return result
def get_config(component=None, config=None): """ Wrapper for get_active_configuration :param component: Selected component. :param config: Configuration to get, written on disk. :return: AffectedItemsWazuhResult. """ result = AffectedItemsWazuhResult(all_msg=f"Active configuration read successfully" f"{' in specified node' if node_id != 'manager' else ''}", some_msg='Could not read active configuration in some nodes', none_msg=f"Could not read active configuration" f"{' in specified node' if node_id != 'manager' else ''}" ) try: data = configuration.get_active_configuration(agent_id='000', component=component, configuration=config) len(data.keys()) > 0 and result.affected_items.append(data) except WazuhError as e: result.add_failed_item(id_=node_id, error=e) result.total_affected_items = len(result.affected_items) return result
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
def create_user(username: str = None, password: str = None, allow_run_as: bool = False): """Create a new user Parameters ---------- username : str Name for the new user password : str Password for the new user allow_run_as : bool Enable authorization context login method for the new user Returns ------- result : AffectedItemsWazuhResult Status message """ if len(password) > 64 or len(password) < 8: raise WazuhError(5009) elif not _user_password.match(password): raise WazuhError(5007) result = AffectedItemsWazuhResult(none_msg='User could not be created', all_msg='User was successfully created') with AuthenticationManager() as auth: if auth.add_user(username, password, allow_run_as=allow_run_as): operation = auth.get_user(username) if operation: result.affected_items.append(operation) result.total_affected_items = 1 else: result.add_failed_item(id_=username, error=WazuhError(5000)) else: result.add_failed_item(id_=username, error=WazuhError(5000)) return result
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 WazuhResourceNotFound(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 run(agent_list=None): """Run rootcheck scan. Parameters ---------- agent_list : list Run rootcheck in a list of agents. 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') 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 run(agent_list=None): """Run a syscheck scan in the specified agents. Parameters ---------- agent_list : str List of the agents IDs to run the scan for. Returns ------- result : AffectedItemsWazuhResult Confirmation/Error message. """ 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: wq = WazuhQueue(common.ARQUEUE) wq.send_msg_to_agent(WazuhQueue.HC_SK_RESTART, agent_id) result.affected_items.append(agent_id) wq.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 hourly(): """ Returns the hourly averages. :return: Dictionary: averages and interactions. """ averages = [] interactions = 0 # What's the 24 for? for i in range(25): try: hfile = open(common.stats_path + '/hourly-average/' + str(i)) data = hfile.read() if i == 24: interactions = int(data) else: averages.append(int(data)) hfile.close() except IOError: if i < 24: averages.append(0) result = AffectedItemsWazuhResult( all_msg= 'Statistical information per hour for each node was successfully read', some_msg= 'Could not read statistical information per hour for some nodes', none_msg='Could not read statistical information per hour for any node' ) result.affected_items.append({ 'averages': averages, 'interactions': interactions }) result.total_affected_items = len(result.affected_items) return result
def ossec_log(level=None, tag=None, offset=0, limit=common.database_limit, sort_by=None, sort_ascending=True, search_text=None, complementary_search=False, search_in_fields=None, q=''): """Gets logs from ossec.log. :param level: Filters by log level: all, error or info. :param tag: Filters by log category/tag (i.e. wazuh-remoted). :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 q: Defines query to filter. :return: AffectedItemsWazuhResult """ result = AffectedItemsWazuhResult(all_msg=f"Logs were successfully read" f"{' in specified node' if node_id != 'manager' else ''}", some_msg='Could not read logs in some nodes', none_msg=f"Could not read logs" f"{' in specified node' if node_id != 'manager' else ''}" ) logs = get_ossec_logs() query = [] level and query.append(f'level={level}') tag and query.append(f'tag={tag}') q and query.append(q) query = ';'.join(query) data = process_array(logs, 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, q=query) 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 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
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: db_query = WazuhDBQueryAgents(select=['os.platform'], filters={'id': agent_list}, default_sort_field='os_platform', min_select_fields=set(), distinct=True) 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 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 create_user(username: str = None, password: str = None): """Create a new user :param username: Name for the new user :param password: Password for the new user :return: Status message """ if not _user_password.match(password): raise WazuhError(5007) result = AffectedItemsWazuhResult(none_msg='User could not be created', all_msg='User created correctly') with AuthenticationManager() as auth: if auth.add_user(username, password): operation = auth.get_user(username) if operation: result.affected_items.append(operation) result.total_affected_items = 1 else: result.add_failed_item(id_=username, error=WazuhError(5000)) else: result.add_failed_item(id_=username, error=WazuhError(5000)) 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
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 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 = set(map(operator.itemgetter('id'), data['items'])) agent_list = set(agent_list) try: agent_list.remove('000') result.add_failed_item('000', WazuhError(1703)) except KeyError: pass # Add not existing agents to failed_items not_found_agents = agent_list - system_agents list( map( lambda ag: result.add_failed_item( id_=ag, error=WazuhResourceNotFound(1701)), not_found_agents)) # Add non eligible agents to failed_items non_eligible_agents = agent_list - not_found_agents - can_purge_agents list( map( lambda ag: result.add_failed_item( id_=ag, error=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 '')))), non_eligible_agents)) for agent_id in agent_list.intersection(system_agents).intersection( can_purge_agents): try: my_agent = Agent(agent_id) 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) # Clear temporary cache clear_temporary_caches() result.total_affected_items = len(result.affected_items) result.affected_items.sort(key=int) 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 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 Parameters ---------- agent_list : list Agent ids to get policies from. q : str Defines query to filter in DB. 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"]} select : str Select fields to return. Format: {"fields":["field1","field2"]}. filters : str Define field filters required by the user. Format: {"field1":"value1", "field2":["value2","value3"]} Returns ------- 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
def get_rootcheck_agent(agent_list=None, offset=0, limit=common.database_limit, sort=None, search=None, select=None, filters=None, q='', distinct=None): """Return a list of events from the rootcheck database. Parameters ---------- agent_list : list Agent ID to get the rootcheck events from. offset : int First element to return in the collection. limit : int Maximum number of elements to return. sort : str Sort the collection by a field or fields (separated by comma). Use +/- at the beginning to list in ascending or descending order. search : str Look for elements with the specified string. select : str Select which fields to return (separated by comma). q : str Query to filter results by. distinct : bool Look for distinct values. filters : dict Fields to filter by. Returns ------- result : AffectedItemsWazuhResult JSON containing the rootcheck events. """ if filters is None: filters = {} result = AffectedItemsWazuhResult( all_msg='All selected rootcheck information was returned', some_msg='Some rootcheck information was not returned', none_msg='No rootcheck information was returned') db_query = WazuhDBQueryRootcheck(agent_id=agent_list[0], offset=offset, limit=limit, sort=sort, search=search, select=select, count=True, get_data=True, query=q, filters=filters, distinct=distinct) data = db_query.run() result.affected_items.extend(data['items']) result.total_affected_items = data['totalItems'] return result
def get_sca_checks(policy_id=None, agent_list=None, q="", offset=0, limit=common.database_limit, sort=None, search=None, select=None, filters=None): """ Get a list of checks analyzed for a policy :param policy_id: policy id to get the checks from :param agent_list: agent id to get the 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/policy information was returned', some_msg='Some sca/policy information was not returned', none_msg='No sca/policy information was returned') if len(agent_list) != 0: if agent_list[0] in get_agents_info(): fields_translation = { **fields_translation_sca_check, **fields_translation_sca_check_compliance, **fields_translation_sca_check_rule } full_select = ( list(fields_translation_sca_check.keys()) + list(fields_translation_sca_check_compliance.keys()) + list(fields_translation_sca_check_rule.keys())) db_query = WazuhDBQuerySCA(agent_id=agent_list[0], offset=offset, limit=limit, sort=sort, search=search, select=full_select, count=True, get_data=True, query=f"policy_id={policy_id}" if q == "" else f"policy_id={policy_id};{q}", filters=filters, default_query=default_query_sca_check, default_sort_field='policy_id', fields=fields_translation, count_field='id') result_dict = db_query.run() if 'items' in result_dict: checks = result_dict['items'] else: raise WazuhInternalError(2007) groups = groupby(checks, key=itemgetter('id')) select_fields = full_select if select is None else select select_fields = set([ field if field != 'compliance' else 'compliance' for field in select_fields if field in fields_translation_sca_check ]) # Rearrange check and compliance fields for _, group in groups: group_list = list(group) check_dict = { k: v for k, v in group_list[0].items() if k in select_fields } for extra_field, field_translations in [ ('compliance', fields_translation_sca_check_compliance), ('rules', fields_translation_sca_check_rule) ]: if (select is None or extra_field in select) \ and set(field_translations.keys()) & group_list[0].keys(): check_dict[extra_field] = [ dict(zip(field_translations.values(), x)) for x in set(( map(itemgetter( *field_translations.keys()), group_list))) ] result.affected_items.append(check_dict) result.total_affected_items = result_dict['totalItems'] else: result.add_failed_item(id_=agent_list[0], error=WazuhResourceNotFound(1701)) result.total_affected_items = 0 return result
def totals(date): """ Returns the totals file. :param date: date object with the date value of the stats :return: Array of dictionaries. Each dictionary represents an hour. """ stat_filename = "" try: stat_filename = os.path.join( common.stats_path, "totals", str(date.year), MONTHS[date.month - 1], f"ossec-totals-{date.strftime('%d')}.log") stats = open(stat_filename, 'r') except IOError: raise WazuhError(1308, extra_message=stat_filename) result = AffectedItemsWazuhResult( all_msg='Statistical information for each node was successfully read', some_msg='Could not read statistical information for some nodes', none_msg='Could not read statistical information for any node') alerts = [] for line in stats: data = line.split('-') if len(data) == 4: sigid = int(data[1]) level = int(data[2]) times = int(data[3]) alert = {'sigid': sigid, 'level': level, 'times': times} alerts.append(alert) else: data = line.split('--') if len(data) != 5: if len(data) in (0, 1): continue else: result.add_failed_item( id_=node_id if cluster_enabled else 'manager', error=WazuhInternalError(1309)) return result hour = int(data[0]) total_alerts = int(data[1]) events = int(data[2]) syscheck = int(data[3]) firewall = int(data[4]) result.affected_items.append({ 'hour': hour, 'alerts': alerts, 'totalAlerts': total_alerts, 'events': events, 'syscheck': syscheck, 'firewall': firewall }) alerts = [] result.total_affected_items = len(result.affected_items) return result
def get_sca_checks(policy_id=None, agent_list=None, q="", offset=0, limit=common.database_limit, sort=None, search=None, select=None, filters=None): """ Get a list of checks analyzed for a policy Parameters ---------- policy_id : str Policy id to get the checks from. agent_list : list Agent id to get the policies from q : str Defines query to filter in DB. 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"]} select : str Select fields to return. Format: {"fields":["field1","field2"]}. filters : str Define field filters required by the user. Format: {"field1":"value1", "field2":["value2","value3"]} Returns ------- AffectedItemsWazuhResult """ result = AffectedItemsWazuhResult( all_msg='All selected sca/policy information was returned', some_msg='Some sca/policy information was not returned', none_msg='No sca/policy information was returned') if len(agent_list) != 0: sca_checks = list() if agent_list[0] in get_agents_info(): fields_translation = { **fields_translation_sca_check, **fields_translation_sca_check_compliance, **fields_translation_sca_check_rule } full_select = ( list(fields_translation_sca_check.keys()) + list(fields_translation_sca_check_compliance.keys()) + list(fields_translation_sca_check_rule.keys())) # Workaround for too long sca_checks results until the chunk algorithm is implemented (1/2) db_query = WazuhDBQuerySCA(agent_id=agent_list[0], offset=0, limit=None, sort=None, filters=filters, search=None, select=full_select, count=True, get_data=True, query=f"policy_id={policy_id}", default_query=default_query_sca_check, default_sort_field='policy_id', fields=fields_translation, count_field='id') result_dict = db_query.run() if 'items' in result_dict: checks = result_dict['items'] else: raise WazuhInternalError(2007) groups = groupby(checks, key=itemgetter('id')) select_fields = full_select if select is None else select select_fields = set([ field if field != 'compliance' else 'compliance' for field in select_fields if field in fields_translation_sca_check ]) # Rearrange check and compliance fields for _, group in groups: group_list = list(group) check_dict = { k: v for k, v in group_list[0].items() if k in select_fields } for extra_field, field_translations in [ ('compliance', fields_translation_sca_check_compliance), ('rules', fields_translation_sca_check_rule) ]: if (select is None or extra_field in select) \ and set(field_translations.keys()) & group_list[0].keys(): check_dict[extra_field] = [ dict(zip(field_translations.values(), x)) for x in set(( map(itemgetter( *field_translations.keys()), group_list))) ] sca_checks.append(check_dict) else: result.add_failed_item(id_=agent_list[0], error=WazuhResourceNotFound(1701)) result.total_affected_items = 0 # Workaround for too long sca_checks results until the chunk algorithm is implemented (2/2) data = process_array( sca_checks, search_text=search['value'] if search else None, complementary_search=search['negation'] if search else False, sort_by=sort['fields'] if sort else ['policy_id'], sort_ascending=False if sort and sort['order'] == 'desc' else True, offset=offset, limit=limit, q=q) result.affected_items = data['items'] result.total_affected_items = data['totalItems'] return result
def files(agent_list=None, offset=0, limit=common.database_limit, sort=None, search=None, select=None, filters=None, q='', nested=True, summary=False, distinct=False): """Return a list of files from the syscheck database of the specified agents. Parameters ---------- agent_list : str Agent ID. filters : dict Fields to filter by. summary : bool Returns a summary grouping by filename. 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. select : list[str] Select fields to return. Format: ["field1","field2"]. q : str Query to filter by. nested : bool Specify whether there are nested fields or not. distinct : bool Look for distinct values. Returns ------- result : AffectedItemsWazuhResult Confirmation/Error message. """ if filters is None: filters = {} parameters = { "date": "date", "arch": "arch", "value.type": "value_type", "value.name": "value_name", "mtime": "mtime", "file": "file", "size": "size", "perm": "perm", "uname": "uname", "gname": "gname", "md5": "md5", "sha1": "sha1", "sha256": "sha256", "inode": "inode", "gid": "gid", "uid": "uid", "type": "type", "changes": "changes", "attributes": "attributes" } summary_parameters = {"date": "date", "mtime": "mtime", "file": "file"} result = AffectedItemsWazuhResult( all_msg='FIM findings of the agent were returned', none_msg='No FIM information was returned') if 'hash' in filters: q = f'(md5={filters["hash"]},sha1={filters["hash"]},sha256={filters["hash"]})' + ( '' if not q else ';' + q) del filters['hash'] with WazuhDBQuerySyscheck( agent_id=agent_list[0], offset=offset, limit=limit, sort=sort, search=search, filters=filters, nested=nested, query=q, select=select, table='fim_entry', distinct=distinct, fields=summary_parameters if summary else parameters, min_select_fields={'file'}) as db_query: db_query = db_query.run() result.affected_items = db_query['items'] result.total_affected_items = db_query['totalItems'] return result