예제 #1
0
    def get_ticket(self, source, target, crypto, key):

        # prepare metadata
        md = {
            'requestor': source,
            'target': target,
            'timestamp': time.time(),
            'nonce': struct.unpack('Q', os.urandom(8))[0]
        }
        metadata = base64.b64encode(jsonutils.dumps(md))

        # sign metadata
        signature = crypto.sign(key, metadata)

        # HTTP request
        reply = self._get_ticket({
            'metadata': metadata,
            'signature': signature
        })

        # verify reply
        signature = crypto.sign(key, (reply['metadata'] + reply['ticket']))
        if signature != reply['signature']:
            raise InvalidEncryptedTicket(md['source'], md['destination'])
        md = jsonutils.loads(base64.b64decode(reply['metadata']))
        if ((md['source'] != source or md['destination'] != target
             or md['expiration'] < time.time())):
            raise InvalidEncryptedTicket(md['source'], md['destination'])

        # return ticket data
        tkt = jsonutils.loads(crypto.decrypt(key, reply['ticket']))

        return tkt, md['expiration']
예제 #2
0
    def get_ticket(self, source, target, crypto, key):

        #prepare metadata
        md = {'requestor': source,
              'target': target,
              'timestamp': time.time(),
              'nonce': struct.unpack('Q', os.urandom(8))[0]}
        metadata = base64.b64encode(jsonutils.dumps(md))

        # sign metadata
        signature = crypto.sign(key, metadata)

        # HTTP request
        reply = self._get_ticket({'metadata': metadata,
                                  'signature': signature})

        # Verify reply
        signature = crypto.sign(key, (reply['metadata'] + reply['ticket']))
        if signature != reply['signature']:
            raise InvalidEncryptedTicket(md['source'], md['destination'])
        md = jsonutils.loads(base64.b64decode(reply['metadata']))
        if (((md['source'] != source) or
             (md['destination'] != target) or
             (md['expiration'] < time.time()))):
            raise InvalidEncryptedTicket(md['source'], md['destination'])

        #return ticket data
        tkt = jsonutils.loads(crypto.decrypt(key, reply['ticket']))

        return tkt, md['expiration']
예제 #3
0
    def test_loads_unicode(self):
        self.assertIsInstance(jsonutils.loads(b'"foo"'), six.text_type)
        self.assertIsInstance(jsonutils.loads(u'"foo"'), six.text_type)

        # 'test' in Ukrainian
        i18n_str_unicode = u'"\u0442\u0435\u0441\u0442"'
        self.assertIsInstance(jsonutils.loads(i18n_str_unicode), six.text_type)

        i18n_str = i18n_str_unicode.encode('utf-8')
        self.assertIsInstance(jsonutils.loads(i18n_str), six.text_type)
예제 #4
0
    def _test_secure_message(self, data, encrypt):
        msg = {'message': 'body'}

        # Use a fresh store for each test
        store = rpc_secmsg.KeyStore()

        send = rpc_secmsg.SecureMessage(data['source'][0], data['source'][1],
                                        self.CONF, data['send_key'],
                                        store, encrypt, enctype=data['cipher'],
                                        hashtype=data['hash'])
        recv = rpc_secmsg.SecureMessage(data['target'][0], data['target'][1],
                                        self.CONF, data['recv_key'],
                                        store, encrypt, enctype=data['cipher'],
                                        hashtype=data['hash'])

        source = '%s.%s' % data['source']
        target = '%s.%s' % data['target']
        # Adds test keys in cache, we do it twice, once for client side use,
        # then for server side use as we run both in the same process
        store.put_ticket(source, target,
                         data['skey'], data['ekey'], data['esek'], 2000000000)

        pkt = send.encode(rpc_common._RPC_ENVELOPE_VERSION,
                          target, jsonutils.dumps(msg))

        out = recv.decode(rpc_common._RPC_ENVELOPE_VERSION,
                          pkt[0], pkt[1], pkt[2])
        rmsg = jsonutils.loads(out[1])

        self.assertEqual(len(msg),
                         len(set(msg.items()) & set(rmsg.items())))
예제 #5
0
    def decode_post_data(self):
        result = {}
        for item in self.post_data.split("&"):
            key, _sep, value = item.partition("=")
            result[key] = jsonutils.loads(urllib.unquote_plus(value))

        return result
예제 #6
0
 def _bands_handler(req, res):
     #NOTE: This only handles JSON responses.
     # You can use content type header to test for XML.
     data = jsonutils.loads(res.body)
     data['FOXNSOX:big_bands'] = 'Pig Bands!'
     res.body = jsonutils.dumps(data)
     return res
예제 #7
0
    def decode_post_data(self, post_data):
        result = {}
        for item in post_data.split('&'):
            key, _sep, value = item.partition('=')
            result[key] = jsonutils.loads(urllib.unquote_plus(value))

        return result
예제 #8
0
 def _goose_handler(req, res):
     #NOTE: This only handles JSON responses.
     # You can use content type header to test for XML.
     data = jsonutils.loads(res.body)
     data['FOXNSOX:googoose'] = req.GET.get('chewing')
     res.body = jsonutils.dumps(data)
     return res
예제 #9
0
    def test_serialize_remote_exception_cell_hop(self):
        # A remote remote (no typo) exception should maintain its type and
        # module, when being re-serialized, so that through any amount of cell
        # hops up, it can pop out with the right type
        expected = {
            'class': 'OpenstackException',
            'module': 'openstack.common.exception',
            'message': exception.OpenstackException.msg_fmt,
        }

        def raise_remote_exception():
            try:
                raise exception.OpenstackException()
            except Exception as e:
                ex_type = type(e)
                message = str(e)
                str_override = lambda self: message
                new_ex_type = type(ex_type.__name__ + "_Remote", (ex_type,),
                                   {'__str__': str_override,
                                    '__unicode__': str_override})
                new_ex_type.__module__ = '%s_Remote' % e.__class__.__module__
                e.__class__ = new_ex_type
                raise

        try:
            raise_remote_exception()
        except Exception:
            failure = rpc_common.serialize_remote_exception(sys.exc_info())

        failure = jsonutils.loads(failure)
        self.assertEqual(expected['class'], failure['class'])
        self.assertEqual(expected['module'], failure['module'])
        self.assertEqual(expected['message'], failure['message'])
예제 #10
0
    def test_serialize_remote_exception_cell_hop(self):
        # A remote remote (no typo) exception should maintain its type and
        # module, when being re-serialized, so that through any amount of cell
        # hops up, it can pop out with the right type
        expected = {
            'class': 'FakeUserDefinedException',
            'module': self.__class__.__module__,
            'message': 'foobar',
        }

        def raise_remote_exception():
            try:
                raise FakeUserDefinedException('foobar')
            except Exception as e:
                ex_type = type(e)
                message = str(e)
                str_override = lambda self: message
                new_ex_type = type(ex_type.__name__ + "_Remote", (ex_type, ), {
                    '__str__': str_override,
                    '__unicode__': str_override
                })
                new_ex_type.__module__ = '%s_Remote' % e.__class__.__module__
                e.__class__ = new_ex_type
                raise

        try:
            raise_remote_exception()
        except Exception:
            failure = rpc_common.serialize_remote_exception(sys.exc_info())

        failure = jsonutils.loads(failure)
        self.assertEqual(expected['class'], failure['class'])
        self.assertEqual(expected['module'], failure['module'])
        self.assertEqual(expected['message'], failure['message'])
예제 #11
0
    def _decode_esek(self, key, source, target, timestamp, esek):
        """This function decrypts the esek buffer passed in and returns a
        KeyStore to be used to check and decrypt the received message.

        :param key: The key to use to decrypt the ticket (esek)
        :param source: The name of the source service
        :param traget: The name of the target service
        :param timestamp: The incoming message timestamp
        :param esek: a base64 encoded encrypted block containing a JSON string
        """
        rkey = None

        try:
            s = self._crypto.decrypt(key, esek)
            j = jsonutils.loads(s)

            rkey = base64.b64decode(j['key'])
            expiration = j['timestamp'] + j['ttl']
            if j['timestamp'] > timestamp or timestamp > expiration:
                raise InvalidExpiredTicket(source, target)

        except Exception:
            raise InvalidEncryptedTicket(source, target)

        info = '%s,%s,%s' % (source, target, str(j['timestamp']))

        sek = self._hkdf.expand(rkey, info, len(key) * 2)

        return self._split_key(sek, len(key))
예제 #12
0
    def decode_post_data(self, post_data):
        result = {}
        for item in post_data.split('&'):
            key, _sep, value = item.partition('=')
            result[key] = jsonutils.loads(urllib.unquote_plus(value))

        return result
예제 #13
0
파일: context.py 프로젝트: uday4444/mr
    def _get_authenticated_context(self, req):

        headers = req.headers

        deprecated_token = headers.get('X-Storage-Token')
        roles_header = headers.get('X-Roles', '') # X-Roles is a csv string
        roles = [r.strip().lower() for r in roles_header.split(',')]

        catalog_header = headers.get('X-Service-Catalog')
        if catalog_header is not None:
            try:
                service_catalog = json.loads(catalog_header)
            except ValueError:
                raise webob.exc.HTTPInternalServerError('Invalid server '
                                                        'catalog json')

        kwargs = {
            'auth_token': headers.get('X-Auth-Token', deprecated_token),
            'user': req.headers.get('X-User-Id'),
            'tenant': req.headers.get('X-Tenant-Id'),
            'is_admin': CONF.admin_role.strip().lower() in roles,
            'service_catalog': service_catalog,
        }

        return context.RequestContext(**kwargs)
예제 #14
0
    def _decode_esek(self, key, source, target, timestamp, esek):
        """This function decrypts the esek buffer passed in and returns a
        KeyStore to be used to check and decrypt the received message.

        :param key: The key to use to decrypt the ticket (esek)
        :param source: The name of the source service
        :param traget: The name of the target service
        :param timestamp: The incoming message timestamp
        :param esek: a base64 encoded encrypted block containing a JSON string
        """
        rkey = None

        try:
            s = self._crypto.decrypt(key, esek)
            j = jsonutils.loads(s)

            rkey = base64.b64decode(j['key'])
            expiration = j['timestamp'] + j['ttl']
            if j['timestamp'] > timestamp or timestamp > expiration:
                raise InvalidExpiredTicket(source, target)

        except Exception:
            raise InvalidEncryptedTicket(source, target)

        info = '%s,%s,%s' % (source, target, str(j['timestamp']))

        sek = self._hkdf.expand(rkey, info, len(key) * 2)

        return self._split_key(sek, len(key))
예제 #15
0
    def load_json(cls, data, default_rule=None):
        """Allow loading of JSON rule data."""

        # Suck in the JSON data and parse the rules
        rules = dict((k, parse_rule(v)) for k, v in
                     jsonutils.loads(data).items())

        return cls(rules, default_rule)
예제 #16
0
    def load_json(cls, data, default_rule=None):
        """Allow loading of JSON rule data."""

        # Suck in the JSON data and parse the rules
        rules = dict((k, parse_rule(v)) for k, v in
                     jsonutils.loads(data).items())

        return cls(rules, default_rule)
예제 #17
0
    def test_get_resources(self):
        app = setup_extensions_app()

        response = app.get("/dummy_resources/1?chewing=newblue")

        response_data = jsonutils.loads(response.body)
        self.assertEqual('newblue', response_data['FOXNSOX:googoose'])
        self.assertEqual("Pig Bands!", response_data['FOXNSOX:big_bands'])
예제 #18
0
    def test_get_resources(self):
        app = setup_extensions_app()

        response = app.get("/dummy_resources/1?chewing=newblue")

        response_data = jsonutils.loads(response.body)
        self.assertEqual('newblue', response_data['FOXNSOX:googoose'])
        self.assertEqual("Pig Bands!", response_data['FOXNSOX:big_bands'])
예제 #19
0
    def __call__(self, model):
        # this part deals with subviews that were already serialized
        cpy = copy.deepcopy(model)
        for key, valstr in model.items():
            if getattr(valstr, '__is_json__', False):
                cpy[key] = json.loads(valstr)

        res = utils.StringWithAttrs(json.dumps(cpy.data))
        res.__is_json__ = True
        return res
예제 #20
0
    def test_resource_extension_for_get_custom_collection_action(self):
        controller = self.ResourceExtensionController()
        collections = {'custom_collection_action': "PUT"}
        res_ext = extensions.ResourceExtension('tweedles', controller,
                                               collection_actions=collections)
        test_app = setup_extensions_app(SimpleExtensionManager(res_ext))

        response = test_app.put("/tweedles/custom_collection_action")
        self.assertEqual(200, response.status_int)
        self.assertEqual(jsonutils.loads(response.body)['collection'], "value")
예제 #21
0
    def __call__(self, model):
        # this part deals with subviews that were already serialized
        cpy = copy.deepcopy(model)
        for key in model.keys():
            if getattr(model[key], '__is_json__', False):
                cpy[key] = json.loads(model[key])

        res = utils.StringWithAttrs(json.dumps(cpy.data, sort_keys=True))
        res.__is_json__ = True
        return res
예제 #22
0
    def test_resource_extension_with_custom_member_action(self):
        controller = self.ResourceExtensionController()
        member = {'custom_member_action': "GET"}
        res_ext = extensions.ResourceExtension('tweedles', controller,
                                               member_actions=member)
        test_app = setup_extensions_app(SimpleExtensionManager(res_ext))

        response = test_app.get("/tweedles/some_id/custom_member_action")
        self.assertEqual(200, response.status_int)
        self.assertEqual(jsonutils.loads(response.body)['member_action'],
                         "value")
예제 #23
0
    def test_resource_extension_for_get_custom_collection_action(self):
        controller = self.ResourceExtensionController()
        collections = {'custom_collection_action': "PUT"}
        res_ext = extensions.ResourceExtension('tweedles',
                                               controller,
                                               collection_actions=collections)
        test_app = setup_extensions_app(SimpleExtensionManager(res_ext))

        response = test_app.put("/tweedles/custom_collection_action")
        self.assertEqual(200, response.status_int)
        self.assertEqual(jsonutils.loads(response.body)['collection'], "value")
예제 #24
0
    def test_resource_extension_with_custom_member_action(self):
        controller = self.ResourceExtensionController()
        member = {'custom_member_action': "GET"}
        res_ext = extensions.ResourceExtension('tweedles',
                                               controller,
                                               member_actions=member)
        test_app = setup_extensions_app(SimpleExtensionManager(res_ext))

        response = test_app.get("/tweedles/some_id/custom_member_action")
        self.assertEqual(200, response.status_int)
        self.assertEqual(
            jsonutils.loads(response.body)['member_action'], "value")
예제 #25
0
    def test_serialize_remote_exception(self):
        expected = {"class": "Exception", "module": "exceptions", "message": "test"}

        try:
            raise_exception()
        except Exception as exc:
            failure = rpc_common.serialize_remote_exception(sys.exc_info())

        failure = jsonutils.loads(failure)
        # assure the traceback was added
        self.assertEqual(expected["class"], failure["class"])
        self.assertEqual(expected["module"], failure["module"])
        self.assertEqual(expected["message"], failure["message"])
예제 #26
0
    def _get_reply(self, url, resp):
        if resp.text:
            try:
                body = jsonutils.loads(resp.text)
                reply = body['reply']
            except (KeyError, TypeError, ValueError):
                msg = "Failed to decode reply: %s" % resp.text
                raise CommunicationError(url, msg)
        else:
            msg = "No reply data was returned."
            raise CommunicationError(url, msg)

        return reply
예제 #27
0
    def _get_reply(self, url, resp):
        if resp.text:
            try:
                body = jsonutils.loads(resp.text)
                reply = body['reply']
            except (KeyError, TypeError, ValueError):
                msg = "Failed to decode reply: %s" % resp.text
                raise CommunicationError(url, msg)
        else:
            msg = "No reply data was returned."
            raise CommunicationError(url, msg)

        return reply
예제 #28
0
    def test_resource_ext_for_nested_resource_custom_collection_action(self):
        controller = self.ResourceExtensionController()
        collections = {'custom_collection_action': "GET"}
        parent = dict(collection_name='beetles', member_name='beetle')
        res_ext = extensions.ResourceExtension('tweedles', controller,
                                               collection_actions=collections,
                                               parent=parent)
        test_app = setup_extensions_app(SimpleExtensionManager(res_ext))

        response = test_app.get("/beetles/beetle_id"
                                "/tweedles/custom_collection_action")

        self.assertEqual(200, response.status_int)
        self.assertEqual(jsonutils.loads(response.body)['collection'], "value")
예제 #29
0
    def _unpack_json_msg(self, msg):
        """Load the JSON data in msg if msg.content_type indicates that it
           is necessary.  Put the loaded data back into msg.content and
           update msg.content_type appropriately.

        A Qpid Message containing a dict will have a content_type of
        'amqp/map', whereas one containing a string that needs to be converted
        back from JSON will have a content_type of JSON_CONTENT_TYPE.

        :param msg: a Qpid Message object
        :returns: None
        """
        if msg.content_type == JSON_CONTENT_TYPE:
            msg.content = jsonutils.loads(msg.content)
            msg.content_type = 'amqp/map'
예제 #30
0
    def test_resource_ext_for_nested_resource_custom_collection_action(self):
        controller = self.ResourceExtensionController()
        collections = {'custom_collection_action': "GET"}
        parent = dict(collection_name='beetles', member_name='beetle')
        res_ext = extensions.ResourceExtension('tweedles',
                                               controller,
                                               collection_actions=collections,
                                               parent=parent)
        test_app = setup_extensions_app(SimpleExtensionManager(res_ext))

        response = test_app.get("/beetles/beetle_id"
                                "/tweedles/custom_collection_action")

        self.assertEqual(200, response.status_int)
        self.assertEqual(jsonutils.loads(response.body)['collection'], "value")
예제 #31
0
    def _unpack_json_msg(self, msg):
        """Load the JSON data in msg if msg.content_type indicates that it
           is necessary.  Put the loaded data back into msg.content and
           update msg.content_type appropriately.

        A Qpid Message containing a dict will have a content_type of
        'amqp/map', whereas one containing a string that needs to be converted
        back from JSON will have a content_type of JSON_CONTENT_TYPE.

        :param msg: a Qpid Message object
        :returns: None
        """
        if msg.content_type == JSON_CONTENT_TYPE:
            msg.content = jsonutils.loads(msg.content)
            msg.content_type = 'amqp/map'
예제 #32
0
    def test_extend_get_resource_response(self):
        def extend_response_data(req, res):
            data = jsonutils.loads(res.body)
            data['FOXNSOX:extended_key'] = req.GET.get('extended_key')
            res.body = jsonutils.dumps(data)
            return res

        app = self._setup_app_with_request_handler(extend_response_data, 'GET')
        response = app.get("/dummy_resources/1?extended_key=extended_data")

        self.assertEqual(200, response.status_int)

        response_data = jsonutils.loads(response.body)
        self.assertEqual('extended_data',
                         response_data['FOXNSOX:extended_key'])
        self.assertEqual('knox', response_data['fort'])
예제 #33
0
    def test_serialize_remote_exception(self):
        expected = {
            'class': 'Exception',
            'module': 'exceptions',
            'message': 'test',
        }

        try:
            raise Exception("test")
        except Exception:
            failure = rpc_common.serialize_remote_exception(sys.exc_info())

        failure = jsonutils.loads(failure)
        self.assertEqual(expected['class'], failure['class'])
        self.assertEqual(expected['module'], failure['module'])
        self.assertEqual(expected['message'], failure['message'])
예제 #34
0
    def test_serialize_remote_custom_exception(self):
        expected = {
            'class': 'FakeUserDefinedException',
            'module': self.__class__.__module__,
            'message': 'test',
        }

        try:
            raise FakeUserDefinedException('test')
        except Exception:
            failure = rpc_common.serialize_remote_exception(sys.exc_info())

        failure = jsonutils.loads(failure)
        self.assertEqual(expected['class'], failure['class'])
        self.assertEqual(expected['module'], failure['module'])
        self.assertEqual(expected['message'], failure['message'])
예제 #35
0
    def test_extend_get_resource_response(self):
        def extend_response_data(req, res):
            data = jsonutils.loads(res.body)
            data['FOXNSOX:extended_key'] = req.GET.get('extended_key')
            res.body = jsonutils.dumps(data)
            return res

        app = self._setup_app_with_request_handler(extend_response_data, 'GET')
        response = app.get("/dummy_resources/1?extended_key=extended_data")

        self.assertEqual(200, response.status_int)

        response_data = jsonutils.loads(response.body)
        self.assertEqual('extended_data',
                         response_data['FOXNSOX:extended_key'])
        self.assertEqual('knox', response_data['fort'])
예제 #36
0
    def test_serialize_remote_exception(self):
        expected = {
            'class': 'Exception',
            'module': 'exceptions',
            'message': 'test',
        }

        try:
            raise_exception()
        except Exception:
            failure = rpc_common.serialize_remote_exception(sys.exc_info())

        failure = jsonutils.loads(failure)
        self.assertEqual(expected['class'], failure['class'])
        self.assertEqual(expected['module'], failure['module'])
        self.assertEqual(expected['message'], failure['message'])
    def test_serialize_remote_custom_exception(self):
        expected = {
            'class': 'FakeUserDefinedException',
            'module': self.__class__.__module__,
            'message': 'test',
        }

        try:
            raise FakeUserDefinedException('test')
        except Exception:
            failure = rpc_common.serialize_remote_exception(sys.exc_info())

        failure = jsonutils.loads(failure)
        self.assertEqual(expected['class'], failure['class'])
        self.assertEqual(expected['module'], failure['module'])
        self.assertEqual(expected['message'], failure['message'])
예제 #38
0
    def test_serialize_remote_exception(self):
        expected = {
            'class': 'Exception',
            'module': 'exceptions',
            'message': 'test',
        }

        try:
            raise_exception()
        except Exception as exc:
            failure = rpc_common.serialize_remote_exception(sys.exc_info())

        failure = jsonutils.loads(failure)
        #assure the traceback was added
        self.assertEqual(expected['class'], failure['class'])
        self.assertEqual(expected['module'], failure['module'])
        self.assertEqual(expected['message'], failure['message'])
예제 #39
0
    def decode(self, version, metadata, message, signature):
        """This is the main decoding function.

        It takes a version, metadata, message and signature strings and
        returns a tuple with a (decrypted) message and metadata or raises
        an exception in case of error.

        :param version: the current envelope version
        :param metadata: a JSON serialized object with metadata for validation
        :param message: a JSON serialized (base64 encoded encrypted) message
        :param signature: a base64 encoded signature
        """
        md = jsonutils.loads(metadata)

        check_args = ('source', 'destination', 'timestamp',
                      'nonce', 'esek', 'encryption')
        for arg in check_args:
            if arg not in md:
                raise InvalidMetadata('Missing metadata "%s"' % arg)

        if md['destination'] != self._name:
            # TODO(simo) handle group keys by checking target
            raise UnknownDestinationName(md['destination'])

        try:
            skey, ekey = self._decode_esek(self._key,
                                           md['source'], md['destination'],
                                           md['timestamp'], md['esek'])
        except InvalidExpiredTicket:
            raise
        except Exception:
            raise InvalidMetadata('Failed to decode ESEK for %s/%s' % (
                                  md['source'], md['destination']))

        sig = self._crypto.sign(skey, version + metadata + message)

        if sig != signature:
            raise InvalidSignature(md['source'], md['destination'])

        if md['encryption'] is True:
            msg = self._crypto.decrypt(ekey, message)
        else:
            msg = message

        return (md, msg)
예제 #40
0
    def decode(self, version, metadata, message, signature):
        """This is the main decoding function.

        It takes a version, metadata, message and signature strings and
        returns a tuple with a (decrypted) message and metadata or raises
        an exception in case of error.

        :param version: the current envelope version
        :param metadata: a JSON serialized object with metadata for validation
        :param message: a JSON serialized (base64 encoded encrypted) message
        :param signature: a base64 encoded signature
        """
        md = jsonutils.loads(metadata)

        check_args = ('source', 'destination', 'timestamp', 'nonce', 'esek',
                      'encryption')
        for arg in check_args:
            if arg not in md:
                raise InvalidMetadata('Missing metadata "%s"' % arg)

        if md['destination'] != self._name:
            # TODO(simo) handle group keys by checking target
            raise UnknownDestinationName(md['destination'])

        try:
            skey, ekey = self._decode_esek(self._key, md['source'],
                                           md['destination'], md['timestamp'],
                                           md['esek'])
        except InvalidExpiredTicket:
            raise
        except Exception:
            raise InvalidMetadata('Failed to decode ESEK for %s/%s' %
                                  (md['source'], md['destination']))

        sig = self._crypto.sign(skey, version + metadata + message)

        if sig != signature:
            raise InvalidSignature(md['source'], md['destination'])

        if md['encryption'] is True:
            msg = self._crypto.decrypt(ekey, message)
        else:
            msg = message

        return (md, msg)
예제 #41
0
    def test_serialize_remote_custom_exception(self):
        def raise_custom_exception():
            raise exception.MalformedRequestBody(reason='test')

        expected = {
            'class': 'MalformedRequestBody',
            'module': 'openstack.common.exception',
            'message': str(exception.MalformedRequestBody(reason='test')),
        }

        try:
            raise_custom_exception()
        except Exception:
            failure = rpc_common.serialize_remote_exception(sys.exc_info())

        failure = jsonutils.loads(failure)
        self.assertEqual(expected['class'], failure['class'])
        self.assertEqual(expected['module'], failure['module'])
        self.assertEqual(expected['message'], failure['message'])
예제 #42
0
def deserialize_remote_exception(conf, data):
    failure = jsonutils.loads(str(data))

    trace = failure.get('tb', [])
    message = failure.get('message', "") + "\n" + "\n".join(trace)
    name = failure.get('class')
    module = failure.get('module')

    # NOTE(ameade): We DO NOT want to allow just any module to be imported, in
    # order to prevent arbitrary code execution.
    if module not in conf.allowed_rpc_exception_modules:
        return RemoteError(name, failure.get('message'), trace)

    try:
        mod = importutils.import_module(module)
        klass = getattr(mod, name)
        if not issubclass(klass, Exception):
            raise TypeError("Can only deserialize Exceptions")

        failure = klass(*failure.get('args', []), **failure.get('kwargs', {}))
    except (AttributeError, TypeError, ImportError):
        return RemoteError(name, failure.get('message'), trace)

    ex_type = type(failure)
    str_override = lambda self: message
    new_ex_type = type(ex_type.__name__ + _REMOTE_POSTFIX, (ex_type, ), {
        '__str__': str_override,
        '__unicode__': str_override
    })
    new_ex_type.__module__ = '%s%s' % (module, _REMOTE_POSTFIX)
    try:
        # NOTE(ameade): Dynamically create a new exception type and swap it in
        # as the new type for the exception. This only works on user defined
        # Exceptions and not core python exceptions. This is important because
        # we cannot necessarily change an exception message so we must override
        # the __str__ method.
        failure.__class__ = new_ex_type
    except TypeError:
        # NOTE(ameade): If a core exception then just add the traceback to the
        # first exception argument.
        failure.args = (message, ) + failure.args[1:]
    return failure
예제 #43
0
def deserialize_msg(msg):
    # NOTE(russellb): Hang on to your hats, this road is about to
    # get a little bumpy.
    #
    # Robustness Principle:
    #    "Be strict in what you send, liberal in what you accept."
    #
    # At this point we have to do a bit of guessing about what it
    # is we just received.  Here is the set of possibilities:
    #
    # 1) We received a dict.  This could be 2 things:
    #
    #   a) Inspect it to see if it looks like a standard message envelope.
    #      If so, great!
    #
    #   b) If it doesn't look like a standard message envelope, it could either
    #      be a notification, or a message from before we added a message
    #      envelope (referred to as version 1.0).
    #      Just return the message as-is.
    #
    # 2) It's any other non-dict type.  Just return it and hope for the best.
    #    This case covers return values from rpc.call() from before message
    #    envelopes were used.  (messages to call a method were always a dict)

    if not isinstance(msg, dict):
        # See #2 above.
        return msg

    base_envelope_keys = (_VERSION_KEY, _MESSAGE_KEY)
    if not all(map(lambda key: key in msg, base_envelope_keys)):
        #  See #1.b above.
        return msg

    # At this point we think we have the message envelope
    # format we were expecting. (#1.a above)

    if not version_is_compatible(_RPC_ENVELOPE_VERSION, msg[_VERSION_KEY]):
        raise UnsupportedRpcEnvelopeVersion(version=msg[_VERSION_KEY])

    raw_msg = jsonutils.loads(msg[_MESSAGE_KEY])

    return raw_msg
예제 #44
0
def deserialize_msg(msg):
    # NOTE(russellb): Hang on to your hats, this road is about to
    # get a little bumpy.
    #
    # Robustness Principle:
    #    "Be strict in what you send, liberal in what you accept."
    #
    # At this point we have to do a bit of guessing about what it
    # is we just received.  Here is the set of possibilities:
    #
    # 1) We received a dict.  This could be 2 things:
    #
    #   a) Inspect it to see if it looks like a standard message envelope.
    #      If so, great!
    #
    #   b) If it doesn't look like a standard message envelope, it could either
    #      be a notification, or a message from before we added a message
    #      envelope (referred to as version 1.0).
    #      Just return the message as-is.
    #
    # 2) It's any other non-dict type.  Just return it and hope for the best.
    #    This case covers return values from rpc.call() from before message
    #    envelopes were used.  (messages to call a method were always a dict)

    if not isinstance(msg, dict):
        # See #2 above.
        return msg

    base_envelope_keys = (_VERSION_KEY, _MESSAGE_KEY)
    if not all(map(lambda key: key in msg, base_envelope_keys)):
        #  See #1.b above.
        return msg

    # At this point we think we have the message envelope
    # format we were expecting. (#1.a above)

    if not version_is_compatible(_RPC_ENVELOPE_VERSION, msg[_VERSION_KEY]):
        raise UnsupportedRpcEnvelopeVersion(version=msg[_VERSION_KEY])

    raw_msg = jsonutils.loads(msg[_MESSAGE_KEY])

    return raw_msg
예제 #45
0
    def test_json_exception(self):
        test_msg = 'This is %s'
        test_data = 'exceptional'
        try:
            raise Exception('This is exceptional')
        except Exception:
            self.log.exception(test_msg, test_data)

        data = jsonutils.loads(self.stream.getvalue())
        self.assertTrue(data)
        self.assertTrue('extra' in data)
        self.assertEqual('test-json', data['name'])

        self.assertEqual(test_msg % test_data, data['message'])
        self.assertEqual(test_msg, data['msg'])
        self.assertEqual([test_data], data['args'])

        self.assertEqual('ERROR', data['levelname'])
        self.assertEqual(logging.ERROR, data['levelno'])
        self.assertTrue(data['traceback'])
예제 #46
0
    def test_json(self):
        test_msg = 'This is a %(test)s line'
        test_data = {'test': 'log'}
        self.log.debug(test_msg, test_data)

        data = jsonutils.loads(self.stream.getvalue())
        self.assertTrue(data)
        self.assertTrue('extra' in data)
        self.assertEqual('test-json', data['name'])

        self.assertEqual(test_msg % test_data, data['message'])
        self.assertEqual(test_msg, data['msg'])
        self.assertEqual(test_data, data['args'])

        self.assertEqual('test_log.py', data['filename'])
        self.assertEqual('test_json', data['funcname'])

        self.assertEqual('DEBUG', data['levelname'])
        self.assertEqual(logging.DEBUG, data['levelno'])
        self.assertFalse(data['traceback'])
예제 #47
0
    def test_serialize_remote_custom_exception(self):
        def raise_custom_exception():
            raise exception.OpenstackException()

        expected = {
            "class": "OpenstackException",
            "module": "openstack.common.exception",
            "message": exception.OpenstackException.message,
        }

        try:
            raise_custom_exception()
        except Exception as exc:
            failure = rpc_common.serialize_remote_exception(sys.exc_info())

        failure = jsonutils.loads(failure)
        # assure the traceback was added
        self.assertEqual(expected["class"], failure["class"])
        self.assertEqual(expected["module"], failure["module"])
        self.assertEqual(expected["message"], failure["message"])
예제 #48
0
    def test_serialize_remote_custom_exception(self):
        def raise_custom_exception():
            raise exception.OpenstackException()

        expected = {
            'class': 'OpenstackException',
            'module': 'openstack.common.exception',
            'message': exception.OpenstackException.message,
        }

        try:
            raise_custom_exception()
        except Exception as exc:
            failure = rpc_common.serialize_remote_exception(sys.exc_info())

        failure = jsonutils.loads(failure)
        #assure the traceback was added
        self.assertEqual(expected['class'], failure['class'])
        self.assertEqual(expected['module'], failure['module'])
        self.assertEqual(expected['message'], failure['message'])
예제 #49
0
    def test_json(self):
        test_msg = "This is a %(test)s line"
        test_data = {"test": "log"}
        self.log.debug(test_msg, test_data)

        data = jsonutils.loads(self.stream.getvalue())
        self.assertTrue(data)
        self.assertTrue("extra" in data)
        self.assertEqual("test-json", data["name"])

        self.assertEqual(test_msg % test_data, data["message"])
        self.assertEqual(test_msg, data["msg"])
        self.assertEqual(test_data, data["args"])

        self.assertEqual("test_log.py", data["filename"])
        self.assertEqual("test_json", data["funcname"])

        self.assertEqual("DEBUG", data["levelname"])
        self.assertEqual(logging.DEBUG, data["levelno"])
        self.assertFalse(data["traceback"])
예제 #50
0
    def test_serialize_remote_custom_exception(self):
        def raise_custom_exception():
            raise exception.OpenstackException()

        expected = {
            'class': 'OpenstackException',
            'module': 'openstack.common.exception',
            'message': exception.OpenstackException.message,
        }

        try:
            raise_custom_exception()
        except Exception as exc:
            failure = rpc_common.serialize_remote_exception(sys.exc_info())

        failure = jsonutils.loads(failure)
        #assure the traceback was added
        self.assertEqual(expected['class'], failure['class'])
        self.assertEqual(expected['module'], failure['module'])
        self.assertEqual(expected['message'], failure['message'])
예제 #51
0
    def test_json(self):
        test_msg = 'This is a %(test)s line'
        test_data = {'test': 'log'}
        self.log.debug(test_msg, test_data)

        data = jsonutils.loads(self.stream.getvalue())
        self.assertTrue(data)
        self.assertTrue('extra' in data)
        self.assertEqual('test-json', data['name'])

        self.assertEqual(test_msg % test_data, data['message'])
        self.assertEqual(test_msg, data['msg'])
        self.assertEqual(test_data, data['args'])

        self.assertEqual('test_log.py', data['filename'])
        self.assertEqual('test_json', data['funcname'])

        self.assertEqual('DEBUG', data['levelname'])
        self.assertEqual(logging.DEBUG, data['levelno'])
        self.assertFalse(data['traceback'])
예제 #52
0
    def test_json_exception(self):
        test_msg = "This is %s"
        test_data = "exceptional"
        try:
            raise Exception("This is exceptional")
        except Exception:
            self.log.exception(test_msg, test_data)

        data = jsonutils.loads(self.stream.getvalue())
        self.assertTrue(data)
        self.assertTrue("extra" in data)
        self.assertEqual("test-json", data["name"])

        self.assertEqual(test_msg % test_data, data["message"])
        self.assertEqual(test_msg, data["msg"])
        self.assertEqual([test_data], data["args"])

        self.assertEqual("ERROR", data["levelname"])
        self.assertEqual(logging.ERROR, data["levelno"])
        self.assertTrue(data["traceback"])
예제 #53
0
    def test_json_exception(self):
        test_msg = 'This is %s'
        test_data = 'exceptional'
        try:
            raise Exception('This is exceptional')
        except Exception:
            self.log.exception(test_msg, test_data)

        data = jsonutils.loads(self.stream.getvalue())
        self.assertTrue(data)
        self.assertTrue('extra' in data)
        self.assertEqual('test-json', data['name'])

        self.assertEqual(test_msg % test_data, data['message'])
        self.assertEqual(test_msg, data['msg'])
        self.assertEqual([test_data], data['args'])

        self.assertEqual('ERROR', data['levelname'])
        self.assertEqual(logging.ERROR, data['levelno'])
        self.assertTrue(data['traceback'])
예제 #54
0
def deserialize_remote_exception(conf, data):
    failure = jsonutils.loads(str(data))

    trace = failure.get('tb', [])
    message = failure.get('message', "") + "\n" + "\n".join(trace)
    name = failure.get('class')
    module = failure.get('module')

    # NOTE(ameade): We DO NOT want to allow just any module to be imported, in
    # order to prevent arbitrary code execution.
    if module not in conf.allowed_rpc_exception_modules:
        return RemoteError(name, failure.get('message'), trace)

    try:
        mod = importutils.import_module(module)
        klass = getattr(mod, name)
        if not issubclass(klass, Exception):
            raise TypeError("Can only deserialize Exceptions")

        failure = klass(*failure.get('args', []), **failure.get('kwargs', {}))
    except (AttributeError, TypeError, ImportError):
        return RemoteError(name, failure.get('message'), trace)

    ex_type = type(failure)
    str_override = lambda self: message
    new_ex_type = type(ex_type.__name__ + _REMOTE_POSTFIX, (ex_type,),
                       {'__str__': str_override, '__unicode__': str_override})
    new_ex_type.__module__ = '%s%s' % (module, _REMOTE_POSTFIX)
    try:
        # NOTE(ameade): Dynamically create a new exception type and swap it in
        # as the new type for the exception. This only works on user defined
        # Exceptions and not core python exceptions. This is important because
        # we cannot necessarily change an exception message so we must override
        # the __str__ method.
        failure.__class__ = new_ex_type
    except TypeError:
        # NOTE(ameade): If a core exception then just add the traceback to the
        # first exception argument.
        failure.args = (message,) + failure.args[1:]
    return failure
예제 #55
0
    def _test_secure_message(self, data, encrypt):
        msg = {'message': 'body'}

        # Use a fresh store for each test
        store = rpc_secmsg.KeyStore()

        send = rpc_secmsg.SecureMessage(data['source'][0],
                                        data['source'][1],
                                        self.CONF,
                                        data['send_key'],
                                        store,
                                        encrypt,
                                        enctype=data['cipher'],
                                        hashtype=data['hash'])
        recv = rpc_secmsg.SecureMessage(data['target'][0],
                                        data['target'][1],
                                        self.CONF,
                                        data['recv_key'],
                                        store,
                                        encrypt,
                                        enctype=data['cipher'],
                                        hashtype=data['hash'])

        source = '%s.%s' % data['source']
        target = '%s.%s' % data['target']
        # Adds test keys in cache, we do it twice, once for client side use,
        # then for server side use as we run both in the same process
        store.put_ticket(source, target, data['skey'], data['ekey'],
                         data['esek'], 2000000000)

        pkt = send.encode(rpc_common._RPC_ENVELOPE_VERSION, target,
                          jsonutils.dumps(msg))

        out = recv.decode(rpc_common._RPC_ENVELOPE_VERSION, pkt[0], pkt[1],
                          pkt[2])
        rmsg = jsonutils.loads(out[1])

        self.assertEqual(len(msg), len(set(msg.items()) & set(rmsg.items())))
예제 #56
0
    def host_passes(self, host_state, filter_properties):
        """Return a list of hosts that can fulfill the requirements
        specified in the query.
        """
        # TODO(zhiteng) Add description for filter_properties structure
        # and scheduler_hints.
        try:
            query = filter_properties['scheduler_hints']['query']
        except KeyError:
            query = None
        if not query:
            return True

        # NOTE(comstud): Not checking capabilities or service for
        # enabled/disabled so that a provided json filter can decide

        result = self._process_filter(jsonutils.loads(query), host_state)
        if isinstance(result, list):
            # If any succeeded, include the host
            result = any(result)
        if result:
            # Filter it out.
            return True
        return False
예제 #57
0
 def _update_handler(req, res):
     data = jsonutils.loads(res.body)
     data['uneditable'] = jsonutils.loads(req.body)['uneditable']
     res.body = jsonutils.dumps(data)
     return res
예제 #58
0
 def extend_response_data(req, res):
     data = jsonutils.loads(res.body)
     data['FOXNSOX:extended_key'] = req.GET.get('extended_key')
     res.body = jsonutils.dumps(data)
     return res
예제 #59
0
 def _from_json(self, datastring):
     try:
         return jsonutils.loads(datastring)
     except ValueError:
         msg = _("cannot understand JSON")
         raise exception.MalformedRequestBody(reason=msg)