def get_item_agent(agent_id, offset, limit, select, search, sort, filters, valid_select_fields, allowed_sort_fields, table, nested=True, array=False): Agent(agent_id).get_basic_information() if select: select_fields = list(set(select['fields']) & set(valid_select_fields)) if select_fields == []: incorrect_fields = map(lambda x: str(x), set(select['fields']) - set(valid_select_fields)) raise WazuhException(1724, "Allowed select fields: {0}. Fields {1}".\ format(', '.join(valid_select_fields), ','.join(incorrect_fields))) else: select_fields = valid_select_fields if search: search['fields'] = valid_select_fields # Sorting if sort and sort['fields']: # Check if every element in sort['fields'] is in allowed_sort_fields. if not set(sort['fields']).issubset(allowed_sort_fields): raise WazuhException(1403, 'Allowed sort fields: {0}. Fields: {1}'.format( ', '.join(allowed_sort_fields), ','.join(sort['fields']))) response, total = Agent(agent_id)._load_info_from_agent_db(table=table, offset=offset, limit=limit, select=select_fields, count=True, sort=sort, search=search, filters=filters) if array: return_data = response if not nested else list(map(lambda x: plain_dict_to_nested_dict(x), response)) elif not response: return_data = {} else: return_data = response[0] if not nested else plain_dict_to_nested_dict(response[0]) return {'items': return_data, 'totalItems': total} if array else return_data
def _get_agent_items(func, offset, limit, select, filters, search, sort, array=False, query=''): agents, result = Agent.get_agents_overview(select={'fields': ['id']})['items'], [] total = 0 for agent in agents: items = func(agent_id=agent['id'], select=select, filters=filters, limit=limit, offset=offset, search=search, sort=sort, nested=False, q=query) if items == {}: continue total += 1 if not array else items['totalItems'] items = [items] if not array else items['items'] for item in items: if 0 < limit <= len(result): break item['agent_id'] = agent['id'] result.append(item) if result: if sort and sort['fields']: result = sorted(result, key=itemgetter(sort['fields'][0]), reverse=True if sort['order'] == "desc" else False) fields_to_nest, non_nested = get_fields_to_nest(result[0].keys(), '_') else: fields_to_nest, non_nested = None, None return {'items': list(map(lambda x: plain_dict_to_nested_dict(x, fields_to_nest, non_nested, WazuhDBQuerySyscollector.nested_fields, '_'), result)), 'totalItems': total}
def _format_data_into_dictionary(self): if self.nested: fields_to_nest, non_nested = get_fields_to_nest( self.fields.keys(), self.nested_fields, '_') self._data = [ plain_dict_to_nested_dict(d, fields_to_nest, non_nested, self.nested_fields, '_') for d in self._data ] return super()._format_data_into_dictionary() if self.array else next( iter(self._data), {})
def get_agents_without_group(offset=0, limit=common.database_limit, sort=None, search=None, select=None): """ Gets the agents in a group :param group_id: Group ID. :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. :return: Dictionary: {'items': array of items, 'totalItems': Number of items (without applying the limit)} """ # Connect DB db_global = glob(common.database_path_global) if not db_global: raise WazuhException(1600) conn = Connection(db_global[0]) valid_select_fiels = { "id", "name", "ip", "last_keepalive", "os_name", "os_version", "os_platform", "os_uname", "version", "config_sum", "merged_sum", "manager_host", "status" } # fields like status need to retrieve others to be properly computed. dependent_select_fields = {'status': {'last_keepalive', 'version'}} search_fields = {"id", "name", "os_name"} # Init query query = "SELECT {0} FROM agent WHERE `group` IS NULL AND id != 0" fields = {'id': 'id', 'name': 'name'} # field: db_column request = {} # Select if select: select_fields_param = set(select['fields']) if not select_fields_param.issubset(valid_select_fiels): uncorrect_fields = select_fields_param - valid_select_fiels raise WazuhException(1724, "Allowed select fields: {0}. Fields {1}".\ format(', '.join(list(valid_select_fiels)), ', '.join(uncorrect_fields))) select_fields = select_fields_param else: select_fields = valid_select_fiels # add dependent select fields to the database select query db_select_fields = set() for dependent, dependent_fields in dependent_select_fields.items(): if dependent in select_fields: db_select_fields |= dependent_fields db_select_fields |= (select_fields - set(dependent_select_fields.keys())) # Search if search: query += " AND NOT" if bool(search['negation']) else ' AND' query += " (" + " OR ".join(x + ' LIKE :search' for x in search_fields) + " )" request['search'] = '%{0}%'.format( int(search['value']) if search['value'].isdigit( ) else search['value']) # Count conn.execute(query.format('COUNT(*)'), request) data = {'totalItems': conn.fetch()[0]} # Sorting if sort: if sort['fields']: allowed_sort_fields = db_select_fields # Check if every element in sort['fields'] is in allowed_sort_fields. if not set(sort['fields']).issubset(allowed_sort_fields): raise WazuhException(1403, 'Allowed sort fields: {0}. Fields: {1}'.\ format(allowed_sort_fields, sort['fields'])) order_str_fields = [ '{0} {1}'.format(fields[i], sort['order']) for i in sort['fields'] ] query += ' ORDER BY ' + ','.join(order_str_fields) else: query += ' ORDER BY id {0}'.format(sort['order']) else: query += ' ORDER BY id ASC' # OFFSET - LIMIT if limit: query += ' LIMIT :offset,:limit' request['offset'] = offset request['limit'] = limit # Data query conn.execute(query.format(','.join(db_select_fields)), request) non_nested = [{field:tuple_elem for field,tuple_elem \ in zip(db_select_fields, tuple) if tuple_elem} for tuple in conn] if 'id' in select_fields: map(lambda x: setitem(x, 'id', str(x['id']).zfill(3)), non_nested) if 'status' in select_fields: try: map( lambda x: setitem( x, 'status', Agent.calculate_status(x['last_keepalive'], x['version'] == None)), non_nested) except KeyError: pass # return only the fields requested by the user (saved in select_fields) and not the dependent ones non_nested = [{k: v for k, v in d.items() if k in select_fields} for d in non_nested] data['items'] = [plain_dict_to_nested_dict(d, ['os']) for d in non_nested] return data
def get_agent_group(group_id, offset=0, limit=common.database_limit, sort=None, search=None, select=None): """ Gets the agents in a group :param group_id: Group ID. :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. :return: Dictionary: {'items': array of items, 'totalItems': Number of items (without applying the limit)} """ # Connect DB db_global = glob(common.database_path_global) if not db_global: raise WazuhException(1600) conn = Connection(db_global[0]) valid_select_fiels = [ "id", "name", "ip", "last_keepalive", "os_name", "os_version", "os_platform", "os_uname", "version", "config_sum", "merged_sum", "manager_host" ] search_fields = {"id", "name", "os_name"} # Init query query = "SELECT {0} FROM agent WHERE `group` = :group_id" fields = {'id': 'id', 'name': 'name'} # field: db_column request = {'group_id': group_id} # Select if select: if not set(select['fields']).issubset(valid_select_fiels): uncorrect_fields = map( lambda x: str(x), set(select['fields']) - set(valid_select_fiels)) raise WazuhException(1724, "Allowed select fields: {0}. Fields {1}".\ format(valid_select_fiels, uncorrect_fields)) select_fields = select['fields'] else: select_fields = valid_select_fiels # Search if search: query += " AND NOT" if bool(search['negation']) else ' AND' query += " (" + " OR ".join(x + ' LIKE :search' for x in search_fields) + " )" request['search'] = '%{0}%'.format( int(search['value']) if search['value'].isdigit( ) else search['value']) # Count conn.execute(query.format('COUNT(*)'), request) data = {'totalItems': conn.fetch()[0]} # Sorting if sort: if sort['fields']: allowed_sort_fields = select_fields # Check if every element in sort['fields'] is in allowed_sort_fields. if not set(sort['fields']).issubset(allowed_sort_fields): raise WazuhException(1403, 'Allowed sort fields: {0}. Fields: {1}'.\ format(allowed_sort_fields, sort['fields'])) order_str_fields = [ '{0} {1}'.format(fields[i], sort['order']) for i in sort['fields'] ] query += ' ORDER BY ' + ','.join(order_str_fields) else: query += ' ORDER BY id {0}'.format(sort['order']) else: query += ' ORDER BY id ASC' # OFFSET - LIMIT if limit: query += ' LIMIT :offset,:limit' request['offset'] = offset request['limit'] = limit # Data query conn.execute(query.format(','.join(select_fields)), request) non_nested = [{field:tuple_elem for field,tuple_elem \ in zip(select_fields, tuple) if tuple_elem} for tuple in conn] map(lambda x: setitem(x, 'id', str(x['id']).zfill(3)), non_nested) data['items'] = [plain_dict_to_nested_dict(d, ['os']) for d in non_nested] return data
def _nest_dictionary_by_keys(fields, dict, keys): fields_to_nest, non_nested = get_fields_to_nest(fields.values(), keys, '.') return [plain_dict_to_nested_dict(d, fields_to_nest, non_nested, keys, '.') for d in dict]