def send_restart_command(agent_id: str = '', agent_version: str = '', wq: WazuhQueue = None) -> str: """Send restart command to an agent. Parameters ---------- agent_id : str ID specifying the agent where the restart command will be sent to agent_version : str Agent version to compare with the required version. The format is vX.Y.Z. wq : WazuhQueue WazuhQueue used for the active response messages. Returns ------- str Message generated by Wazuh. """ # If the Wazuh agent version is newer or equal to the AR legacy version, # the message sent will have JSON format if WazuhVersion(agent_version) >= WazuhVersion(common.AR_LEGACY_VERSION): ret_msg = wq.send_msg_to_agent(WazuhQueue.RESTART_AGENTS_JSON, agent_id) else: ret_msg = wq.send_msg_to_agent(WazuhQueue.RESTART_AGENTS, agent_id) return ret_msg
def get_stats(self, component): """Read the agent's component stats. Parameters ---------- component : string Name of the component to get stats from. Returns ------- Dict Object with component's stats. """ # Check if agent version is compatible with this feature self.load_info_from_db() if self.version is None: raise WazuhInternalError(1015) agent_version = WazuhVersion(self.version.split(" ")[1]) required_version = WazuhVersion( AGENT_COMPONENT_STATS_REQUIRED_VERSION.get(component)) if agent_version < required_version: raise WazuhInternalError( 1735, extra_message="Minimum required version is " + str(required_version)) return stats.get_daemons_stats_from_socket(self.id, component)
def getconfig(self, component: str = '', config: str = '', agent_version: str = '') -> dict: """Read agent's loaded configuration. Parameters ---------- component : str Selected component of the agent configuration. config : str Agent's active configuration to get. agent_version : str Agent version to compare with the required version. The format is vX.Y.Z or Wazuh vX.Y.Z. Raises ------ WazuhError(1735) The agent version is older than the minimum required version. Returns ------- dict Agent's active configuration. """ if WazuhVersion(agent_version) < WazuhVersion( common.ACTIVE_CONFIG_VERSION): raise WazuhInternalError( 1735, extra_message= f"Minimum required version is {common.ACTIVE_CONFIG_VERSION}") return configuration.get_active_configuration(self.id, component, config)
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 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 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