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
Esempio n. 2
0
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()
Esempio n. 3
0
 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': {}}})
Esempio n. 4
0
    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
Esempio n. 5
0
 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': {}
                 }})
Esempio n. 6
0
    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
Esempio n. 7
0
    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
Esempio n. 8
0
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()
Esempio n. 9
0
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()
Esempio n. 10
0
    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
                                     }})
Esempio n. 11
0
    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
        }
Esempio n. 12
0
    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}