def post_save(self, obj, old_obj=None): """ Check if path has changed to refresh children nodes """ if (self.request.method == 'PUT' and old_obj and obj.get('path') != old_obj.get('path')): # The ou path has changed new_path = ','.join([obj.get('path'), str(old_obj[self.key])]) old_path = ','.join([old_obj.get('path'), str(old_obj[self.key])]) children = self.collection.find({ 'path': { '$regex': '^{0}'.format(old_path) } }) for child in children: old_child_path = child['path'] new_child_path = str(old_child_path).replace(old_path, new_path) self.collection.update({ self.key: child[self.key] }, { '$set': { 'path': new_child_path } }) elif self.request.method == 'POST' and is_domain(obj): obj['master'] = MASTER_DEFAULT obj['master_policies'] = {} return obj
def can_access_to_this_path(request, collection_nodes, oid_or_obj, ou_type='ou_managed'): obj = None request = request ou_managed_ids = request.user.get(ou_type, []) if not request.user.get('is_superuser'): if not ou_managed_ids: logger.error("The user %s has no %s data!" % (request.user.get('username'), ou_type)) raise HTTPForbidden() if isinstance(oid_or_obj, dict): obj = oid_or_obj else: obj = collection_nodes.find_one({'_id': ObjectId(oid_or_obj)}) if obj is None: logger.error("Unknown object! {0}".format(oid_or_obj)) raise HTTPForbidden() path = obj['path'] if (path == 'root' or len(path.split(',')) == 2) and request.method == 'DELETE': logger.warn( "Only the superadministrators can delete a domain! (user: %s)" % (request.user.get('username'))) raise HTTPForbidden() if '_id' in obj: path = '%s,%s' % (path, obj['_id']) if not is_path_right(request, path, ou_type): if not is_domain(obj) or not request.method == 'GET': raise HTTPForbidden()
def command(self): db = self.pyramid.db ous = db.nodes.find({'type': 'ou'}) for ou in ous: if is_domain(ou): db.nodes.update({'_id': ou['_id']}, {'$set': {'master': ou['source'], 'master_policies': {}}})
def _get_domain(self, ouSchema, xmlDomain, is_ad_master, report): # Get already exists root domain domain_id = self.request.POST.get('domainId', None) system_type = self.request.POST.get('systemType', 'ad') if not domain_id: raise HTTPBadRequest('GECOSCC needs a domainId param') filter_domain = { '_id': ObjectId(domain_id), 'type': ouSchema['mongoType'] } domain = self.collection.find_one(filter_domain) if not domain: raise HTTPBadRequest('domain does not exists') can_access_to_this_path(self.request, self.collection, domain, ou_type='ou_availables') if not is_domain(domain): raise HTTPBadRequest('domain param is not a domain id') update_domain = { 'extra': xmlDomain.attributes['DistinguishedName'].value, 'source': u'{0}:{1}:{2}'.format( system_type, xmlDomain.attributes['DistinguishedName'].value, xmlDomain.attributes['ObjectGUID'].value), 'adObjectGUID': xmlDomain.attributes['ObjectGUID'].value, 'adDistinguishedName': xmlDomain.attributes['DistinguishedName'].value, 'master_policies': {} } has_updated = False report['total'] += 1 if is_ad_master: update_domain['master'] = u'{0}:{1}:{2}'.format( system_type, xmlDomain.attributes['DistinguishedName'].value, xmlDomain.attributes['ObjectGUID'].value) has_updated = True elif not is_ad_master: if 'adObjectGUID' not in domain: update_domain['master'] = MASTER_DEFAULT has_updated = True elif domain['master'] != MASTER_DEFAULT: update_domain['master'] = MASTER_DEFAULT has_updated = True if has_updated: self.collection.update(filter_domain, {'$set': update_domain}) report['updated'] += 1 domain = self.collection.find_one(filter_domain) return domain
def command(self): db = self.pyramid.db ous = db.nodes.find({'type': 'ou'}) for ou in ous: if is_domain(ou): db.nodes.update( {'_id': ou['_id']}, {'$set': { 'master': ou['source'], 'master_policies': {} }})
def _get_domain(self, ouSchema, xmlDomain, is_ad_master, report): # Get already exists root domain domain_id = self.request.POST.get('domainId', None) system_type = self.request.POST.get('systemType', 'ad') if not domain_id: raise HTTPBadRequest('GECOSCC needs a domainId param') filter_domain = { '_id': ObjectId(domain_id), 'type': ouSchema['mongoType'] } domain = self.collection.find_one(filter_domain) if not domain: raise HTTPBadRequest('domain does not exists') can_access_to_this_path(self.request, self.collection, domain, ou_type='ou_availables') if not is_domain(domain): raise HTTPBadRequest('domain param is not a domain id') update_domain = { 'extra': xmlDomain.attributes['DistinguishedName'].value, 'source': u'{0}:{1}:{2}'.format(system_type, xmlDomain.attributes['DistinguishedName'].value, xmlDomain.attributes['ObjectGUID'].value), 'adObjectGUID': xmlDomain.attributes['ObjectGUID'].value, 'adDistinguishedName': xmlDomain.attributes['DistinguishedName'].value, 'master_policies': {} } has_updated = False report['total'] += 1 if is_ad_master: update_domain['master'] = u'{0}:{1}:{2}'.format(system_type, xmlDomain.attributes['DistinguishedName'].value, xmlDomain.attributes['ObjectGUID'].value) has_updated = True elif not is_ad_master: if 'adObjectGUID' not in domain: update_domain['master'] = MASTER_DEFAULT has_updated = True elif domain['master'] != MASTER_DEFAULT: update_domain['master'] = MASTER_DEFAULT has_updated = True if has_updated: self.collection.update(filter_domain, {'$set': update_domain}) report['updated'] += 1 domain = self.collection.find_one(filter_domain) return domain
def check_unique_node_name_by_type_at_domain(self, obj): unique = check_unique_node_name_by_type_at_domain( self.request.db.nodes, obj) if not unique: self.request.errors.add('body', 'name', "Name must be unique in domain.") if unique and not is_domain(obj) and not is_root(obj): # Check that the node name is not the same as the domain name domain = get_domain(obj, self.request.db.nodes) if domain['name'].lower() == obj['name'].lower(): self.request.errors.add('body', 'name', "Name already used as domain name.") return False return unique
def can_access_to_this_path(request, collection_nodes, oid_or_obj, ou_type='ou_managed'): obj = None request = request ou_managed_ids = request.user.get(ou_type, []) if not request.user.get('is_superuser') or ou_managed_ids: if isinstance(oid_or_obj, dict): obj = oid_or_obj else: obj = collection_nodes.find_one({'_id': ObjectId(oid_or_obj)}) path = obj['path'] if '_id' in obj: path = '%s,%s' % (path, obj['_id']) if not is_path_right(request, path, ou_type): if not is_domain(obj) or not request.method == 'GET': raise HTTPForbidden()
def check_node(self, node): ''' Check the policies applied to a node ''' logger.info('Checking node: "%s" type:%s path: %s' % (node['name'], node['type'], node['path'])) # Check for name duplicates if not check_unique_node_name_by_type_at_domain(self.db.nodes, node): logger.error('Duplicates found for node: "%s" type:%s path: %s' % (node['name'], node['type'], node['path'])) elif not is_domain(node) and not is_root(node): # Check that the node name is not the same as the domain name domain = get_domain(node, self.db.nodes) if domain['name'].lower() == node['name'].lower(): logger.error( 'The node has the same name as the domain: "%s" type:%s path: %s' % (node['name'], node['type'], node['path'])) if self.options.inheritance: inheritance_node = deepcopy(node) # Check policies if 'policies' in node: to_remove = [] # Check the policies data for policy in node['policies']: logger.debug('Checking policy with ID: %s' % (policy)) if not str(policy) in self.policiesdata: logger.warn( "Can't find %s policy data in the database! (probably deprecated)" % (policy)) to_remove.append(str(policy)) else: policydata = self.policiesdata[str(policy)] nodedata = node['policies'][str(policy)] # Emiters policies have a "name" field in the data # Non emiters policies have a "title" field in the data namefield = 'name' if not (namefield in policydata): namefield = 'title' if not ('name' in policydata): logger.critical( 'Policy with ID: %s doesn\'t have a name nor title!' % (str(policy))) continue logger.info('Checking node: "%s" Checking policy: "%s"' % (node['name'], policydata[namefield])) if 'DEPRECATED' in policydata[namefield]: logger.warning('Using deprecated policy: %s' % (policydata[namefield])) logger.debug('Node policy data: %s' % (json.dumps(node['policies'][str(policy)]))) is_emitter_policy = False emitter_policy_slug = None if "is_emitter_policy" in policydata: is_emitter_policy = policydata["is_emitter_policy"] emitter_policy_slug = policydata["slug"] # Check object self.check_object_property(policydata['schema'], nodedata, None, is_emitter_policy, emitter_policy_slug) if self.options.inheritance: # Check inheritance field trace_inheritance(logger, self.db, 'change', inheritance_node, deepcopy(policydata)) changed = False for policy in to_remove: logger.info("FIXED: Remove %s policy information" % (policy)) del node['policies'][str(policy)] changed = True if changed: self.db.nodes.update({'_id': ObjectId(node['_id'])}, {'$set': { 'policies': node['policies'] }}) else: logger.debug('No policies in this node.') if self.options.inheritance and ( 'inheritance' in inheritance_node) and ( (not 'inheritance' in node) or (inheritance_node['inheritance'] != node['inheritance'])): # Save inheritance field logger.info('FIXED: updating inheritance field!') self.db.nodes.update( {'_id': ObjectId(node['_id'])}, {'$set': { 'inheritance': inheritance_node['inheritance'] }}) # Check referenced nodes if node['type'] == 'user': # Check computers new_id_list = self.check_referenced_nodes(node['computers'], ['computer'], 'computers') difference = set(node['computers']).difference(set(new_id_list)) if len(difference) > 0: logger.info('FIXED: remove %s references' % (difference)) self.db.nodes.update({'_id': ObjectId(node['_id'])}, {'$set': { 'computers': new_id_list }}) # Check user data self.check_user_data(node) # Check memberof new_id_list = self.check_referenced_nodes(node['memberof'], ['group'], 'memberof') difference = set(node['memberof']).difference(set(new_id_list)) if len(difference) > 0: logger.info('FIXED: remove %s references' % (difference)) self.db.nodes.update({'_id': ObjectId(node['_id'])}, {'$set': { 'memberof': new_id_list }}) if node['type'] == 'computer': # Check memberof new_id_list = self.check_referenced_nodes(node['memberof'], ['group'], 'memberof') difference = set(node['memberof']).difference(set(new_id_list)) if len(difference) > 0: logger.info('FIXED: remove %s references' % (difference)) self.db.nodes.update({'_id': ObjectId(node['_id'])}, {'$set': { 'memberof': new_id_list }}) if node['type'] == 'group': # Check memberof new_id_list = self.check_referenced_nodes(node['memberof'], ['group'], 'memberof') difference = set(node['memberof']).difference(set(new_id_list)) if len(difference) > 0: logger.info('FIXED: remove %s references' % (difference)) self.db.nodes.update({'_id': ObjectId(node['_id'])}, {'$set': { 'memberof': new_id_list }}) # Check members new_id_list = self.check_referenced_nodes( node['members'], ['user', 'computer', 'group'], 'members') difference = set(node['members']).difference(set(new_id_list)) if len(difference) > 0: logger.info('FIXED: remove %s references' % (difference)) self.db.nodes.update({'_id': ObjectId(node['_id'])}, {'$set': { 'members': new_id_list }})
def post(self): """ Imports and converts XML GPOs into GECOSCC from self.request """ try: counter = 0 status = '' ok = True # Read SID-GUID data postedfile = self.request.POST['media0'].file xmldata = GzipFile('', 'r', 9, StringIO(postedfile.read())).read() xmlsid_guid = xmltodict.parse(xmldata) GPOConversor.xml_sid_guid = xmlsid_guid # Update domain with master_policies domain_id = self.request.POST.get('domainId', None) if not domain_id: raise HTTPBadRequest('GECOSCC needs a domainId param') filter_domain = { '_id': ObjectId(domain_id), 'type': 'ou' } domain = self.collection.find_one(filter_domain) if not domain: raise HTTPBadRequest('domain does not exists') can_access_to_this_path(self.request, self.collection, domain, ou_type='ou_availables') if not is_domain(domain): raise HTTPBadRequest('domain param is not a domain id') policies_slugs = self.request.POST.getall('masterPolicy[]') for policy_slug in policies_slugs: policy = self.collection_policies.find_one({'slug': policy_slug}) if 'master_policies' not in domain: domain['master_policies'] = {} if policy is not None and policy['_id'] not in domain['master_policies']: domain['master_policies'][str(policy['_id'])] = True self.collection.update(filter_domain, domain) # Read GPOs data postedfile = self.request.POST['media1'].file xmldata = GzipFile('', 'r', 9, StringIO(postedfile.read())).read() xmlgpos = xmltodict.parse(xmldata) # Apply each xmlgpo for xmlgpo in xmlgpos['report']['GPO']: for gpoconversorclass in GPOConversor.__subclasses__(): if not gpoconversorclass(self.request).apply(self._cleanPrefixNamespaces(xmlgpo)): # TODO Report error to somewhere ok = False else: counter += 1 status = 'Policies applied correctly: {0}'.format(counter) except Exception as e: logger.exception(e) status = u'{0}'.format(e) ok = False return { 'status': status, 'ok': ok }
def post(self): """ Imports and converts XML GPOs into GECOSCC from self.request """ try: counter = 0 status = '' ok = True # Read SID-GUID data postedfile = self.request.POST['media0'].file xmldata = GzipFile('', 'r', 9, StringIO(postedfile.read())).read() xmlsid_guid = xmltodict.parse(xmldata) GPOConversor.xml_sid_guid = xmlsid_guid # Update domain with master_policies domain_id = self.request.POST.get('domainId', None) if not domain_id: raise HTTPBadRequest('GECOSCC needs a domainId param') filter_domain = {'_id': ObjectId(domain_id), 'type': 'ou'} domain = self.collection.find_one(filter_domain) if not domain: raise HTTPBadRequest('domain does not exists') can_access_to_this_path(self.request, self.collection, domain, ou_type='ou_availables') if not is_domain(domain): raise HTTPBadRequest('domain param is not a domain id') policies_slugs = self.request.POST.getall('masterPolicy[]') for policy_slug in policies_slugs: policy = self.collection_policies.find_one( {'slug': policy_slug}) if 'master_policies' not in domain: domain['master_policies'] = {} if policy is not None and policy['_id'] not in domain[ 'master_policies']: domain['master_policies'][str(policy['_id'])] = True self.collection.update(filter_domain, domain) # Read GPOs data postedfile = self.request.POST['media1'].file xmldata = GzipFile('', 'r', 9, StringIO(postedfile.read())).read() xmlgpos = xmltodict.parse(xmldata) # Apply each xmlgpo for xmlgpo in xmlgpos['report']['GPO']: for gpoconversorclass in GPOConversor.__subclasses__(): if not gpoconversorclass(self.request).apply( self._cleanPrefixNamespaces(xmlgpo)): # TODO Report error to somewhere ok = False else: counter += 1 status = 'Policies applied correctly: {0}'.format(counter) except Exception as e: logger.exception(e) status = u'{0}'.format(e) ok = False return {'status': status, 'ok': ok}