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 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 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_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 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 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 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 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 clear(agent_list=None): """Clear the rootcheck database for a list of agents. Parameters ---------- agent_list : list List of agent ids. Returns ------- result : AffectedItemsWazuhResult JSON containing the affected agents. """ result = AffectedItemsWazuhResult( all_msg='Rootcheck database was cleared on returned agents', some_msg='Rootcheck database was not cleared on some agents', none_msg="No rootcheck database was cleared") wdb_conn = WazuhDBConnection() for agent_id in agent_list: if agent_id not in get_agents_info(): result.add_failed_item(id_=agent_id, error=WazuhResourceNotFound(1701)) else: try: wdb_conn.execute(f"agent {agent_id} rootcheck delete", delete=True) result.affected_items.append(agent_id) except WazuhError as e: result.add_failed_item(id_=agent_id, error=e) result.affected_items.sort(key=int) result.total_affected_items = len(result.affected_items) return result
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 delete_agents(agent_list=None, backup=False, purge=False, status="all", older_than="7d", use_only_authd=False): """Deletes a list of agents. :param agent_list: List of agents ID's. :param backup: Create backup before removing the agent. :param purge: Delete definitely from key store. :param older_than: Filters out disconnected agents for longer than specified. Time in seconds | "[n_days]d" | "[n_hours]h" | "[n_minutes]m" | "[n_seconds]s". For never_connected agents, uses the register date. :param status: Filters by agent status: active, disconnected or never_connected. Multiples statuses separated by commas. :param use_only_authd: Force the use of authd when adding and removing agents. :return: AffectedItemsWazuhResult. """ result = AffectedItemsWazuhResult( all_msg='All selected agents were deleted', some_msg='Some agents were not deleted', none_msg='No agents were deleted') if len(agent_list) != 0: db_query = WazuhDBQueryAgents(limit=None, select=["id"], filters={ 'older_than': older_than, 'status': status, 'id': agent_list }) data = db_query.run() can_purge_agents = list(map(operator.itemgetter('id'), data['items'])) system_agents = get_agents_info() for agent_id in agent_list: try: if agent_id == "000": raise WazuhError(1703) elif agent_id not in system_agents: raise WazuhResourceNotFound(1701) else: my_agent = Agent(agent_id) my_agent.load_info_from_db() if agent_id not in can_purge_agents: raise WazuhError( 1731, extra_message= "The agent has a status different to '{0}' or the specified time " "frame 'older_than {1}' does not apply".format( status, older_than)) my_agent.remove(backup=backup, purge=purge, use_only_authd=use_only_authd) result.affected_items.append(agent_id) except WazuhException as e: result.add_failed_item(id_=agent_id, error=e) result.total_affected_items = len(result.affected_items) result.affected_items.sort(key=int) result['older_than'] = older_than return result
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_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_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 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 _expand_resource(resource): """This function expand a specified resource depending of its type. Parameters ---------- resource : str Resource to be expanded Returns ------- str Result of the resource expansion. """ name, attribute, value = resource.split(':') resource_type = ':'.join([name, attribute]) # This is the special case, expand_group can receive * or the name of the group. That's why it' s always called if resource_type == 'agent:group': return expand_group(value) # We need to transform the wildcard * to the resource of the system if value == '*': if resource_type == 'agent:id': return get_agents_info() elif resource_type == 'group:id': return get_groups() elif resource_type == 'role:id': with RolesManager() as rm: roles = rm.get_roles() return {str(role_id.id) for role_id in roles} elif resource_type == 'policy:id': with PoliciesManager() as pm: policies = pm.get_policies() return {str(policy_id.id) for policy_id in policies} elif resource_type == 'user:id': users_system = set() with AuthenticationManager() as auth: users = auth.get_users() for user in users: users_system.add(str(user['user_id'])) return users_system elif resource_type == 'rule:id': with RulesManager() as rum: rules = rum.get_rules() return {str(rule_id.id) for rule_id in rules} elif resource_type == 'rule:file': return expand_rules() elif resource_type == 'decoder:file': return expand_decoders() elif resource_type == 'list:file': return expand_lists() elif resource_type == 'node:id': return set(cluster_nodes.get()) elif resource_type == '*:*': # Resourceless return {'*'} return set() # We return the value casted to set else: return {value}
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_ciscat_results(agent_list=None, offset=0, limit=common.database_limit, select=None, search=None, sort=None, filters=None, nested=True, array=True, q=''): """ Get CIS-CAT results for a list of agents :param agent_list: list of Agent ID to get scan results from. Currently, only first item will be considered :param offset: First element to return in the collection :param limit: Maximum number of elements to return :param select: Select which fields to return :param search: Looks for items with the specified string. Begins with '-' for a complementary search :param sort: Sorts the items. Format: {"fields":["field1","field2"],"order":"asc|desc"} :param filters: Fields to filter by :param nested: Nested fields :param array: Array :param q: Defines query to filter in DB. :return: AffectedItemsWazuhResult """ result = AffectedItemsWazuhResult( all_msg='All CISCAT results were returned', some_msg='Some CISCAT results were not returned', none_msg='No CISCAT results were returned', sort_fields=['agent_id'] if sort is None else sort['fields'], sort_casting=['str'], sort_ascending=[sort['order'] == 'asc' for _ in sort['fields']] if sort is not None else ['True'] ) valid_select_fields = {'scan.id': 'scan_id', 'scan.time': 'scan_time', 'benchmark': 'benchmark', 'profile': 'profile', 'pass': '******', 'fail': 'fail', 'error': 'error', 'notchecked': 'notchecked', 'unknown': 'unknown', 'score': 'score'} table = 'ciscat_results' system_agents = get_agents_info() for agent in agent_list: try: if agent not in system_agents: raise WazuhResourceNotFound(1701) db_query = WazuhDBQuerySyscollector(agent_id=agent, offset=offset, limit=limit, select=select, search=search, sort=sort, filters=filters, fields=valid_select_fields, table=table, array=array, nested=nested, query=q) data = db_query.run() if len(data['items']) > 0: for item in data['items']: item['agent_id'] = agent result.affected_items.append(item) result.total_affected_items += data['totalItems'] except WazuhResourceNotFound as e: result.add_failed_item(id_=agent, error=e) result.affected_items = merge(*[[res] for res in result.affected_items], criteria=result.sort_fields, ascending=result.sort_ascending, types=result.sort_casting) return result
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 get_item_agent(agent_list, offset=0, limit=common.database_limit, select=None, search=None, sort=None, filters=None, q='', array=True, nested=True, element_type='os'): """ Get syscollector information about a list of agents. :param agent_list: List of agents ID's. :param offset: First item to return. :param limit: Maximum number of items to return. :param sort: Sorts the items. Format: {"fields":["field1","field2"],"order":"asc|desc"}. :param select: Select fields to return. Format: {"fields":["field1","field2"]}. :param search: Looks for items with the specified string. Format: {"fields": ["field1","field2"]} :param q: Defines query to filter in DB. :param filters: Fields to filter by :param nested: Nested fields :param array: Array :param element_type: Type of element to get syscollector information from :return: AffectedItemsWazuhResult """ result = AffectedItemsWazuhResult( none_msg='No syscollector information was returned', some_msg='Some syscollector information was not returned', all_msg='All specified syscollector information was returned', sort_fields=['agent_id'] if sort is None else sort['fields'], sort_casting=['str'], sort_ascending=[sort['order'] == 'asc' for _ in sort['fields']] if sort is not None else ['True'] ) for agent in agent_list: try: if agent not in get_agents_info(): raise WazuhResourceNotFound(1701) table, valid_select_fields = get_valid_fields(Type(element_type), agent_id=agent) db_query = WazuhDBQuerySyscollector(agent_id=agent, offset=offset, limit=limit, select=select, search=search, sort=sort, filters=filters, fields=valid_select_fields, table=table, array=array, nested=nested, query=q) data = db_query.run() for item in data['items']: item['agent_id'] = agent result.affected_items.append(item) result.total_affected_items += data['totalItems'] except WazuhResourceNotFound as e: result.add_failed_item(id_=agent, error=e) result.affected_items = merge(*[[res] for res in result.affected_items], criteria=result.sort_fields, ascending=result.sort_ascending, types=result.sort_casting) return result
def run_command(agent_list: list = None, command: str = '', arguments: list = None, custom: bool = False, alert: dict = None) -> AffectedItemsWazuhResult: """Run AR command in a specific agent. Parameters ---------- agent_list : list Agents list that will run the AR command. command : str Command running in the agents. If this value starts with !, then it refers to a script name instead of a command name. custom : bool Whether the specified command is a custom command or not. arguments : list Command arguments. alert : dict Alert information depending on the AR executed. Returns ------- AffectedItemsWazuhResult. """ result = AffectedItemsWazuhResult( all_msg='AR command was sent to all agents', some_msg='AR command was not sent to some agents', none_msg='AR command was not sent to any agent') if agent_list: wq = WazuhQueue(common.ARQUEUE) system_agents = get_agents_info() for agent_id in agent_list: try: if agent_id not in system_agents: raise WazuhResourceNotFound(1701) if agent_id == "000": raise WazuhError(1703) active_response.send_ar_message(agent_id, wq, command, arguments, custom, alert) result.affected_items.append(agent_id) result.total_affected_items += 1 except WazuhException as e: result.add_failed_item(id_=agent_id, error=e) result.affected_items.sort(key=int) wq.close() return result
def get_sca_list(agent_list=None, q="", offset=0, limit=common.database_limit, sort=None, search=None, select=None, filters=None): """ Get a list of policies analyzed in the configuration assessment for a given agent :param agent_list: agent id to get policies from :param q: Defines query to filter in DB. :param offset: First item to return. :param limit: Maximum number of items to return. :param sort: Sorts the items. Format: {"fields":["field1","field2"],"order":"asc|desc"}. :param search: Looks for items with the specified string. Format: {"fields": ["field1","field2"]} :param select: Select fields to return. Format: {"fields":["field1","field2"]}. :param filters: Define field filters required by the user. Format: {"field1":"value1", "field2":["value2","value3"]} :return: AffectedItemsWazuhResult """ result = AffectedItemsWazuhResult( all_msg='All selected sca information was returned', some_msg='Some sca information was not returned', none_msg='No sca information was returned') if len(agent_list) != 0: if agent_list[0] in get_agents_info(): select = list( fields_translation_sca.keys()) if select is None else select db_query = WazuhDBQuerySCA(agent_id=agent_list[0], offset=offset, limit=limit, sort=sort, search=search, select=select, count=True, get_data=True, query=q, filters=filters) data = db_query.run() result.affected_items.extend(data['items']) result.total_affected_items = data['totalItems'] else: result.add_failed_item(id_=agent_list[0], error=WazuhResourceNotFound(1701)) return result
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 remove_agent_from_group(group_list=None, agent_list=None): """Removes an agent assignment from a specified group. :param group_list: List of Group names. :param agent_list: List of Agent IDs. :return: Confirmation message. """ group_id = group_list[0] agent_id = agent_list[0] # Check if agent and group exist and it is not 000 if agent_id not in get_agents_info(): raise WazuhResourceNotFound(1701) if agent_id == '000': raise WazuhError(1703) if group_id not in get_groups(): raise WazuhResourceNotFound(1710) return WazuhResult({'message': Agent.unset_single_group_agent(agent_id=agent_id, group_id=group_id, force=True)})
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_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: rootcheck_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) result.affected_items.sort(key=int) 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 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