def get_related_computers_of_ou(self, ou, related_computers, related_objects): if self.walking_here(ou, related_objects): return related_computers computers = self.db.nodes.find({ 'path': get_filter_nodes_belonging_ou(ou['_id']), 'type': 'computer' }) for computer in computers: self.get_related_computers_of_computer(computer, related_computers, related_objects) users = self.db.nodes.find({ 'path': get_filter_nodes_belonging_ou(ou['_id']), 'type': 'user' }) for user in users: self.get_related_computers_of_user(user, related_computers, related_objects) groups = self.db.nodes.find({ 'path': get_filter_nodes_belonging_ou(ou['_id']), 'type': 'group' }) for group in groups: self.get_related_computers_of_group(group, related_computers, related_objects) return related_computers
def get_related_computers_of_ou(self, ou, related_computers, related_objects): if self.walking_here(ou, related_objects): return related_computers computers = self.db.nodes.find({'path': get_filter_nodes_belonging_ou(ou['_id']), 'type': 'computer'}) for computer in computers: self.get_related_computers_of_computer(computer, related_computers, related_objects) users = self.db.nodes.find({'path': get_filter_nodes_belonging_ou(ou['_id']), 'type': 'user'}) for user in users: self.get_related_computers_of_user(user, related_computers, related_objects) groups = self.db.nodes.find({'path': get_filter_nodes_belonging_ou(ou['_id']), 'type': 'group'}) for group in groups: self.get_related_computers_of_group(group, related_computers, related_objects) return related_computers
def report_storages(context, request, file_ext): ''' Generate a report with all the storages and its related users. Args: ou_id (string) : ID of the OU. Returns: headers (list) : The headers of the table to export rows (list) : Rows with the report data widths (list) : The witdhs of the columns of the table to export page : Translation of the word "page" to the current language of : Translation of the word "of" to the current language report_type : Type of report (html, csv or pdf) ''' # Check current user permissions ou_id = check_visibility_of_ou(request) if ou_id is None: raise HTTPBadRequest() # Get storages policy policy = request.db.policies.find_one({'slug': 'storage_can_view'}) property_name = 'policies.' + str(policy['_id']) + '.object_related_list' # Get all storages query = request.db.nodes.find( {'type': 'storage','path': get_filter_nodes_belonging_ou(ou_id)}) rows = [] if file_ext == 'pdf': for item in query: row = [] # No path in PDF because it's too long row.append('--') row.append(item['name']) row.append(item['uri']) row.append(item['_id']) # Get all nodes related with this storage nodes_query = request.db.nodes.find({property_name: str(item['_id'])}) # Targets: ou, group or user users = [] for node in nodes_query: if node['type'] == 'ou': users = list(request.db.nodes.find( {'path': get_filter_nodes_belonging_ou(node['_id']), 'type': 'user'})) elif node['type'] == 'group': users = list(request.db.nodes.find( {'_id': node['members'], 'type': 'user'})) elif node['type'] == 'user': users = [node] if len(users) == 0: row.append('--') row.append('--') rows.append(row) else: for user in users: user_row = list(row) user_row.append(user['name']) # No path in PDF because it's too long user_row.append('--') rows.append(user_row) else: for item in query: row = [] item['complete_path'] = get_complete_path(request.db, item['path']) row.append(treatment_string_to_csv(item, 'complete_path')) if file_ext == 'csv': row.append(treatment_string_to_csv(item, 'name')) else: # html links row.append(get_html_node_link(item)) row.append(treatment_string_to_csv(item, 'uri')) row.append(item['_id']) # Get all nodes related with this printer nodes_query = request.db.nodes.find({property_name: str(item['_id'])}) # Targets: ou, group or user users = [] for node in nodes_query: if node['type'] == 'ou': users = list(request.db.nodes.find( {'path': get_filter_nodes_belonging_ou(node['_id']), 'type': 'user'})) elif node['type'] == 'group': users = list(request.db.nodes.find( {'_id': node['members'], 'type': 'user'})) elif node['type'] == 'user': users = [node] if len(users) == 0: row.append('--') rows.append(row) else: for user in users: user_row = list(row) if file_ext == 'csv': user_row.append(treatment_string_to_csv(user, 'name')) else: # html links user_row.append(get_html_node_link(user)) user['complete_path'] = get_complete_path(request.db, item['path']) rows.append(user_row) header = (_(u'Path').encode('utf-8'), _(u'Name').encode('utf-8'), _(u'Uri').encode('utf-8'), _(u'Id').encode('utf-8'), _(u'User').encode('utf-8')) # Column widths in percentage widths = (0, 20, 45, 15, 20, 0) title = _(u'Storages and related users report') now = datetime.datetime.now().strftime("%d/%m/%Y %H:%M") return {'headers': header, 'rows': rows, 'widths': widths, 'report_title': title, 'page': _(u'Page').encode('utf-8'), 'of': _(u'of').encode('utf-8'), 'report_type': file_ext, 'now': now}
def report_computer(context, request, file_ext): ''' Generate a report with all the computers that belongs to an OU. If the administrator is a superadmin the generated report will contain all the computers in the database. Args: ou_id (string) : ID of the OU. Returns: headers (list) : The headers of the table to export rows (list) : Rows with the report data widths (list) : The witdhs of the columns of the table to export page : Translation of the word "page" to the current language of : Translation of the word "of" to the current language report_type : Type of report (html, csv or pdf) ''' # Check current user permissions ou_id = check_visibility_of_ou(request) if ou_id is None: raise HTTPBadRequest() # Get user data query = request.db.nodes.find({ 'type': 'computer', 'path': get_filter_nodes_belonging_ou(ou_id) }) if file_ext == 'pdf': rows = [ ( treatment_string_to_pdf(item, 'name', 20), treatment_string_to_pdf(item, 'family', 10), treatment_string_to_pdf(item, 'registry', 10), treatment_string_to_pdf(item, 'serial', 15), #treatment_string_to_pdf(item, 'node_chef_id', 25), item['_id']) for item in query ] else: rows = [(treatment_string_to_csv(item, 'name') if file_ext == 'csv' \ else get_html_node_link(item), treatment_string_to_csv(item, 'family'), treatment_string_to_csv(item, 'registry'), treatment_string_to_csv(item, 'serial'), #treatment_string_to_csv(item, 'node_chef_id'), item['_id']) for item in query] header = ( _(u'Name'), _(u'Type'), _(u'Registry number'), _(u'Serial number'), #_(u'Node chef id'), _(u'Id')) # Column widths in percentage widths = (20, 20, 20, 20, 20) title = _(u'Computers report') now = datetime.datetime.now().strftime("%d/%m/%Y %H:%M") # Sort rows # TODO: Use MongoDB Collations to do a "ignore_case" sorting # (MongoDB 2.6 does not support "ignore case" sorting) rows = sorted(rows, key=lambda i: (i[0].lower())) return { 'headers': header, 'rows': rows, 'widths': widths, 'default_order': [[0, 'asc']], 'report_title': title, 'page': _(u'Page'), 'of': _(u'of'), 'report_type': file_ext, 'now': now }
def report_no_user_computers(context, request, file_ext): ''' Generate a report with all the no-user computers that belongs to a OU. If the administrator is a superadmin the generated report will contain all the users in the database. Args: ou_id (string) : ID of the OU. Returns: headers (list) : The headers of the table to export rows (list) : Rows with the report data widths (list) : The witdhs of the columns of the table to export page : Translation of the word "page" to the current language of : Translation of the word "of" to the current language report_type : Type of report (html, csv or pdf) ''' # Check current user permissions ou_id = check_visibility_of_ou(request) if ou_id is None: raise HTTPBadRequest() task = ChefTask() related_computers = [] related_objects = [] filters = ({'type': 'user', 'path': get_filter_nodes_belonging_ou(ou_id)}) logger.info("report_no-user_computers: filters = {}".format(filters)) users = request.db.nodes.find(filters) for user in users: related_computers = task.get_related_computers_of_user( user, related_computers, related_objects) references = [c['_id'] for c in related_computers] logger.info("report_no-user_computers: references = {}".format(references)) filters2 = ({ 'type': 'computer', 'path': get_filter_nodes_belonging_ou(ou_id) }) filters2.update({'_id': {'$nin': [c['_id'] for c in related_computers]}}) logger.info("report_no-user_computers: filters2 = {}".format(filters2)) computers = request.db.nodes.find(filters2) rows = [] if file_ext == 'pdf': rows = [(item['name'], treatment_string_to_pdf(item, 'family', 15), treatment_string_to_pdf(item, 'registry', 15), treatment_string_to_pdf(item, 'serial', 20), item['node_chef_id'], item['_id']) for item in computers] else: rows = [(treatment_string_to_csv(item, 'name') if file_ext == 'csv' \ else get_html_node_link(item), treatment_string_to_csv(item, 'family'), treatment_string_to_csv(item, 'registry'), treatment_string_to_csv(item, 'serial'), treatment_string_to_csv(item, 'node_chef_id'), item['_id']) for item in computers] header = (_(u'Name').encode('utf-8'), _(u'Type').encode('utf-8'), _(u'Registry number').encode('utf-8'), _(u'Serial number').encode('utf-8'), _(u'Node chef id').encode('utf-8'), _(u'Id').encode('utf-8')) # Column widths in percentage widths = (25, 10, 15, 15, 20, 15) title = _(u'No-user computers') now = datetime.datetime.now().strftime("%d/%m/%Y %H:%M") # Sort rows # TODO: Use MongoDB Collations to do a "ignore_case" sorting # (MongoDB 2.6 does not support "ignore case" sorting) rows = sorted(rows, key=lambda i: (i[0].lower())) return { 'headers': header, 'rows': rows, 'default_order': [[0, 'asc']], 'widths': widths, 'report_title': title, 'page': _(u'Page').encode('utf-8'), 'of': _(u'of').encode('utf-8'), 'report_type': file_ext, 'now': now }
def report_status(context, request, file_ext): ''' Generate a report with all the users that belongs to an OU. If the administrator is a superadmin the generated report will contain all the users in the database. Args: ou_id (string) : ID of the OU. Returns: headers (list) : The headers of the table to export rows (list) : Rows with the report data widths (list) : The witdhs of the columns of the table to export page : Translation of the word "page" to the current language of : Translation of the word "of" to the current language report_type : Type of report (html, csv or pdf) ''' # Check current user permissions ou_id = check_visibility_of_ou(request) if ou_id is None: raise HTTPBadRequest() # Get user data query = request.db.nodes.find( {'type': 'computer','path': get_filter_nodes_belonging_ou(ou_id)}).sort('last_agent_run_time', -1) rows = [] current_time = int(time.time()) logger.debug("report_status: current_time = {}".format(current_time)) # update_error_interval: Hours. Converts it to seconds update_error_interval = timedelta(hours=int(get_current_registry().settings.get('update_error_interval', 24))).seconds logger.debug("report_status: update_error_interval = {}".format(update_error_interval)) # gecos-agent runs every 60 minutes (cron resource: minutes 30) # See https://github.com/gecos-team/gecos-workstation-management-cookbook/blob/master/recipes/default.rb (line: 57) # 10-min max delay margin of chef-client concurrent executions # See https://github.com/gecos-team/gecosws-agent/blob/trusty/scripts/gecos-chef-client-wrapper (line: 30) # 15-min delay margin of network or chef-client execution # 60 + 10 + 15 = 85 delay_margin = timedelta(minutes=85).seconds for item in query: row = [] last_agent_run_time = int(item.get('last_agent_run_time',0)) logger.debug("report_status: last_agent_run_time = {}".format(last_agent_run_time)) if last_agent_run_time + delay_margin >= current_time: item['status'] = '<div class="centered" style="width: 100%"><img alt="OK" src="/static/images/checkmark.jpg"/></div>' \ if file_ext != 'csv' else 'OK' # Chef-run error or update_error_interval hours has elapsed from last agent run time elif (item['error_last_chef_client'] or last_agent_run_time + update_error_interval >= current_time ): item['status'] = '<div class="centered" style="width: 100%"><img alt="ERROR" src="/static/images/xmark.jpg"/></div>' \ if file_ext != 'csv' else 'ERROR' # delay_margin < last_agent_run_time < update_error_interval else: item['status'] = '<div class="centered" style="width: 100%"><img alt="WARN" src="/static/images/alertmark.jpg"/></div>' \ if file_ext != 'csv' else 'WARN' if file_ext == 'pdf': row.append(treatment_string_to_pdf(item, 'name', 20)) row.append(item['_id']) if last_agent_run_time != 0: row.append(datetime.utcfromtimestamp(last_agent_run_time).strftime('%Y-%m-%d %H:%M:%S')) else: row.append(' -- ') row.append(item['status']) else: if file_ext == 'csv': row.append(treatment_string_to_csv(item, 'name')) else: row.append(get_html_node_link(item)) row.append(item['_id']) if last_agent_run_time != 0: row.append(datetime.utcfromtimestamp(last_agent_run_time).strftime('%Y-%m-%d %H:%M:%S')) else: row.append('--') row.append(treatment_string_to_csv(item, 'status')) rows.append(row) header = (_(u'Name').encode('utf-8'), _(u'Id').encode('utf-8'), _(u'Agent last runtime').encode('utf-8'), _(u'Status').encode('utf-8')) # Column widths in percentage if file_ext == 'pdf': widths = (45, 20, 20, 15) else: widths = (15, 35, 15, 20) title = _(u'Computer with anomalies') now = datetime.now().strftime("%d/%m/%Y %H:%M") return {'headers': header, 'rows': rows, 'widths': widths, 'report_title': title, 'page': _(u'Page').encode('utf-8'), 'of': _(u'of').encode('utf-8'), 'report_type': file_ext, 'now': now}
def report_computer(context, request, file_ext): ''' Generate a report with all the computers that belongs to an OU. If the administrator is a superadmin the generated report will contain all the computers in the database. Args: ou_id (string) : ID of the OU. Returns: headers (list) : The headers of the table to export rows (list) : Rows with the report data widths (list) : The witdhs of the columns of the table to export page : Translation of the word "page" to the current language of : Translation of the word "of" to the current language report_type : Type of report (html, csv or pdf) ''' # Check current user permissions ou_id = check_visibility_of_ou(request) if ou_id is None: raise HTTPBadRequest() # Get user data query = request.db.nodes.find( {'type': 'computer', 'path': get_filter_nodes_belonging_ou(ou_id)}) if file_ext == 'pdf': rows = [(treatment_string_to_pdf(item, 'name', 20), treatment_string_to_pdf(item, 'family', 10), treatment_string_to_pdf(item, 'registry', 10), treatment_string_to_pdf(item, 'serial', 15), #treatment_string_to_pdf(item, 'node_chef_id', 25), item['_id']) for item in query] else: rows = [(treatment_string_to_csv(item, 'name') if file_ext == 'csv' else get_html_node_link(item), treatment_string_to_csv(item, 'family'), treatment_string_to_csv(item, 'registry'), treatment_string_to_csv(item, 'serial'), #treatment_string_to_csv(item, 'node_chef_id'), item['_id']) for item in query] header = (_(u'Name').encode('utf-8'), _(u'Type').encode('utf-8'), _(u'Registry number').encode('utf-8'), _(u'Serial number').encode('utf-8'), #_(u'Node chef id').encode('utf-8'), _(u'Id').encode('utf-8')) # Column widths in percentage widths = (20, 20, 20, 20, 20) title = _(u'Computers report') now = datetime.datetime.now().strftime("%d/%m/%Y %H:%M") return {'headers': header, 'rows': rows, 'widths': widths, 'report_title': title, 'page': _(u'Page').encode('utf-8'), 'of': _(u'of').encode('utf-8'), 'report_type': file_ext, 'now': now}
def report_storages(context, request, file_ext): ''' Generate a report with all the storages and its related users. Args: ou_id (string) : ID of the OU. Returns: headers (list) : The headers of the table to export rows (list) : Rows with the report data widths (list) : The witdhs of the columns of the table to export page : Translation of the word "page" to the current language of : Translation of the word "of" to the current language report_type : Type of report (html, csv or pdf) ''' # Check current user permissions ou_id = check_visibility_of_ou(request) if ou_id is None: raise HTTPBadRequest() # Get storages policy policy = request.db.policies.find_one({'slug': 'storage_can_view'}) property_name = 'policies.' + str(policy['_id']) + '.object_related_list' # Get all storages query = request.db.nodes.find({ 'type': 'storage', 'path': get_filter_nodes_belonging_ou(ou_id) }) rows = [] if file_ext == 'pdf': for item in query: row = [] # No path in PDF because it's too long row.append('--') row.append(item['name']) row.append(item['uri']) row.append(item['_id']) # Get all nodes related with this storage nodes_query = request.db.nodes.find( {property_name: str(item['_id'])}) # Targets: ou, group or user users = [] for node in nodes_query: if node['type'] == 'ou': users = list( request.db.nodes.find({ 'path': get_filter_nodes_belonging_ou(node['_id']), 'type': 'user' })) elif node['type'] == 'group': users = list( request.db.nodes.find({ '_id': node['members'], 'type': 'user' })) elif node['type'] == 'user': users = [node] if len(users) == 0: row.append('--') row.append('--') rows.append(row) else: for user in users: user_row = list(row) user_row.append(user['name']) # No path in PDF because it's too long user_row.append('--') rows.append(user_row) else: for item in query: row = [] item['complete_path'] = get_complete_path(request.db, item['path']) row.append(treatment_string_to_csv(item, 'complete_path')) if file_ext == 'csv': row.append(treatment_string_to_csv(item, 'name')) else: # html links row.append(get_html_node_link(item)) row.append(treatment_string_to_csv(item, 'uri')) row.append(item['_id']) # Get all nodes related with this printer nodes_query = request.db.nodes.find( {property_name: str(item['_id'])}) # Targets: ou, group or user users = [] for node in nodes_query: if node['type'] == 'ou': users = list( request.db.nodes.find({ 'path': get_filter_nodes_belonging_ou(node['_id']), 'type': 'user' })) elif node['type'] == 'group': users = list( request.db.nodes.find({ '_id': node['members'], 'type': 'user' })) elif node['type'] == 'user': users = [node] if len(users) == 0: row.append('--') rows.append(row) else: for user in users: user_row = list(row) if file_ext == 'csv': user_row.append(treatment_string_to_csv(user, 'name')) else: # html links user_row.append(get_html_node_link(user)) user['complete_path'] = get_complete_path( request.db, item['path']) rows.append(user_row) header = (_(u'Path'), _(u'Name'), _(u'Uri'), _(u'Id'), _(u'User')) # Column widths in percentage widths = (0, 20, 45, 15, 20, 0) title = _(u'Storages and related users report') now = datetime.datetime.now().strftime("%d/%m/%Y %H:%M") # Sort rows rows = sorted(rows, key=lambda i: (i[0].lower(), i[1].lower(), i[4].lower())) return { 'headers': header, 'rows': rows, 'default_order': [[0, 'asc'], [1, 'asc'], [4, 'asc']], 'widths': widths, 'report_title': title, 'page': _(u'Page'), 'of': _(u'of'), 'report_type': file_ext, 'now': now }
def command(self): # Initialization sanitized = False computers = set() self.api = _get_chef_api(self.settings.get('chef.url'), toChefUsername(self.options.chef_username), self.options.chef_pem, False, self.settings.get('chef.version')) self.auth_user = self.db.adminusers.find_one( {'username': self.options.chef_username}) if self.auth_user is None: logger.error('The administrator user must exist in MongoDB') sys.exit(1) self.db = self.pyramid.db # Get local_users (Users) policy logger.info('Getting Users (local_users_res) policy ...') policy = self.db.policies.find_one({'name': 'Users'}) schema = policy['schema'] policyId = policy['_id'] logger.debug('schema = %s' % str(schema)) logger.debug('Id.policy = %s' % str(policyId)) # Searching nodes with the Users policy # Query Fields of an Embedded Document (Mongo documentation) # Example: # db.nodes.find({"policies.58c8122a0dfd425b0894d5b6":{$exists:true}}) logger.info('Searching nodes with the Users policy...') field = 'policies.' + str(policyId) filters = {field: {'$exists': True}} nodes = self.db.nodes.find(filters).sort([('path', 1), ('name', 1)]) # Validating data and, where appropiate, fixing for node in nodes: instance = node['policies'][unicode(policyId)] logger.info('Node name = %s, _id = %s' % (node['name'], str(node['_id']))) logger.info('Instance before validate method: %s' % str(instance)) while True: try: validate(instance, schema) break except ValidationError as e: logger.warning('Validation error on instance = %s' % str(e.message)) # Sanitize instance self.sanitize(e, instance) sanitized = True if sanitized: # Setting false sanitized for next iteration sanitized = False logger.info('Sanitized instance: %s' % str(instance)) # Update mongo self.db.nodes.update({'_id': node['_id']}, {'$set': { field: instance }}) # Affected nodes if node['type'] == 'ou': result = list( self.db.nodes.find( { 'path': get_filter_nodes_belonging_ou( node['_id']), 'type': 'computer' }, {'_id': 1})) logger.info('OU computers = %s' % str(result)) elif node['type'] == 'group': result = list( self.db.nodes.find( { '_id': { '$in': node['members'] }, 'type': 'computer' }, {'_id': 1})) logger.info('GROUP computers = %s' % str(result)) elif node['type'] == 'computer': result = [node] logger.info('COMPUTER computers = %s' % str(result)) [computers.add(str(n['_id'])) for n in result] for computer in computers: logger.info('computer = %s' % str(computer)) computer = self.db.nodes.find_one({'_id': ObjectId(computer)}) apply_policies_to_computer(self.db.nodes, computer, self.auth_user, api=self.api, initialize=False, use_celery=False) logger.info('Finished.')
def command(self): # Initialization sanitized = False computers = set() self.api = _get_chef_api(self.settings.get('chef.url'), toChefUsername(self.options.chef_username), self.options.chef_pem, False, self.settings.get('chef.version')) self.auth_user = self.db.adminusers.find_one({'username': self.options.chef_username}) if self.auth_user is None: logger.error('The administrator user must exist in MongoDB') sys.exit(1) self.db = self.pyramid.db # Get local_groups (Local groups) policy logger.info('Getting Local Groups (local_groups_res) policy ...') policy = self.db.policies.find_one({'name':'Local groups'}) schema = policy['schema'] policyId = policy['_id'] logger.debug('schema = %s'%str(schema)) logger.debug('Id.policy = %s'%str(policyId)) # Searching nodes with the Local Groups policy # Query Fields of an Embedded Document (Mongo documentation) # Example: # db.nodes.find({"policies.58c8122a0dfd425b0894d5b6":{$exists:true}}) logger.info('Searching nodes with the Local Groups policy...') field = 'policies.' + str(policyId) filters = {field:{'$exists':True}} nodes = self.db.nodes.find(filters).sort([('path',1),('name',1)]) # Validating data and, where appropiate, fixing for node in nodes: instance = node['policies'][unicode(policyId)] logger.info('Node name = %s, _id = %s)'%(node['name'],str(node['_id']))) logger.info('Instance before validate method: %s'%str(instance)) while True: try: validate(instance, schema) break except ValidationError as e: logger.warning('Validation error on instance = %s'%str(e.message)) # Sanitize instance self.sanitize(e, instance) sanitized = True if sanitized: # Setting false sanitized for next iteration sanitized = False logger.info('Sanitized instance: %s'%str(instance)) # Update mongo self.db.nodes.update({'_id': node['_id']},{'$set':{field:instance}}) # Affected nodes if node['type'] == 'ou': result = list(self.db.nodes.find({'path': get_filter_nodes_belonging_ou(node['_id']),'type': 'computer'},{'_id':1})) logger.info('OU computers = %s'%str(result)) elif node['type'] == 'group': result = list(self.db.nodes.find({'_id':{'$in':node['members']},'type':'computer'},{'_id':1})) logger.info('GROUP computers = %s'%str(result)) elif node['type'] == 'computer': result = [node] logger.info('COMPUTER computers = %s'%str(result)) [computers.add(str(n['_id'])) for n in result] for computer in computers: logger.info('computer = %s'%str(computer)) computer = self.db.nodes.find_one({'_id': ObjectId(computer)}) apply_policies_to_computer(self.db.nodes, computer, self.auth_user, api=self.api, initialize=False, use_celery=False) logger.info('Finished.')
def report_user(context, request, file_ext): ''' Generate a report with all the users that belongs to an OU. If the administrator is a superadmin the generated report will contain all the users in the database. Args: ou_id (string) : ID of the OU. Returns: headers (list) : The headers of the table to export rows (list) : Rows with the report data widths (list) : The witdhs of the columns of the table to export page : Translation of the word "page" to the current language of : Translation of the word "of" to the current language report_type : Type of report (html, csv or pdf) ''' # Check current user permissions ou_id = check_visibility_of_ou(request) if ou_id is None: raise HTTPBadRequest() # Get user data query = request.db.nodes.find( {'type': 'user','path': get_filter_nodes_belonging_ou(ou_id)}) rows = [] if file_ext == 'pdf': rows = [(' '+item['name'], ' '+item['first_name']+" "+item['last_name'], ' '+item['email'], ' '+item['phone'], ' '+item['address'], ' '+str(item['_id'])) for item in query] else: rows = [(treatment_string_to_csv(item, 'name') if file_ext == 'csv' \ else get_html_node_link(item), treatment_string_to_csv(item, 'first_name'), treatment_string_to_csv(item, 'last_name'), treatment_string_to_csv(item, 'email'), treatment_string_to_csv(item, 'phone'), treatment_string_to_csv(item, 'address'), str(item['_id'])) for item in query] if file_ext == 'pdf': header = (u'Username', u'Name', u'Email', u'Phone', u'Address', u'ID') else: header = (_(u'Username'), _(u'First name'), _(u'Last name'), _(u'Email'), _(u'Phone'), _(u'Address'), _(u'Id')) # Column widths in percentage if file_ext == 'pdf': widths = (15, 15, 25, 10, 15, 20) else: widths = (15, 25, 10, 10, 5, 20, 15) title = _(u'Users report') now = datetime.datetime.now().strftime("%d/%m/%Y %H:%M") # Sort rows # TODO: Use MongoDB Collations to do a "ignore_case" sorting # (MongoDB 2.6 does not support "ignore case" sorting) rows = sorted(rows, key = lambda i: (i[0].lower())) return {'headers': header, 'rows': rows, 'default_order': [[ 0, 'asc' ]], 'widths': widths, 'report_title': title, 'page': _(u'Page'), 'of': _(u'of'), 'report_type': file_ext, 'now': now}
def statistics(context, request): object_counters = [] policy_counters = [] ous = {} ous_visibles = [] settings = get_current_registry().settings policyname = "name_{}".format(settings['pyramid.default_locale_name']) is_superuser = request.user.get('is_superuser', False) ou_id = request.GET.get('ou_id', None) logger.debug("admins.py ::: statistics - ou_id = {}".format(ou_id)) if is_superuser: ous_visibles = request.db.nodes.find( {"type": "ou"}, {"_id": 1, "name": 1, "path": 1} ) else: # Get managed ous for admin oids = request.user.get('ou_managed', []) + request.user.get('ou_readonly', []) ous_visibles = request.db.nodes.find( {"_id": { "$in": map(ObjectId, oids) }}, {"_id": 1, "name": 1, "path": 1} ) for ou in ous_visibles: path = ou['path'] + ',' + str(ou['_id']) ous.update({str(ou['_id']): get_complete_path(request.db, path)}) sorted_ous = collections.OrderedDict(sorted(ous.items(), key=lambda kv: len(kv[1]))) logger.debug("admins.py ::: statistics - sorted_ous = {}".format(sorted_ous)) # Defaults if not ou_id: ou_id = str(sorted_ous.items()[0][0]) logger.debug("admins.py ::: statistics - ou_id = {}".format(ou_id)) # Objects object_counters = request.db.nodes.aggregate([ {"$match" : { "path": get_filter_nodes_belonging_ou(ou_id)}}, {"$group" : { "_id" : "$type", "count": {"$sum":1}}} ], cursor={}) logger.debug("admins.py ::: statistics - object_counters = {}".format(object_counters)) # Policies for pol in request.db.policies.find().sort("name"): c = request.db.nodes.find({ "$or": [{"path": get_filter_nodes_belonging_ou(ou_id)}, {"_id":ObjectId(ou_id)}], "policies." + str(pol['_id']): {'$exists': True} }).count() try: policy_counters.append([pol[policyname],c]) except KeyError: policy_counters.append([pol['name'],c]) logger.debug("admins.py ::: statistics - policy_counters = {}".format(policy_counters)) return { 'policy_counters': policy_counters, 'object_counters': object_counters, 'ou_managed': sorted_ous, 'ou_selected': ou_id, 'is_superuser': is_superuser }
def report_user(context, request, file_ext): ''' Generate a report with all the users that belongs to an OU. If the administrator is a superadmin the generated report will contain all the users in the database. Args: ou_id (string) : ID of the OU. Returns: headers (list) : The headers of the table to export rows (list) : Rows with the report data widths (list) : The witdhs of the columns of the table to export page : Translation of the word "page" to the current language of : Translation of the word "of" to the current language report_type : Type of report (html, csv or pdf) ''' # Check current user permissions ou_id = check_visibility_of_ou(request) if ou_id is None: raise HTTPBadRequest() # Get user data query = request.db.nodes.find( {'type': 'user','path': get_filter_nodes_belonging_ou(ou_id)}) rows = [] if file_ext == 'pdf': rows = [(' '+item['name'], ' '+item['first_name']+" "+item['last_name'], ' '+item['email'], ' '+item['phone'], ' '+item['address'], ' '+str(item['_id'])) for item in query] else: rows = [(treatment_string_to_csv(item, 'name') if file_ext == 'csv' else get_html_node_link(item), treatment_string_to_csv(item, 'first_name'), treatment_string_to_csv(item, 'last_name'), treatment_string_to_csv(item, 'email'), treatment_string_to_csv(item, 'phone'), treatment_string_to_csv(item, 'address'), str(item['_id'])) for item in query] if file_ext == 'pdf': header = (u'Username', u'Name', u'Email', u'Phone', u'Address', u'ID') else: header = (_(u'Username').encode('utf-8'), _(u'First name').encode('utf-8'), _(u'Last name').encode('utf-8'), _(u'Email').encode('utf-8'), _(u'Phone').encode('utf-8'), _(u'Address').encode('utf-8'), _(u'Id').encode('utf-8')) # Column widths in percentage if file_ext == 'pdf': widths = (15, 15, 25, 10, 15, 20) else: widths = (15, 25, 10, 10, 5, 20, 15) title = _(u'Users report') now = datetime.datetime.now().strftime("%d/%m/%Y %H:%M") return {'headers': header, 'rows': rows, 'widths': widths, 'report_title': title, 'page': _(u'Page').encode('utf-8'), 'of': _(u'of').encode('utf-8'), 'report_type': file_ext, 'now': now}
def command(self): # Initialization sanitized = False computers = set() self.api = _get_chef_api(self.settings.get('chef.url'), toChefUsername(self.options.chef_username), self.options.chef_pem, False, self.settings.get('chef.version')) self.auth_user = self.db.adminusers.find_one({'username': self.options.chef_username}) if self.auth_user is None: logger.error('The administrator user must exist in MongoDB') sys.exit(1) self.db = self.pyramid.db # Get local_admin_users_res (Local Administrators) policy logger.info('Getting Local Administrators (local_admin_users_res) policy ...') policy = self.db.policies.find_one({'slug':'local_admin_users_res'}) schema = policy['schema'] policyId = policy['_id'] logger.info('schema = %s'%str(schema)) logger.info('Id.policy = %s'%str(policyId)) # Searching nodes with the Local Administrators policy # Query Fields of an Embedded Document (Mongo documentation) # Example: # db.nodes.find({"policies.58c8122a0dfd425b0894d5b6":{$exists:true}}) logger.info('Searching nodes with the Local Administrators policy...') field = 'policies.' + str(policyId) filters = {field:{'$exists':True}} nodes = self.db.nodes.find(filters) # Validating data and, where appropiate, fixing for node in nodes: instance = node['policies'][unicode(policyId)] logger.info('Node name = %s, _id = %s'%(node['name'],str(node['_id']))) logger.info('Instance before validate method: %s'%str(instance)) while True: try: validate(instance, schema) break except ValidationError as e: logger.warning('Validation error on instance = %s'%str(e.message)) # Sanitize instance self.sanitize(e, instance) sanitized = True if sanitized: # Setting false sanitized for next iteration sanitized = False logger.info('Sanitized instance: %s'%str(instance)) # Update mongo self.db.nodes.update({'_id': node['_id']},{'$set':{field:instance}}) # Affected nodes if node['type'] == 'ou': result = list(self.db.nodes.find({'path': get_filter_nodes_belonging_ou(node['_id']),'type': 'computer'},{'_id':1})) logger.info('OU computers = %s'%str(result)) elif node['type'] == 'group': result = list(self.db.nodes.find({'_id':{'$in':node['members']},'type':'computer'},{'_id':1})) logger.info('GROUP computers = %s'%str(result)) elif node['type'] == 'computer': result = [node] logger.info('COMPUTER computers = %s'%str(result)) [computers.add(str(n['_id'])) for n in result] # Removing unused local_admin_remove_list attribute in chef nodes for node_id in ChefNode.list(): node = ChefNode(node_id, self.api) logger.info('Checking node: %s'%(node_id)) attr_dotted = policy['path'] + '.local_admin_remove_list' logger.info('Atttribute dotted path: %s'%(attr_dotted)) if node.attributes.has_dotted(attr_dotted): logger.info("Remove 'local_admin_remove_list' attribute!") try: logger.info("node.attributes = %s" % str(node.attributes['gecos_ws_mgmt']['misc_mgmt']['local_admin_users_res'].to_dict())) delete_dotted(node.attributes, attr_dotted) node.save() except: logger.warn("Problem deleting local_admin_remove_list value from node: %s"%(node_id)) logger.warn("You may be trying to delete a default attribute instead normal attribute: %s"%(node_id)) for computer in computers: logger.info('computer = %s'%str(computer)) computer = self.db.nodes.find_one({'_id': ObjectId(computer)}) apply_policies_to_computer(self.db.nodes, computer, self.auth_user, api=self.api, initialize=False, use_celery=False) logger.info('Finished.')
def command(self): # Initialization logger.info("MIGRATION SCRIPT FOR FILES LIST POLICY") logger.info("######################################") # Disabling InsecureRequestWarning Unverified HTTPS request requests.packages.urllib3.disable_warnings() sanitized = False computers = set() self.api = _get_chef_api(self.settings.get('chef.url'), toChefUsername(self.options.chef_username), self.options.chef_pem, False, self.settings.get('chef.version')) self.auth_user = self.db.adminusers.find_one({'username': self.options.chef_username}) if self.auth_user is None: logger.error('The administrator user must exist in MongoDB') sys.exit(1) self.db = self.pyramid.db # Get local_file (File list) policy logger.info('Getting policy schema (local_file_res) ...') policy = self.db.policies.find_one({'slug':'local_file_res'}) schema = policy['schema'] policyId = policy['_id'] logger.info('schema = %s'%str(schema)) logger.debug('policyId = %s'%str(policyId)) # Searching nodes with the File List policy # Query Fields of an Embedded Document (Mongo documentation) # Example: # db.nodes.find({"policies.58c8122a0dfd425b0894d5b6":{$exists:true}}) logger.info('Searching for nodes with applied policy...') field = 'policies.' + str(policyId) filters = {field:{'$exists':True}} nodes = self.db.nodes.find(filters) # Validating data and, where appropiate, fixing for node in nodes: instance = node['policies'][unicode(policyId)] logger.debug("node = %s" % str(node)) logger.info('-----------------------------------------------') logger.info('Node name = %s, mongo_id = %s'%(node['name'],str(node['_id']))) logger.info('Instance of the policy on the node: %s'%str(instance)) while True: try: validate(instance, schema) break except ValidationError as e: logger.warn('Validation error on instance: instance = %s'%str(instance)) logger.warn('Validation error on instance: message error = %s'%str(e.message)) # Sanitize instance self.sanitize(e, instance) sanitized = True if sanitized: # Setting false sanitized for next iteration sanitized = False logger.info('Sanitized instance of the policy on the node AFTER calling the validate method: %s'%str(instance)) # Update mongo logger.info('Updating instance in database (mongo) ...') self.db.nodes.update({'_id': node['_id']},{'$set':{field:instance}}) logger.info('Recalculating policies in the node.') # Affected nodes if node['type'] == 'ou': result = list(self.db.nodes.find({'path': get_filter_nodes_belonging_ou(node['_id']),'type': 'computer'},{'_id':1})) logger.info('OU computers = %s'%str(result)) elif node['type'] == 'group': result = list(self.db.nodes.find({'_id':{'$in':node['members']},'type':'computer'},{'_id':1})) logger.info('GROUP computers = %s'%str(result)) elif node['type'] == 'computer': result = [node] logger.info('COMPUTER computers = %s'%str(result)) [computers.add(str(n['_id'])) for n in result] for computer in computers: logger.info('Applying policies to COMPUTER. For more information, see "gecosccui-celery.log" file') computer = self.db.nodes.find_one({'_id': ObjectId(computer)}) apply_policies_to_computer(self.db.nodes, computer, self.auth_user, api=self.api, initialize=False, use_celery=True) # Removing unused attributes (copy_files, delete_files) in chef nodes logger.info('\n') attrs = ["%s.copy_files" % (policy['path']), "%s.delete_files" % (policy['path'])] logger.info('Removing unused attributes %s in chef nodes ...' % attrs) logger.info('\n') for node_id in ChefNode.list(): node = ChefNode(node_id, self.api) logger.info('Checking node: %s'%(node_id)) for attr in attrs: try: if node.attributes.has_dotted(attr): logger.warn("Remove %s attribute!" % attr) delete_dotted(node.attributes, attr) node.save() except: logger.warn("Problem deleting attribute %s value from node: %s"%(attr, node_id)) logger.warn("You may be trying to delete a default attribute instead normal attribute: %s"%(node_id)) logger.info('Finished.')
def command(self): # Initialization logger.info("MIGRATION SCRIPT FOR FILES LIST POLICY") logger.info("######################################") # Disabling InsecureRequestWarning Unverified HTTPS request requests.packages.urllib3.disable_warnings() sanitized = False computers = set() self.api = _get_chef_api(self.settings.get('chef.url'), toChefUsername(self.options.chef_username), self.options.chef_pem, False, self.settings.get('chef.version')) self.auth_user = self.db.adminusers.find_one( {'username': self.options.chef_username}) if self.auth_user is None: logger.error('The administrator user must exist in MongoDB') sys.exit(1) self.db = self.pyramid.db # Get local_file (File list) policy logger.info('Getting policy schema (local_file_res) ...') policy = self.db.policies.find_one({'slug': 'local_file_res'}) schema = policy['schema'] policyId = policy['_id'] logger.info('schema = %s' % str(schema)) logger.debug('policyId = %s' % str(policyId)) # Searching nodes with the File List policy # Query Fields of an Embedded Document (Mongo documentation) # Example: # db.nodes.find({"policies.58c8122a0dfd425b0894d5b6":{$exists:true}}) logger.info('Searching for nodes with applied policy...') field = 'policies.' + str(policyId) filters = {field: {'$exists': True}} nodes = self.db.nodes.find(filters) # Validating data and, where appropiate, fixing for node in nodes: instance = node['policies'][unicode(policyId)] logger.debug("node = %s" % str(node)) logger.info('-----------------------------------------------') logger.info('Node name = %s, mongo_id = %s' % (node['name'], str(node['_id']))) logger.info('Instance of the policy on the node: %s' % str(instance)) while True: try: validate(instance, schema) break except ValidationError as e: logger.warn('Validation error on instance: instance = %s' % str(instance)) logger.warn( 'Validation error on instance: message error = %s' % str(e.message)) # Sanitize instance self.sanitize(e, instance) sanitized = True if sanitized: # Setting false sanitized for next iteration sanitized = False logger.info( 'Sanitized instance of the policy on the node AFTER calling the validate method: %s' % str(instance)) # Update mongo logger.info('Updating instance in database (mongo) ...') self.db.nodes.update({'_id': node['_id']}, {'$set': { field: instance }}) logger.info('Recalculating policies in the node.') # Affected nodes if node['type'] == 'ou': result = list( self.db.nodes.find( { 'path': get_filter_nodes_belonging_ou( node['_id']), 'type': 'computer' }, {'_id': 1})) logger.info('OU computers = %s' % str(result)) elif node['type'] == 'group': result = list( self.db.nodes.find( { '_id': { '$in': node['members'] }, 'type': 'computer' }, {'_id': 1})) logger.info('GROUP computers = %s' % str(result)) elif node['type'] == 'computer': result = [node] logger.info('COMPUTER computers = %s' % str(result)) [computers.add(str(n['_id'])) for n in result] for computer in computers: logger.info( 'Applying policies to COMPUTER. For more information, see "gecosccui-celery.log" file' ) computer = self.db.nodes.find_one({'_id': ObjectId(computer)}) apply_policies_to_computer(self.db.nodes, computer, self.auth_user, api=self.api, initialize=False, use_celery=True) # Removing unused attributes (copy_files, delete_files) in chef nodes logger.info('\n') attrs = [ "%s.copy_files" % (policy['path']), "%s.delete_files" % (policy['path']) ] logger.info('Removing unused attributes %s in chef nodes ...' % attrs) logger.info('\n') for node_id in ChefNode.list(): node = ChefNode(node_id, self.api) logger.info('Checking node: %s' % (node_id)) for attr in attrs: try: if node.attributes.has_dotted(attr): logger.warn("Remove %s attribute!" % attr) delete_dotted(node.attributes, attr) node.save() except: logger.warn( "Problem deleting attribute %s value from node: %s" % (attr, node_id)) logger.warn( "You may be trying to delete a default attribute instead normal attribute: %s" % (node_id)) logger.info('Finished.')
def report_status(context, request, file_ext): ''' Generate a report with all the users that belongs to an OU. If the administrator is a superadmin the generated report will contain all the users in the database. Args: ou_id (string) : ID of the OU. Returns: headers (list) : The headers of the table to export rows (list) : Rows with the report data widths (list) : The witdhs of the columns of the table to export page : Translation of the word "page" to the current language of : Translation of the word "of" to the current language report_type : Type of report (html, csv or pdf) ''' # Check current user permissions ou_id = check_visibility_of_ou(request) if ou_id is None: raise HTTPBadRequest() # Get user data query = request.db.nodes.find( {'type': 'computer','path': get_filter_nodes_belonging_ou(ou_id)} ).sort( [('error_last_chef_client', pymongo.DESCENDING), ('last_agent_run_time', pymongo.DESCENDING), ('name', pymongo.ASCENDING) ] ) rows = [] orders = [] current_time = int(time.time()) logger.debug("report_status: current_time = {}".format(current_time)) # update_error_interval: Hours. Converts it to seconds update_error_interval = timedelta( hours=int(get_current_registry().settings.get( 'update_error_interval', 24))).seconds logger.debug("report_status: update_error_interval = {}".format( update_error_interval)) # gecos-agent runs every 60 minutes (cron resource: minutes 30) # See https://github.com/gecos-team/gecos-workstation-management-cookbook/blob/master/recipes/default.rb (line: 57) # 10-min max delay margin of chef-client concurrent executions # See https://github.com/gecos-team/gecosws-agent/blob/trusty/scripts/gecos-chef-client-wrapper (line: 30) # 15-min delay margin of network or chef-client execution # 60 + 10 + 15 = 85 delay_margin = timedelta(minutes=85).seconds for item in query: row = [] order = [] status = '0' last_agent_run_time = int(item.get('last_agent_run_time',0)) logger.debug("report_status: last_agent_run_time = {}".format( last_agent_run_time)) if last_agent_run_time + delay_margin >= current_time: item['status'] = '<div class="centered" style="width: 100%">'\ '<img alt="OK" src="/static/images/checkmark.jpg"/></div>' \ if file_ext != 'csv' else 'OK' status = '0' # Chef-run error or update_error_interval hours has elapsed from last agent run time elif (item['error_last_chef_client'] or last_agent_run_time + update_error_interval >= current_time ): item['status'] = '<div class="centered" style="width: 100%">'\ '<img alt="ERROR" src="/static/images/xmark.jpg"/></div>' \ if file_ext != 'csv' else 'ERROR' status = '2' # delay_margin < last_agent_run_time < update_error_interval else: item['status'] = '<div class="centered" style="width: 100%">'\ '<img alt="WARN" src="/static/images/alertmark.jpg"/></div>' \ if file_ext != 'csv' else 'WARN' status = '1' if file_ext == 'pdf': row.append(treatment_string_to_pdf(item, 'name', 20)) order.append('') row.append(item['_id']) order.append('') if last_agent_run_time != 0: row.append(datetime.utcfromtimestamp( last_agent_run_time).strftime('%d/%m/%Y %H:%M:%S')) else: row.append(' -- ') order.append(last_agent_run_time) row.append(item['status']) order.append(status) else: if file_ext == 'csv': row.append(treatment_string_to_csv(item, 'name')) else: row.append(get_html_node_link(item)) order.append('') row.append(item['_id']) order.append('') if last_agent_run_time != 0: row.append(datetime.utcfromtimestamp( last_agent_run_time).strftime('%d/%m/%Y %H:%M:%S')) else: row.append('--') order.append(last_agent_run_time) row.append(treatment_string_to_csv(item, 'status')) order.append(status) rows.append(row) orders.append(order) header = (_(u'Name').encode('utf-8'), _(u'Id').encode('utf-8'), _(u'Agent last runtime').encode('utf-8'), _(u'Status').encode('utf-8')) # Column widths in percentage if file_ext == 'pdf': widths = (45, 20, 20, 15) else: widths = (15, 35, 15, 20) title = _(u'Computer with anomalies') now = datetime.now().strftime("%d/%m/%Y %H:%M") # Sort rows rows = sorted(rows, key = lambda i: (get_status(i[3]), i[0].lower())) return {'headers': header, 'rows': rows, 'orders': orders, 'default_order': [[ 3, 'desc' ], [ 0, 'asc' ]], 'widths': widths, 'report_title': title, 'page': _(u'Page').encode('utf-8'), 'of': _(u'of').encode('utf-8'), 'report_type': file_ext, 'now': now}
def report_printers(context, request, file_ext): ''' Generate a report with all the printers and its related computers. Args: ou_id (string) : ID of the OU. Returns: headers (list) : The headers of the table to export rows (list) : Rows with the report data widths (list) : The witdhs of the columns of the table to export page : Translation of the word "page" to the current language of : Translation of the word "of" to the current language report_type : Type of report (html, csv or pdf) ''' # Check current user permissions ou_id = check_visibility_of_ou(request) if ou_id is None: raise HTTPBadRequest() # Get printers policy policy = request.db.policies.find_one({'slug': 'printer_can_view'}) property_name = 'policies.' + str(policy['_id']) + '.object_related_list' # Get all printers query = request.db.nodes.find( {'type': 'printer', 'path': get_filter_nodes_belonging_ou(ou_id)}) task = ChefTask() rows = [] if file_ext == 'pdf': for item in query: row = [] # No path in PDF because it's too long row.append('--') row.append(item['name']); row.append(treatment_string_to_pdf(item, 'manufacturer', 15)) row.append(treatment_string_to_pdf(item, 'model', 15)) row.append(treatment_string_to_pdf(item, 'serial', 15)) row.append(treatment_string_to_pdf(item, 'registry', 15)) # Get all nodes related with this printer nodes_query = request.db.nodes.find({property_name: str(item['_id'])}) related_computers = [] related_objects = [] for node in nodes_query: related_computers = task.get_related_computers(node, related_computers, related_objects) # Remove duplicated computers computer_paths = [] computers = [] for computer in related_computers: full_path = computer['path'] + '.' + computer['name'] if not full_path in computer_paths: computer_paths.append(full_path) computers.append(computer) if len(computers) == 0: row.append('--') rows.append(row) else: for computer in computers: computer_row = list(row) computer_row.append(treatment_string_to_pdf(computer, 'name', 15)) # No path in PDF because it's too long rows.append(computer_row) else: for item in query: row = [] item['complete_path'] = get_complete_path(request.db, item['path']) row.append(treatment_string_to_csv(item, 'complete_path')) row.append(treatment_string_to_csv(item, 'name') if file_ext == 'csv' else get_html_node_link(item)) row.append(treatment_string_to_csv(item, 'manufacturer')) row.append(treatment_string_to_csv(item, 'model')) row.append(treatment_string_to_csv(item, 'serial')) row.append(treatment_string_to_csv(item, 'registry')) # Get all nodes related with this printer nodes_query = request.db.nodes.find({property_name: str(item['_id'])}) related_computers = [] related_objects = [] for node in nodes_query: related_computers = task.get_related_computers(node, related_computers, related_objects) # Remove duplicated computers computer_paths = [] computers = [] for computer in related_computers: full_path = computer['path'] + '.' + computer['name'] if not full_path in computer_paths: computer_paths.append(full_path) computers.append(computer) if len(computers) == 0: row.append('--') rows.append(row) else: for computer in computers: computer_row = list(row) computer_row.append(treatment_string_to_csv(computer, 'name') if file_ext == 'csv' else get_html_node_link(computer)) computer['complete_path'] = get_complete_path(request.db, item['path']) rows.append(computer_row) header = (_(u'Path').encode('utf-8'), _(u'Name').encode('utf-8'), _(u'Manufacturer').encode('utf-8'), _(u'Model').encode('utf-8'), _(u'Serial number').encode('utf-8'), _(u'Registry number').encode('utf-8'), _(u'Computer').encode('utf-8')) # Column widths in percentage if file_ext == 'pdf': widths = (0, 25, 15, 15, 15, 15, 15) else: widths = (0, 20, 10, 10, 10, 10, 20) title = _(u'Printers and related computers report') now = datetime.datetime.now().strftime("%d/%m/%Y %H:%M") return {'headers': header, 'rows': rows, 'widths': widths, 'report_title': title, 'page': _(u'Page').encode('utf-8'), 'of': _(u'of').encode('utf-8'), 'report_type': file_ext, 'now': now}
def report_printers(context, request, file_ext): ''' Generate a report with all the printers and its related computers. Args: ou_id (string) : ID of the OU. Returns: headers (list) : The headers of the table to export rows (list) : Rows with the report data widths (list) : The witdhs of the columns of the table to export page : Translation of the word "page" to the current language of : Translation of the word "of" to the current language report_type : Type of report (html, csv or pdf) ''' # Check current user permissions ou_id = check_visibility_of_ou(request) if ou_id is None: raise HTTPBadRequest() # Get printers policy policy = request.db.policies.find_one({'slug': 'printer_can_view'}) property_name = 'policies.' + str(policy['_id']) + '.object_related_list' # Get all printers query = request.db.nodes.find( {'type': 'printer', 'path': get_filter_nodes_belonging_ou(ou_id)}) task = ChefTask() rows = [] if file_ext == 'pdf': for item in query: row = [] # No path in PDF because it's too long row.append('--') row.append(item['name']); row.append(treatment_string_to_pdf(item, 'manufacturer', 15)) row.append(treatment_string_to_pdf(item, 'model', 15)) row.append(treatment_string_to_pdf(item, 'serial', 15)) row.append(treatment_string_to_pdf(item, 'registry', 15)) # Get all nodes related with this printer nodes_query = request.db.nodes.find( {property_name: str(item['_id'])}) related_computers = [] related_objects = [] for node in nodes_query: related_computers = task.get_related_computers( node, related_computers, related_objects) # Remove duplicated computers computer_paths = [] computers = [] for computer in related_computers: full_path = computer['path'] + '.' + computer['name'] if not full_path in computer_paths: computer_paths.append(full_path) computers.append(computer) if len(computers) == 0: row.append('--') rows.append(row) else: for computer in computers: computer_row = list(row) computer_row.append(treatment_string_to_pdf( computer, 'name', 15)) # No path in PDF because it's too long rows.append(computer_row) else: for item in query: row = [] item['complete_path'] = get_complete_path(request.db, item['path']) row.append(treatment_string_to_csv(item, 'complete_path')) row.append(treatment_string_to_csv(item, 'name') \ if file_ext == 'csv' else get_html_node_link(item)) row.append(treatment_string_to_csv(item, 'manufacturer')) row.append(treatment_string_to_csv(item, 'model')) row.append(treatment_string_to_csv(item, 'serial')) row.append(treatment_string_to_csv(item, 'registry')) # Get all nodes related with this printer nodes_query = request.db.nodes.find( {property_name: str(item['_id'])}) related_computers = [] related_objects = [] for node in nodes_query: related_computers = task.get_related_computers( node, related_computers, related_objects) # Remove duplicated computers computer_paths = [] computers = [] for computer in related_computers: full_path = computer['path'] + '.' + computer['name'] if not full_path in computer_paths: computer_paths.append(full_path) computers.append(computer) if len(computers) == 0: row.append('--') rows.append(row) else: for computer in computers: computer_row = list(row) computer_row.append(treatment_string_to_csv( computer, 'name') \ if file_ext == 'csv' \ else get_html_node_link(computer)) computer['complete_path'] = get_complete_path( request.db, item['path']) rows.append(computer_row) header = (_(u'Path').encode('utf-8'), _(u'Name').encode('utf-8'), _(u'Manufacturer').encode('utf-8'), _(u'Model').encode('utf-8'), _(u'Serial number').encode('utf-8'), _(u'Registry number').encode('utf-8'), _(u'Computer').encode('utf-8')) # Column widths in percentage if file_ext == 'pdf': widths = (0, 25, 15, 15, 15, 15, 15) else: widths = (0, 20, 10, 10, 10, 10, 20) title = _(u'Printers and related computers report') now = datetime.datetime.now().strftime("%d/%m/%Y %H:%M") # Sort rows rows = sorted(rows, key = lambda i: (i[0].lower(), i[1].lower(), i[6].lower())) return {'headers': header, 'rows': rows, 'default_order': [[ 0, 'asc' ], [ 1, 'asc' ], [ 6, 'asc' ]], 'widths': widths, 'report_title': title, 'page': _(u'Page').encode('utf-8'), 'of': _(u'of').encode('utf-8'), 'report_type': file_ext, 'now': now}
def command(self): # Initialization sanitized = False computers = set() self.api = _get_chef_api(self.settings.get('chef.url'), toChefUsername(self.options.chef_username), self.options.chef_pem, False, self.settings.get('chef.version')) self.auth_user = self.db.adminusers.find_one( {'username': self.options.chef_username}) if self.auth_user is None: logger.error('The administrator user must exist in MongoDB') sys.exit(1) self.db = self.pyramid.db # Get local_admin_users_res (Local Administrators) policy logger.info( 'Getting Local Administrators (local_admin_users_res) policy ...') policy = self.db.policies.find_one({'slug': 'local_admin_users_res'}) schema = policy['schema'] policyId = policy['_id'] logger.info('schema = %s' % str(schema)) logger.info('Id.policy = %s' % str(policyId)) # Searching nodes with the Local Administrators policy # Query Fields of an Embedded Document (Mongo documentation) # Example: # db.nodes.find({"policies.58c8122a0dfd425b0894d5b6":{$exists:true}}) logger.info('Searching nodes with the Local Administrators policy...') field = 'policies.' + str(policyId) filters = {field: {'$exists': True}} nodes = self.db.nodes.find(filters) # Validating data and, where appropiate, fixing for node in nodes: instance = node['policies'][unicode(policyId)] logger.info('Node name = %s, _id = %s' % (node['name'], str(node['_id']))) logger.info('Instance before validate method: %s' % str(instance)) while True: try: validate(instance, schema) break except ValidationError as e: logger.warning('Validation error on instance = %s' % str(e.message)) # Sanitize instance self.sanitize(e, instance) sanitized = True if sanitized: # Setting false sanitized for next iteration sanitized = False logger.info('Sanitized instance: %s' % str(instance)) # Update mongo self.db.nodes.update({'_id': node['_id']}, {'$set': { field: instance }}) # Affected nodes if node['type'] == 'ou': result = list( self.db.nodes.find( { 'path': get_filter_nodes_belonging_ou( node['_id']), 'type': 'computer' }, {'_id': 1})) logger.info('OU computers = %s' % str(result)) elif node['type'] == 'group': result = list( self.db.nodes.find( { '_id': { '$in': node['members'] }, 'type': 'computer' }, {'_id': 1})) logger.info('GROUP computers = %s' % str(result)) elif node['type'] == 'computer': result = [node] logger.info('COMPUTER computers = %s' % str(result)) [computers.add(str(n['_id'])) for n in result] # Removing unused local_admin_remove_list attribute in chef nodes for node_id in ChefNode.list(): node = ChefNode(node_id, self.api) logger.info('Checking node: %s' % (node_id)) attr_dotted = policy['path'] + '.local_admin_remove_list' logger.info('Atttribute dotted path: %s' % (attr_dotted)) if node.attributes.has_dotted(attr_dotted): logger.info("Remove 'local_admin_remove_list' attribute!") try: logger.info( "node.attributes = %s" % str(node.attributes['gecos_ws_mgmt']['misc_mgmt'] ['local_admin_users_res'].to_dict())) delete_dotted(node.attributes, attr_dotted) node.save() except: logger.warn( "Problem deleting local_admin_remove_list value from node: %s" % (node_id)) logger.warn( "You may be trying to delete a default attribute instead normal attribute: %s" % (node_id)) for computer in computers: logger.info('computer = %s' % str(computer)) computer = self.db.nodes.find_one({'_id': ObjectId(computer)}) apply_policies_to_computer(self.db.nodes, computer, self.auth_user, api=self.api, initialize=False, use_celery=False) logger.info('Finished.')
def statistics(context, request): object_counters = [] policy_counters = [] ous = {} ous_visibles = [] settings = get_current_registry().settings policyname = "name_{}".format(settings['pyramid.default_locale_name']) is_superuser = request.user.get('is_superuser', False) ou_id = request.GET.get('ou_id', None) logger.debug("admins.py ::: statistics - ou_id = {}".format(ou_id)) if is_superuser: ous_visibles = request.db.nodes.find({"type": "ou"}, { "_id": 1, "name": 1, "path": 1 }) else: # Get managed ous for admin oids = request.user.get('ou_managed', []) + request.user.get( 'ou_readonly', []) ous_visibles = request.db.nodes.find( {"_id": { "$in": list(map(ObjectId, oids)) }}, { "_id": 1, "name": 1, "path": 1 }) for ou in ous_visibles: path = ou['path'] + ',' + str(ou['_id']) ous.update({str(ou['_id']): get_complete_path(request.db, path)}) sorted_ous = collections.OrderedDict( sorted(list(ous.items()), key=lambda kv: len(kv[1]))) logger.debug( "admins.py ::: statistics - sorted_ous = {}".format(sorted_ous)) # Defaults if not ou_id and list(sorted_ous.items()) is not None and len( list(sorted_ous.items())) > 0: ou_id = str(list(sorted_ous.items())[0][0]) logger.debug("admins.py ::: statistics - ou_id = {}".format(ou_id)) # Objects object_counters = request.db.nodes.aggregate([{ "$match": { "path": get_filter_nodes_belonging_ou(ou_id) } }, { "$group": { "_id": "$type", "count": { "$sum": 1 } } }], cursor={}) logger.debug("admins.py ::: statistics - object_counters = {}".format( object_counters)) # Policies for pol in request.db.policies.find().sort("name"): c = request.db.nodes.count_documents({ "$or": [{ "path": get_filter_nodes_belonging_ou(ou_id) }, { "_id": ObjectId(ou_id) }], "policies." + str(pol['_id']): { '$exists': True } }) try: policy_counters.append([pol[policyname], c]) except KeyError: policy_counters.append([pol['name'], c]) logger.debug("admins.py ::: statistics - policy_counters = {}".format( policy_counters)) return { 'policy_counters': policy_counters, 'object_counters': object_counters, 'ou_managed': sorted_ous, 'ou_selected': ou_id, 'is_superuser': is_superuser }
def report_no_user_computers(context, request, file_ext): ''' Generate a report with all the no-user computers that belongs to a OU. If the administrator is a superadmin the generated report will contain all the users in the database. Args: ou_id (string) : ID of the OU. Returns: headers (list) : The headers of the table to export rows (list) : Rows with the report data widths (list) : The witdhs of the columns of the table to export page : Translation of the word "page" to the current language of : Translation of the word "of" to the current language report_type : Type of report (html, csv or pdf) ''' # Check current user permissions ou_id = check_visibility_of_ou(request) if ou_id is None: raise HTTPBadRequest() task = ChefTask() related_computers = [] related_objects = [] filters = ({'type': 'user','path': get_filter_nodes_belonging_ou(ou_id)}) logger.info("report_no-user_computers: filters = {}".format(filters)) users = request.db.nodes.find(filters) for user in users: related_computers = task.get_related_computers_of_user(user, related_computers, related_objects) references = [c['_id'] for c in related_computers] logger.info("report_no-user_computers: references = {}".format(references)) filters2 = ({'type': 'computer','path': get_filter_nodes_belonging_ou(ou_id)}) filters2.update({'_id': {'$nin': [c['_id'] for c in related_computers]}}) logger.info("report_no-user_computers: filters2 = {}".format(filters2)) computers = request.db.nodes.find(filters2) rows = [] if file_ext == 'pdf': rows = [(item['name'], treatment_string_to_pdf(item, 'family', 15), treatment_string_to_pdf(item, 'registry', 15), treatment_string_to_pdf(item, 'serial', 20), item['node_chef_id'], item['_id']) for item in computers] else: rows = [(treatment_string_to_csv(item, 'name') if file_ext == 'csv' else get_html_node_link(item), treatment_string_to_csv(item, 'family'), treatment_string_to_csv(item, 'registry'), treatment_string_to_csv(item, 'serial'), treatment_string_to_csv(item, 'node_chef_id'), item['_id']) for item in computers] header = (_(u'Name').encode('utf-8'), _(u'Type').encode('utf-8'), _(u'Registry number').encode('utf-8'), _(u'Serial number').encode('utf-8'), _(u'Node chef id').encode('utf-8'), _(u'Id').encode('utf-8')) # Column widths in percentage widths = (25, 10, 15, 15, 20, 15) title = _(u'No-user computers') now = datetime.datetime.now().strftime("%d/%m/%Y %H:%M") return {'headers': header, 'rows': rows, 'widths': widths, 'report_title': title, 'page': _(u'Page').encode('utf-8'), 'of': _(u'of').encode('utf-8'), 'report_type': file_ext, 'now': now}