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_requirement(requirement=None, offset=0, limit=common.database_limit, sort_by=None, sort_ascending=True, search_text=None, complementary_search=False, search_in_fields=None): """Get the requirements used in the rules :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 requirement: Requirement to get :return: Dictionary: {'items': array of items, 'totalItems': Number of items (without applying the limit)} """ result = AffectedItemsWazuhResult(none_msg='No rule was shown', all_msg='Selected rules were shown') if requirement not in RULE_REQUIREMENTS: result.add_failed_item( id_=requirement, error=WazuhError( 1205, extra_message=requirement, extra_remediation=f'Valid ones are {RULE_REQUIREMENTS}')) return result req = list({ req for rule in get_rules(limit=None).affected_items for req in rule[requirement] }) data = process_array(req, 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'] return result
def update_policy(policy_id=None, name=None, policy=None): """Updates a policy in the system :param policy_id: Policy id to be update :param name: The new policy name :param policy: The new policy :return Policy information """ if name is None and policy is None: raise WazuhError(4001) result = AffectedItemsWazuhResult(none_msg='Policy was not updated', all_msg='Policy was successfully updated') with PoliciesManager() as pm: status = pm.update_policy(policy_id=policy_id[0], name=name, policy=policy) if status == SecurityError.ALREADY_EXIST: result.add_failed_item(id_=int(policy_id[0]), error=WazuhError(4013)) elif status == SecurityError.INVALID: result.add_failed_item(id_=int(policy_id[0]), error=WazuhError(4006)) elif status == SecurityError.POLICY_NOT_EXIST: result.add_failed_item(id_=int(policy_id[0]), error=WazuhError(4007)) elif status == SecurityError.ADMIN_RESOURCES: result.add_failed_item(id_=int(policy_id[0]), error=WazuhError(4008)) else: updated = pm.get_policy_id(int(policy_id[0])) result.affected_items.append(updated) result.total_affected_items += 1 invalid_roles_tokens(roles=updated['roles']) return result
def remove_user_role(user_id, role_ids): """Create a relationship between a user and a role :param user_id: User id :param role_ids: List of role ids :return User-Roles information """ username = get_username(user_id=user_id) result = AffectedItemsWazuhResult(none_msg=f'No role was unlinked from user {username}', some_msg=f'Some roles were not unlinked from user {username}', all_msg=f'All roles were unlinked from user {username}') success = False with UserRolesManager() as urm: for role_id in role_ids: user_role = urm.remove_role_in_user(user_id=int(user_id[0]), role_id=role_id) if user_role == SecurityError.INVALID: result.add_failed_item(id_=int(role_id), error=WazuhError(4016)) elif user_role == SecurityError.ROLE_NOT_EXIST: result.add_failed_item(id_=int(role_id), error=WazuhError(4002)) elif user_role == SecurityError.USER_NOT_EXIST: result.add_failed_item(id_=int(user_id[0]), error=WazuhError(5001)) break elif user_role == SecurityError.ADMIN_RESOURCES: result.add_failed_item(id_=int(user_id[0]), error=WazuhError(4008)) else: success = True result.total_affected_items += 1 if success: with AuthenticationManager() as auth: result.affected_items.append(auth.get_user_id(int(user_id[0]))) result.affected_items.sort(key=str) invalid_users_tokens(users=user_id) return result
def remove_role_rule(role_id, rule_ids): """Remove a relationship between a role and one or more rules. :param role_id: The new role_id :param rule_ids: List of rule ids :return Result of operation """ result = AffectedItemsWazuhResult(none_msg=f'No security rule was unlinked from role {role_id[0]}', some_msg=f'Some security rules were not unlinked from role {role_id[0]}', all_msg=f'All security rules were unlinked from role {role_id[0]}') success = False with RolesRulesManager() as rrm: for rule_id in rule_ids: role_rule = rrm.remove_rule_in_role(role_id=int(role_id[0]), rule_id=int(rule_id)) if role_rule == SecurityError.INVALID: result.add_failed_item(id_=rule_id, error=WazuhError(4024)) elif role_rule == SecurityError.ROLE_NOT_EXIST: result.add_failed_item(id_=int(role_id[0]), error=WazuhError(4002)) elif role_rule == SecurityError.RULE_NOT_EXIST: result.add_failed_item(id_=rule_id, error=WazuhError(4022)) elif role_rule == SecurityError.ADMIN_RESOURCES: result.add_failed_item(id_=int(role_id[0]), error=WazuhError(4008)) else: success = True result.total_affected_items += 1 if success: with RolesManager() as rm: result.affected_items.append(rm.get_role_id(role_id=role_id[0])) # Invalidate users with auth_context invalid_run_as_tokens() result.affected_items.sort(key=str) return result
def remove_role_policy(role_id, policy_ids): """Removes a relationship between a role and a policy :param role_id: The new role_id :param policy_ids: List of policies ids :return Result of operation """ result = AffectedItemsWazuhResult(none_msg=f'No policy was unlinked from role {role_id[0]}', some_msg=f'Some policies were not unlinked from role {role_id[0]}', all_msg=f'All policies were unlinked from role {role_id[0]}') success = False with RolesPoliciesManager() as rpm: for policy_id in policy_ids: policy_id = int(policy_id) role_policy = rpm.remove_policy_in_role(role_id=role_id[0], policy_id=policy_id) if role_policy == SecurityError.INVALID: result.add_failed_item(id_=policy_id, error=WazuhError(4010)) elif role_policy == SecurityError.ROLE_NOT_EXIST: result.add_failed_item(id_=int(role_id[0]), error=WazuhError(4002)) elif role_policy == SecurityError.POLICY_NOT_EXIST: result.add_failed_item(id_=policy_id, error=WazuhError(4007)) elif role_policy == SecurityError.ADMIN_RESOURCES: result.add_failed_item(id_=int(role_id[0]), error=WazuhError(4008)) else: success = True result.total_affected_items += 1 if success: with RolesManager() as rm: result.affected_items.append(rm.get_role_id(role_id=role_id[0])) role = rm.get_role_id(role_id=role_id[0]) invalid_roles_tokens(roles=[role['id']]) result.affected_items.sort(key=str) return result
def update_role(role_id=None, name=None): """Updates a role in the system :param role_id: Role id to be update :param name: The new role name :return Role information """ if name is None: raise WazuhError(4001) result = AffectedItemsWazuhResult(none_msg='Role was not updated', all_msg='Role was successfully updated') with RolesManager() as rm: status = rm.update_role(role_id=role_id[0], name=name) if status == SecurityError.ALREADY_EXIST: result.add_failed_item(id_=int(role_id[0]), error=WazuhError(4005)) elif status == SecurityError.INVALID: result.add_failed_item(id_=int(role_id[0]), error=WazuhError(4003)) elif status == SecurityError.ROLE_NOT_EXIST: result.add_failed_item(id_=int(role_id[0]), error=WazuhError(4002)) elif status == SecurityError.ADMIN_RESOURCES: result.add_failed_item(id_=int(role_id[0]), error=WazuhError(4008)) else: updated = rm.get_role_id(int(role_id[0])) result.affected_items.append(updated) result.total_affected_items += 1 invalid_roles_tokens(roles=role_id) return result
def delete_agents(agent_list=None, backup=False, purge=False, status="all", older_than="7d", use_only_authd=False): """Deletes a list of agents. :param agent_list: List of agents ID's. :param backup: Create backup before removing the agent. :param purge: Delete definitely from key store. :param older_than: Filters out disconnected agents for longer than specified. Time in seconds | "[n_days]d" | "[n_hours]h" | "[n_minutes]m" | "[n_seconds]s". For never_connected agents, uses the register date. :param status: Filters by agent status: active, disconnected or never_connected. Multiples statuses separated by commas. :param use_only_authd: Force the use of authd when adding and removing agents. :return: AffectedItemsWazuhResult. """ result = AffectedItemsWazuhResult(all_msg='All selected agents were deleted', some_msg='Some agents were not deleted', none_msg='No agents were deleted' ) if len(agent_list) != 0: system_agents = get_agents_info() filters = {'older_than': older_than, 'status': status} rbac_filters = get_rbac_filters(system_resources=system_agents, permitted_resources=agent_list, filters=filters) db_query = WazuhDBQueryAgents(limit=None, select=["id"], **rbac_filters) data = db_query.run() can_purge_agents = list(map(operator.itemgetter('id'), data['items'])) for agent_id in agent_list: try: if agent_id == "000": raise WazuhError(1703) elif agent_id not in system_agents: raise WazuhResourceNotFound(1701) else: my_agent = Agent(agent_id) my_agent.load_info_from_db() if agent_id not in can_purge_agents: raise WazuhError( 1731, extra_message="The agent has a status different to '{0}' or the specified time " "frame 'older_than {1}' does not apply".format(status, older_than) ) my_agent.remove(backup=backup, purge=purge, use_only_authd=use_only_authd) result.affected_items.append(agent_id) except WazuhException as e: result.add_failed_item(id_=agent_id, error=e) result.total_affected_items = len(result.affected_items) result.affected_items.sort(key=int) result['older_than'] = older_than return result
def update_rule(rule_id=None, name=None, rule=None): """Update a rule from the system. :param rule_id: Rule id to be updated :param name: The new name :param rule: The new rule :return Rule information """ if name is None and rule is None: raise WazuhError(4001) result = AffectedItemsWazuhResult( none_msg='Security rule was not updated', all_msg='Security rule was successfully updated') with RulesManager() as rum: status = rum.update_rule(rule_id=rule_id[0], name=name, rule=rule) if status == SecurityError.ALREADY_EXIST: result.add_failed_item(id_=int(rule_id[0]), error=WazuhError(4005)) elif status == SecurityError.INVALID: result.add_failed_item(id_=int(rule_id[0]), error=WazuhError(4003)) elif status == SecurityError.RULE_NOT_EXIST: result.add_failed_item(id_=int(rule_id[0]), error=WazuhError(4022)) elif status == SecurityError.ADMIN_RESOURCES: result.add_failed_item(id_=int(rule_id[0]), error=WazuhError(4008)) else: updated = rum.get_rule(rule_id[0]) result.affected_items.append(updated) result.total_affected_items += 1 invalid_roles_tokens(roles=updated['roles']) return result
def list_handler(result: AffectedItemsWazuhResult, original: dict = None, allowed: dict = None, target: dict = None, add_denied: bool = False, **post_proc_kwargs): """Post processor for framework list responses with affected items and optional denied items. Parameters ---------- result : AffectedItemsWazuhResult Dict with affected_items, failed_items and str_priority. original : dict Original input call parameter values. allowed : dict Allowed input call parameter values. target : dict Name of the input parameters used to calculate resource access. add_denied : bool Flag to add denied permissions to answer. post_proc_kwargs : dict Additional kwargs used in post-processing. Returns ------- AffectedItemsWazuhResult """ if add_denied: for res_id, target_param in target.items(): denied = _get_denied(original, allowed, target_param, res_id) if res_id in integer_resources: denied = {int(i) if i.isdigit() else i for i in denied} for denied_item in denied: result.add_failed_item( id_=denied_item, error=WazuhPermissionError( 4000, extra_message=f'Resource type: {res_id}', ids=denied)) if not add_denied or post_proc_kwargs.get('force'): # Apply post processing exclusion/default values if the main resource was not explicit or # `force` parameter exists in `post_proc_kwargs` and is True if 'default_result_kwargs' in post_proc_kwargs and result is None: return AffectedItemsWazuhResult( **post_proc_kwargs['default_result_kwargs']) if 'exclude_codes' in post_proc_kwargs: result.remove_failed_items(post_proc_kwargs['exclude_codes']) return result
def upload_list_file(filename=None, content=None, overwrite=False): """Upload a new list file. Parameters ---------- filename : str Destination path of the new file. content : str Content of file to be uploaded. overwrite : bool True for updating existing files, false otherwise. Returns ------- result : AffectedItemsWazuhResult Confirmation message. """ result = AffectedItemsWazuhResult(all_msg='CDB list file uploaded successfully', none_msg='Could not upload CDB list file') full_path = join(common.user_lists_path, filename) backup_file = '' try: # Raise WazuhError if CDB list is not valid validate_cdb_list(content) # If file already exists and overwrite is False, raise exception. if not overwrite and exists(full_path): raise WazuhError(1905) # If file with same name already exists in subdirectory. elif get_filenames_paths([filename])[0] != full_path: raise WazuhError(1805) # Create backup and delete original CDB list. elif overwrite and exists(full_path): backup_file = f"{full_path}.backup" delete_file_with_backup(backup_file, full_path, delete_list_file) upload_file(content, to_relative_path(full_path), check_xml_formula_values=False) result.affected_items.append(to_relative_path(full_path)) result.total_affected_items = len(result.affected_items) # Remove back up file if no exceptions were raised. exists(backup_file) and remove(backup_file) except WazuhError as e: result.add_failed_item(id_=to_relative_path(full_path), error=e) finally: # If backup file was not deleted (any exception was raised), it should be restored. exists(backup_file) and safe_move(backup_file, full_path, permissions=0o660) 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 read_config_wrapper(): """ Wrapper for read_config :return: AffectedItemsWazuhResult """ result = AffectedItemsWazuhResult( all_msg='All selected information is shown', none_msg='No information is shown') try: result.affected_items.append(read_config()) except WazuhError as e: result.add_failed_item(id_=node_id, error=e) result.total_affected_items = len(result.affected_items) return result
def validation(): """Check if Wazuh configuration is OK. :return: AffectedItemsWazuhResult. """ result = AffectedItemsWazuhResult(**_validation_default_result_kwargs) try: response = validate_ossec_conf() result.affected_items.append({'name': node_id, **response}) result.total_affected_items += 1 except WazuhError as e: result.add_failed_item(id_=node_id, error=e) return result
def get_node_wrapper(): """ Wrapper for get_node :return: AffectedItemsWazuhResult """ result = AffectedItemsWazuhResult( all_msg='All selected information was returned', none_msg='No information was returned') try: result.affected_items.append(get_node()) 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_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 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_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 get_user_me(): """Get the information of the current user Returns ------- AffectedItemsWazuhResult with the desired information """ result = AffectedItemsWazuhResult(all_msg='Current user information was returned') affected_items = list() with AuthenticationManager() as auth: user = auth.get_user(common.current_user.get()) for index, role_id in enumerate(user['roles']): with RolesManager() as rm: role = rm.get_role_id(role_id=int(role_id)) role.pop('users') for index_r, rule_id in enumerate(role['rules']): with RulesManager() as rum: role['rules'][index_r] = rum.get_rule(rule_id=int(rule_id)) role['rules'][index_r].pop('roles') for index_p, policy_id in enumerate(role['policies']): with PoliciesManager() as pm: role['policies'][index_p] = pm.get_policy_id(policy_id=int(policy_id)) role['policies'][index_p].pop('roles') user['roles'][index] = role affected_items.append(user) if user else result.add_failed_item(id_=common.current_user.get(), error=WazuhError(5001)) data = process_array(affected_items) result.affected_items = data['items'] result.total_affected_items = data['totalItems'] return result
def get_rules(rule_ids=None, offset=0, limit=common.database_limit, sort_by=None, sort_ascending=True, search_text=None, complementary_search=False, search_in_fields=None): """Return information from all the security rules. It does not return information from its associated roles. :param rule_ids: List of rule ids (None for all rules) :param offset: First item to return :param limit: Maximum number of items to return :param sort_by: Fields to sort the items by. Format: {"fields":["field1","field2"],"order":"asc|desc"} :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 :return: Dictionary: {'items': array of items, 'totalItems': Number of items (without applying the limit)} """ affected_items = list() result = AffectedItemsWazuhResult( none_msg='No security rule was returned', some_msg='Some security rules were not returned', all_msg='All specified security rules were returned') with RulesManager() as rum: for ru_id in rule_ids: rule = rum.get_rule(int(ru_id)) if rule != SecurityError.RULE_NOT_EXIST: affected_items.append(rule) else: # Rule id does not exist result.add_failed_item(id_=ru_id, error=WazuhError(4022)) data = process_array(affected_items, 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'] return result
def upload_decoder_file(filename: str, content: str, overwrite: bool = False) -> AffectedItemsWazuhResult: """Upload a new decoder file or update an existing one. Parameters ---------- filename : str Name of the decoder file. content : str Content of the file. It must be a valid XML file. overwrite : bool True for updating existing files. False otherwise. Returns ------- AffectedItemsWazuhResult """ result = AffectedItemsWazuhResult( all_msg='Decoder was successfully uploaded', none_msg='Could not upload decoder') full_path = join(common.user_decoders_path, filename) backup_file = '' try: if len(content) == 0: raise WazuhError(1112) validate_wazuh_xml(content) # If file already exists and overwrite is False, raise exception if not overwrite and exists(full_path): raise WazuhError(1905) elif overwrite and exists(full_path): backup_file = f'{full_path}.backup' delete_file_with_backup(backup_file, full_path, delete_decoder_file) upload_file(content, to_relative_path(full_path)) result.affected_items.append(to_relative_path(full_path)) result.total_affected_items = len(result.affected_items) backup_file and exists(backup_file) and remove(backup_file) except WazuhError as e: result.add_failed_item(id_=to_relative_path(full_path), error=e) finally: exists(backup_file) and safe_move( backup_file, full_path, permissions=0o0660) return result
def update_ossec_conf(new_conf=None): """ Replace wazuh configuration (ossec.conf) with the provided configuration. Parameters ---------- new_conf: str The new configuration to be applied. """ result = AffectedItemsWazuhResult( all_msg=f"Configuration was successfully updated" f"{' in specified node' if node_id != 'manager' else ''}", some_msg='Could not update configuration in some nodes', none_msg=f"Could not update configuration" f"{' in specified node' if node_id != 'manager' else ''}") backup_file = f'{common.ossec_conf}.backup' try: # Check a configuration has been provided if not new_conf: raise WazuhError(1125) # Check if the configuration is valid validate_wazuh_xml(new_conf, config_file=True) # Create a backup of the current configuration before attempting to replace it try: copyfile(common.ossec_conf, backup_file) except IOError: raise WazuhError(1019) # Write the new configuration and validate it write_ossec_conf(new_conf) is_valid = validate_ossec_conf() if not isinstance(is_valid, dict) or ('status' in is_valid and is_valid['status'] != 'OK'): raise WazuhError(1125) else: result.affected_items.append(node_id) exists(backup_file) and remove(backup_file) except WazuhError as e: result.add_failed_item(id_=node_id, error=e) finally: exists(backup_file) and safe_move(backup_file, common.ossec_conf) result.total_affected_items = len(result.affected_items) return result
def set_user_role(user_id, role_ids, position=None): """Create a relationship between a user and a role. Parameters ---------- user_id : list User ID role_ids : list of int List of role ids position : int Position where the new role will be inserted Returns ------- Dict User-Roles information """ if position is not None and position < 0: raise WazuhError(4018) username = get_username(user_id=user_id) result = AffectedItemsWazuhResult( none_msg=f'No link was created to user {username}', some_msg=f'Some roles were not linked to user {username}', all_msg=f'All roles were linked to user {username}') success = False with UserRolesManager() as urm: for role_id in role_ids: user_role = urm.add_role_to_user(user_id=int(user_id[0]), role_id=int(role_id), position=position) if user_role == SecurityError.ALREADY_EXIST: result.add_failed_item(id_=int(role_id), error=WazuhError(4017)) elif user_role == SecurityError.ROLE_NOT_EXIST: result.add_failed_item(id_=int(role_id), error=WazuhError(4002)) elif user_role == SecurityError.USER_NOT_EXIST: result.add_failed_item(id_=int(user_id[0]), error=WazuhError(5001)) break elif user_role == SecurityError.ADMIN_RESOURCES: result.add_failed_item(id_=int(user_id[0]), error=WazuhError(4008)) else: success = True result.total_affected_items += 1 if position is not None: position += 1 if success: with AuthenticationManager() as auth: result.affected_items.append(auth.get_user_id(int(user_id[0]))) result.affected_items.sort(key=str) invalid_users_tokens(users=user_id) return result
def clear(agent_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") wdb_conn = WazuhDBConnection() system_agents = get_agents_info() for agent in agent_list: if agent not in system_agents: 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_policies(policy_ids, offset=0, limit=common.database_limit, sort_by=None, sort_ascending=True, search_text=None, complementary_search=False, search_in_fields=None): """Returns the information of a certain policy :param policy_ids: ID of the policy on which the information will be collected (All for all policies) :param offset: First item to return :param limit: Maximum number of items to return :param sort_by: Fields to sort the items by. Format: {"fields":["field1","field2"],"order":"asc|desc"} :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 :return: Dictionary: {'items': array of items, 'totalItems': Number of items (without applying the limit)} """ result = AffectedItemsWazuhResult( none_msg='No policy was returned', some_msg='Some policies were not returned', all_msg='All specified policies were returned') affected_items = list() with PoliciesManager() as pm: for p_id in policy_ids: policy = pm.get_policy_id(int(p_id)) if policy != SecurityError.POLICY_NOT_EXIST: affected_items.append(policy) else: # Policy id does not exist result.add_failed_item(id_=int(p_id), error=WazuhError(4007)) data = process_array(affected_items, 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'] return result
def get_agent_groups(group_list=None, offset=0, limit=None, sort=None, search=None, hash_algorithm='md5'): """Gets the existing groups. :param group_list: List of Group names. :param offset: First item to return. :param limit: Maximum number of items to return. :param sort: Fields to sort the items by. :param search: Text to search. :param hash_algorithm: hash algorithm used to get mergedsum and configsum. :return: AffectedItemsWazuhResult. """ affected_groups = list() result = AffectedItemsWazuhResult(all_msg='All selected groups information was returned', some_msg='Some groups information was not returned', none_msg='No group information was returned' ) if group_list: system_groups= get_groups() # Add failed items for invalid_group in set(group_list) - system_groups: result.add_failed_item(id_=invalid_group, error=WazuhResourceNotFound(1710)) rbac_filters = get_rbac_filters(system_resources=system_groups, permitted_resources=group_list) group_query = WazuhDBQueryGroup(offset=offset, limit=limit, sort=sort, search=search, **rbac_filters) query_data = group_query.run() for group in query_data['items']: full_entry = path.join(common.shared_path, group['name']) # merged.mg and agent.conf sum merged_sum = get_hash(path.join(full_entry, "merged.mg"), hash_algorithm) conf_sum = get_hash(path.join(full_entry, "agent.conf"), hash_algorithm) if merged_sum: group['mergedSum'] = merged_sum if conf_sum: group['configSum'] = conf_sum affected_groups.append(group) result.affected_items = affected_groups result.total_affected_items = query_data['totalItems'] return result
def 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 with WazuhDBQueryAgents(limit=None, select=["id", "status"], query=f'status!=active', **rbac_filters) as db_query: non_eligible_agents = db_query.run()['items'] [result.add_failed_item( id_=agent['id'], error=WazuhError(1707)) for agent in non_eligible_agents] wq = WazuhQueue(common.ARQUEUE) eligible_agents = agent_list - not_found_agents - {d['id'] for d in non_eligible_agents} for agent_id in eligible_agents: try: wq.send_msg_to_agent(WazuhQueue.HC_SK_RESTART, agent_id) result.affected_items.append(agent_id) except WazuhError as e: result.add_failed_item(id_=agent_id, error=e) wq.close() result.affected_items.sort(key=int) result.total_affected_items = len(result.affected_items) return result
def get_upgrade_result(agent_list=None): """Read upgrade result output from agent. Parameters ---------- agent_list : list List of agent ID's. Returns ------- Upgrade result. """ result = AffectedItemsWazuhResult( all_msg='All upgrade tasks were returned', some_msg='Some upgrade tasks were not returned', none_msg='No upgrade task was returned') agent_list = list( map(int, agents_padding(result=result, agent_list=agent_list))) agents_result_chunks = [ agent_list[x:x + 100] for x in range(0, len(agent_list), 100) ] task_results = list() for agents_chunk in agents_result_chunks: task_results.append( core_upgrade_agents(agents_chunk=agents_chunk, get_result=True)) for task_result_chunk in task_results: for task_result in task_result_chunk['data']: task_error = task_result.pop('error') if task_error == 0: task_result['agent'] = str(task_result['agent']).zfill(3) result.affected_items.append(task_result) result.total_affected_items += 1 else: error = WazuhError(code=1810 + task_error, cmd_error=True, extra_message=task_result['message']) result.add_failed_item(id_=str( task_result.pop('agent')).zfill(3), error=error) result.affected_items = sorted(result.affected_items, key=lambda k: k['agent']) return result
def get_users(user_ids: list = None, offset: int = 0, limit: int = common.database_limit, sort_by: dict = None, sort_ascending: bool = True, search_text: str = None, complementary_search: bool = False, search_in_fields: list = None): """Get the information of a specified user Parameters ---------- user_ids : list List of user ids offset : int First item to return limit : int Maximum number of items to return sort_by : dict Fields to sort the items by. Format: {"fields":["field1","field2"],"order":"asc|desc"} sort_ascending : bool Sort in ascending (true) or descending (false) order search_text : str Text to search complementary_search : bool Find items without the text to search search_in_fields : list Fields to search in Returns ------- AffectedItemsWazuhResult with the desired information """ result = AffectedItemsWazuhResult( none_msg='No user was returned', some_msg='Some users were not returned', all_msg='All specified users were returned') affected_items = list() with AuthenticationManager() as auth: for user_id in user_ids: user_id = int(user_id) user = auth.get_user_id(user_id) affected_items.append(user) if user else result.add_failed_item( id_=user_id, error=WazuhError(5001)) data = process_array(affected_items, 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'] return result
def get_api_config(): """Returns current API configuration. Returns ------- result : AffectedItemsWazuhResult Current API configuration of the manager. """ result = AffectedItemsWazuhResult(**_get_config_default_result_kwargs) try: api_config = {'node_name': node_id, 'node_api_config': get_api_conf()} result.affected_items.append(api_config) except WazuhError as e: result.add_failed_item(id_=node_id, error=e) result.total_affected_items = len(result.affected_items) return result