Example #1
0
    def collection_post(self):
        obj = self.request.validated

        if issubclass(self.schema_detail, Node):
            can_access_to_this_path(self.request, self.collection, obj)
            is_gecos_master_or_403(self.request, self.collection, obj, self.schema_detail)
            master_policy_no_updated_or_403(self.request, self.collection, obj)

        if not self.integrity_validation(obj):
            if len(self.request.errors) < 1:
                self.request.errors.add('body', 'object', 'Integrity error')
            return

        # Remove '_id' for security reasons
        if self.key in obj:
            del obj[self.key]

        obj = self.pre_save(obj)
        if obj is None:
            return

        try:
            obj_id = self.collection.insert(obj)
        except DuplicateKeyError, e:
            raise HTTPBadRequest('The Object already exists: '
                                 '{0}'.format(e.message))
Example #2
0
    def refresh_policies(self):
        obj = self.request.validated
        oid = self.request.matchdict['oid']

        if oid != str(obj[self.key]):
            raise HTTPBadRequest('The object id is not the same that the id in'
                                 ' the url')

        if issubclass(self.schema_detail, Node):
            can_access_to_this_path(self.request, self.collection, oid)
            is_gecos_master_or_403(self.request, self.collection, obj,
                                   self.schema_detail)
            master_policy_no_updated_or_403(self.request, self.collection, obj)

        obj_filter = self.get_oid_filter(oid)
        obj_filter.update(self.mongo_filter)

        real_obj = self.collection.find_one(obj_filter)
        if not real_obj:
            raise HTTPNotFound()

        self.notify_refresh_policies(real_obj)

        obj = self.parse_item(real_obj)

        return obj
Example #3
0
    def collection_post(self):
        obj = self.request.validated

        if issubclass(self.schema_detail, Node):
            can_access_to_this_path(self.request, self.collection, obj)
            is_gecos_master_or_403(self.request, self.collection, obj,
                                   self.schema_detail)
            master_policy_no_updated_or_403(self.request, self.collection, obj)

        if not self.integrity_validation(obj):
            if len(self.request.errors) < 1:
                self.request.errors.add('body', 'object', 'Integrity error')
            return

        # Remove '_id' for security reasons
        if self.key in obj:
            del obj[self.key]

        obj = self.pre_save(obj)
        if obj is None:
            return

        try:
            obj_id = self.collection.insert_one(obj).inserted_id
        except DuplicateKeyError as e:
            raise HTTPBadRequest('The Object already exists: '
                                 '{0}'.format(e.message))

        obj = self.post_save(obj)

        obj.update({self.key: obj_id})
        self.notify_created(obj)
        return self.parse_item(obj)
Example #4
0
    def refresh_policies(self):
        obj = self.request.validated
        oid = self.request.matchdict['oid']

        if oid != str(obj[self.key]):
            raise HTTPBadRequest('The object id is not the same that the id in'
                                 ' the url')

        if issubclass(self.schema_detail, Node):
            can_access_to_this_path(self.request, self.collection, obj)
            is_gecos_master_or_403(self.request, self.collection, obj, self.schema_detail)
            master_policy_no_updated_or_403(self.request, self.collection, obj)

        obj_filter = self.get_oid_filter(oid)
        obj_filter.update(self.mongo_filter)

        real_obj = self.collection.find_one(obj_filter)
        if not real_obj:
            raise HTTPNotFound()
            
        self.notify_refresh_policies(real_obj)
        
        obj = self.parse_item(real_obj)
        
        return obj
Example #5
0
    def put(self):
        obj = self.request.validated
        oid = self.request.matchdict['oid']

        if oid != str(obj[self.key]):
            raise HTTPBadRequest('The object id is not the same that the id in'
                                 ' the url')

        if issubclass(self.schema_detail, Node):
            can_access_to_this_path(self.request, self.collection, oid)
            is_gecos_master_or_403(self.request, self.collection, obj,
                                   self.schema_detail)
            master_policy_no_updated_or_403(self.request, self.collection, obj)

        obj_filter = self.get_oid_filter(oid)
        obj_filter.update(self.mongo_filter)

        real_obj = self.collection.find_one(obj_filter)
        if not real_obj:
            raise HTTPNotFound()
        old_obj = deepcopy(real_obj)

        if not self.integrity_validation(obj, real_obj=real_obj):
            if len(self.request.errors) < 1:
                self.request.errors.add('body', 'object', 'Integrity error')
                logger.error("Integrity error in object: {0}".format(obj))
            else:
                logger.error("Integrity error {0} in object: {1}".format(
                    self.request.errors, obj))

            return

        obj = self.pre_save(obj, old_obj=old_obj)
        if obj is None:
            return

        inheritance_backup = None
        if 'inheritance' in obj:
            # Do not save the inheritance field
            inheritance_backup = obj['inheritance']
            del obj['inheritance']

        real_obj.update(obj)

        try:
            self.collection.replace_one(obj_filter, real_obj)
        except DuplicateKeyError as e:
            raise HTTPBadRequest('Duplicated object {0}'.format(e.message))

        obj = self.post_save(obj, old_obj=old_obj)
        self.notify_changed(obj, old_obj)
        obj = self.parse_item(obj)

        if inheritance_backup is not None:
            obj['inheritance'] = inheritance_backup

        return obj
Example #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
Example #7
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
Example #8
0
    def put(self):
        obj = self.request.validated
        oid = self.request.matchdict['oid']

        if oid != str(obj[self.key]):
            raise HTTPBadRequest('The object id is not the same that the id in'
                                 ' the url')

        if issubclass(self.schema_detail, Node):
            can_access_to_this_path(self.request, self.collection, obj)
            is_gecos_master_or_403(self.request, self.collection, obj, self.schema_detail)
            master_policy_no_updated_or_403(self.request, self.collection, obj)

        obj_filter = self.get_oid_filter(oid)
        obj_filter.update(self.mongo_filter)

        real_obj = self.collection.find_one(obj_filter)
        if not real_obj:
            raise HTTPNotFound()
        old_obj = deepcopy(real_obj)

        if not self.integrity_validation(obj, real_obj=real_obj):
            if len(self.request.errors) < 1:
                self.request.errors.add('body', 'object', 'Integrity error')
            return

        obj = self.pre_save(obj, old_obj=old_obj)
        if obj is None:
            return

        inheritance_backup = None
        if 'inheritance' in obj:
            # Do not save the inheritance field
            inheritance_backup = obj['inheritance']
            del obj['inheritance']
            
        real_obj.update(obj)
        
        try:
            self.collection.update(obj_filter, real_obj, new=True)
        except DuplicateKeyError, e:
            raise HTTPBadRequest('Duplicated object {0}'.format(
                e.message))
Example #9
0
    def get(self):
        oid = self.request.matchdict['oid']
        if issubclass(self.schema_detail, Node):
            try:
                can_access_to_this_path(self.request, self.collection, oid, ou_type='ou_readonly')
            except HTTPForbidden:
                can_access_to_this_path(self.request, self.collection, oid)
        collection_filter = self.get_oid_filter(oid)
        collection_filter.update(self.get_object_filter())
        collection_filter.update(self.mongo_filter)
        node = self.collection.find_one(collection_filter)
        if not node:
            raise HTTPNotFound()
        node = self.parse_item(node)

        if node.get('type', None) in RESOURCES_EMITTERS_TYPES:
            node['is_assigned'] = self.is_assigned(node)
            return node
        return node
Example #10
0
    def get(self):
        oid = self.request.matchdict['oid']
        if issubclass(self.schema_detail, Node):
            try:
                can_access_to_this_path(self.request,
                                        self.collection,
                                        oid,
                                        ou_type='ou_readonly')
            except HTTPForbidden:
                can_access_to_this_path(self.request, self.collection, oid)
        collection_filter = self.get_oid_filter(oid)
        collection_filter.update(self.get_object_filter())
        collection_filter.update(self.mongo_filter)
        node = self.collection.find_one(collection_filter)
        if not node:
            raise HTTPNotFound()
        node = self.parse_item(node)

        if node.get('type', None) in RESOURCES_EMITTERS_TYPES:
            node['is_assigned'] = self.is_assigned(node)
            return node
        return node
Example #11
0
    def delete(self):

        oid = self.request.matchdict['oid']

        if issubclass(self.schema_detail, Node):
            obj = self.collection.find_one({'_id': ObjectId(oid)})
            can_access_to_this_path(self.request, self.collection, obj)
            is_gecos_master_or_403(self.request, self.collection, obj, self.schema_detail)
            master_policy_no_updated_or_403(self.request, self.collection, obj)

        filters = self.get_oid_filter(oid)
        filters.update(self.mongo_filter)

        obj = self.collection.find_one(filters)
        if not obj:
            raise HTTPNotFound()
        old_obj = deepcopy(obj)

        obj = self.pre_save(obj)
        if obj is None:
            return
        obj = self.pre_delete(obj)

        status = self.collection.remove(filters)

        if status['ok']:
            obj = self.post_save(obj, old_obj)
            obj = self.post_delete(obj)

            self.notify_deleted(obj)
            return {
                'status': 'The object was deleted successfully',
                'ok': 1
            }
        else:
            self.request.errors.add(unicode(obj[self.key]), 'db status',
                                    status)
            return
Example #12
0
    def put(self):
        obj = self.request.validated
        oid = self.request.matchdict['oid']

        if oid != str(obj[self.key]):
            raise HTTPBadRequest('The object id is not the same that the id in'
                                 ' the url')

        if issubclass(self.schema_detail, Node):
            can_access_to_this_path(self.request, self.collection, obj)
            is_gecos_master_or_403(self.request, self.collection, obj,
                                   self.schema_detail)
            master_policy_no_updated_or_403(self.request, self.collection, obj)

        obj_filter = self.get_oid_filter(oid)
        obj_filter.update(self.mongo_filter)

        real_obj = self.collection.find_one(obj_filter)
        if not real_obj:
            raise HTTPNotFound()
        old_obj = deepcopy(real_obj)

        if not self.integrity_validation(obj, real_obj=real_obj):
            if len(self.request.errors) < 1:
                self.request.errors.add('body', 'object', 'Integrity error')
            return

        obj = self.pre_save(obj, old_obj=old_obj)
        if obj is None:
            return

        real_obj.update(obj)
        try:
            self.collection.update(obj_filter, real_obj, new=True)
        except DuplicateKeyError, e:
            raise HTTPBadRequest('Duplicated object {0}'.format(e.message))
Example #13
0
    def delete(self):

        oid = self.request.matchdict['oid']

        if issubclass(self.schema_detail, Node):
            obj = self.collection.find_one({'_id': ObjectId(oid)})
            can_access_to_this_path(self.request, self.collection, oid)
            is_gecos_master_or_403(self.request, self.collection, obj,
                                   self.schema_detail)
            master_policy_no_updated_or_403(self.request, self.collection, obj)

        filters = self.get_oid_filter(oid)
        filters.update(self.mongo_filter)

        obj = self.collection.find_one(filters)
        if not obj:
            raise HTTPNotFound()
        old_obj = deepcopy(obj)

        obj = self.pre_save(obj)
        if obj is None:
            return
        obj = self.pre_delete(obj)

        status = self.collection.delete_one(filters).raw_result

        if status['ok']:
            obj = self.post_save(obj, old_obj)
            obj = self.post_delete(obj)

            self.notify_deleted(obj)
            return {'status': 'The object was deleted successfully', 'ok': 1}
        else:
            self.request.errors.add('body', '%s: db status' % (obj[self.key]),
                                    status)
            return
Example #14
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}
Example #15
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
        }
Example #16
0
 def get_oid_filter(self, oid):
     if issubclass(self.schema_detail, Node):
         can_access_to_this_path(self.request, self.collection, oid)
     return {self.key: ObjectId(oid)}
Example #17
0
 def get_oid_filter(self, oid):
     if issubclass(self.schema_detail, Node):
         can_access_to_this_path(self.request, self.collection, oid)
     return {self.key: ObjectId(oid)}
    def post(self):
        logger.debug('/help-channel-client/login START')

        # Default known message
        known_message = 'En un lugar de la Mancha, de cuyo nombre no quiero'\
            ' acordarme, no ha mucho tiempo que vivía un hidalgo de los de'\
            ' lanza en astillero, adarga antigua, rocín flaco y galgo corredor.'

        # Check the parameters
        node_id = self.request.POST.get('node_id')
        if not node_id:
            logger.error('/help-channel-client/login - No node ID')
            return {'ok': False, 'message': 'Please set a node id'}

        username = self.request.POST.get('username')
        if not username:
            logger.error('/help-channel-client/login - No username')
            return {'ok': False, 'message': 'Please set a username'}

        secret = self.request.POST.get('secret')
        if not secret:
            logger.error('/help-channel-client/login - No secret')
            return {'ok': False, 'message': 'Please set a secret'}

        hc_server = self.request.POST.get('hc_server')
        if not hc_server:
            logger.error('/help-channel-client/login - No server')
            return {'ok': False, 'message': 'Please set a Help Channel Server'}

        gcc_username = self.request.POST.get('gcc_username')
        if not gcc_username:
            logger.error('/help-channel-client/login - No admin username')
            return {
                'ok': False,
                'message': 'Please set a GCC administrator username'
            }

        self.request.user = self.request.db.adminusers.find_one(
            {'username': gcc_username})
        if not self.request.user:
            return {
                'ok': False,
                'message': 'The admin user %s does not exists' % gcc_username
            }

        logger.debug('/help-channel-client/login node_id=%s' % (node_id))
        logger.debug('/help-channel-client/login username=%s' % (username))
        logger.debug('/help-channel-client/login secret=%s' % (secret))
        logger.debug('/help-channel-client/login hc_server=%s' % (hc_server))
        logger.debug('/help-channel-client/login gccusername=%s' %
                     (gcc_username))

        gcc_node = self.request.db.nodes.find_one({'node_chef_id': node_id})
        if not gcc_node:
            logger.error('/help-channel-client/login - Node not found')
            return {'ok': False, 'message': 'Node not found in database'}

        can_access_to_this_path(self.request,
                                self.request.db.nodes,
                                gcc_node,
                                ou_type='ou_remote')  # Remote OUs

        gcc_user = self.request.db.nodes.find_one({
            'type': 'user',
            'name': username
        })
        if not gcc_user:
            logger.error('/help-channel-client/login - User not found')
            return {'ok': False, 'message': 'User not found in database'}

        try:
            # Check the secret message
            api = get_chef_api(self.request.registry.settings,
                               self.request.user)
            chef_client = ChefClient(node_id, api)
            if not chef_client.exists:
                logger.error('/help-channel-client/login - Client not found')
                return {'ok': False, 'message': 'This client does not exists'}

            chef_node = ChefNode(node_id, api)
            if not chef_node.exists:
                logger.error(
                    '/help-channel-client/login - Chef node not found')
                return {
                    'ok': False,
                    'message': 'This chef node does not exists'
                }

            client_certificate = chef_client.certificate
            public_key = RSA.importKey(client_certificate)

            decrypted = public_key.encrypt(bytes.fromhex(secret), 0)[0]
            decrypted = decrypted.decode("utf-8")

            known_message_setting = self.request.registry.settings.get(
                'helpchannel.known_message')
            if known_message_setting is not None:
                known_message = known_message_setting

            if decrypted != known_message:
                logger.error('/help-channel-client/login - Bad secret')
                return {'ok': False, 'message': 'Bad secret'}

            # Login successful, generate the token!
            server_address = self.request.registry.settings.get(
                'server_address', 'UNKNOWN')

            if server_address == 'UNKNOWN':
                server_address = os.getenv('HOSTNAME', 'UNKNOWN')

            # - Token generation
            min_char = 8
            max_char = 12
            allchar = string.ascii_letters + string.digits
            token = ''.join(
                choice(allchar) for _ in range(randint(min_char, max_char)))

            self.request.db.helpchannel.insert_one({
                'last_modified':
                datetime.datetime.utcnow(),
                'action':
                'request',
                'computer_node_id':
                node_id,
                'computer_node_path':
                gcc_node['path'],
                'user_node_id':
                str(gcc_user['_id']),
                'user_node_path':
                gcc_user['path'],
                'adminuser_id':
                False,
                'adminuser_ou_managed':
                False,
                'adminuser_is_superuser':
                False,
                'gecos_cc_server':
                server_address,
                'helpchannel_server':
                hc_server,
                'token':
                token
            })

            logger.info('/help-channel-client/login - token: %s' % (token))
            return {'ok': True, 'token': token}

        except (urllib.error.URLError, ChefError, ChefServerError):
            pass

        logger.error('/help-channel-client/login - UNKNOWN')
        return {'ok': False, 'message': 'Unknown error'}