Example #1
0
    def process_request(self, request):
        headers = request.headers

        try:
            if headers['X-Identity-Status'] is 'Invalid':
                # TODO(graham) fix the return to use non-flask resources
                return flask.Response(status=401)
        except KeyError:
            # If the key is valid, Keystone does not include this header at all
            pass

        if headers.get('X-Service-Catalog'):
            catalog = json.loads(headers.get('X-Service-Catalog'))
        else:
            catalog = None

        roles = headers.get('X-Roles').split(',')

        self.make_context(
            request,
            auth_token=headers.get('X-Auth-Token'),
            user=headers.get('X-User-ID'),
            tenant=headers.get('X-Tenant-ID'),
            roles=roles,
            service_catalog=catalog)
Example #2
0
    def process_request(self, request):
        headers = request.headers

        try:
            if headers['X-Identity-Status'] is 'Invalid':
                # TODO(graham) fix the return to use non-flask resources
                return flask.Response(status=401)
        except KeyError:
            # If the key is valid, Keystone does not include this header at all
            pass

        if headers.get('X-Service-Catalog'):
            catalog = json.loads(headers.get('X-Service-Catalog'))
        else:
            catalog = None

        roles = headers.get('X-Roles').split(',')

        context = DesignateContext(auth_token=headers.get('X-Auth-Token'),
                                   user=headers.get('X-User-ID'),
                                   tenant=headers.get('X-Tenant-ID'),
                                   roles=roles,
                                   service_catalog=catalog)

        # Store the context where oslo-log exepcts to find it.
        local.store.context = context

        # Attach the context to the request environment
        request.environ['context'] = context
Example #3
0
    def post(self, jsonurl, data):
        # convert json data string to dict
        ddict = json.loads(data)
        # check basic parameters
        self.testcase.assertIn('method', ddict)
        meth = ddict['method']
        self.testcase.assertIn(meth, ipamethods)
        self.testcase.assertIn('params', ddict)
        self.testcase.assertIsInstance(ddict['params'], list)
        self.testcase.assertEqual(len(ddict['params']), 2)
        self.testcase.assertIsInstance(ddict['params'][0], list)
        self.testcase.assertIsInstance(ddict['params'][1], dict)
        self.testcase.assertIn('version', ddict['params'][1])
        # check method specific parameters
        if meth.startswith('dnsrecord_'):
            self.testcase.assertEqual(len(ddict['params'][0]), 2)
            # domain params end with a .
            param1 = ddict['params'][0][0]
            self.testcase.assertEqual(param1[-1], ".")
        elif meth.startswith('dnszone_'):
            self.testcase.assertEqual(len(ddict['params'][0]), 1)
            param1 = ddict['params'][0][0]
            self.testcase.assertEqual(param1[-1], ".")

        rc = {}
        if self.needauth:
            self.needauth = False  # reset
            return MockResponse(401, json.dumps(rc))
        if self.error:
            rc['error'] = {'code': self.error}
            self.error = None  # reset
        else:
            rc['error'] = None
        return MockResponse(200, json.dumps(rc))
Example #4
0
    def post(self, jsonurl, data):
        # convert json data string to dict
        ddict = json.loads(data)
        # check basic parameters
        self.testcase.assertIn("method", ddict)
        meth = ddict["method"]
        self.testcase.assertIn(meth, ipamethods)
        self.testcase.assertIn("params", ddict)
        self.testcase.assertIsInstance(ddict["params"], list)
        self.testcase.assertEqual(len(ddict["params"]), 2)
        self.testcase.assertIsInstance(ddict["params"][0], list)
        self.testcase.assertIsInstance(ddict["params"][1], dict)
        self.testcase.assertIn("version", ddict["params"][1])
        # check method specific parameters
        if meth.startswith("dnsrecord_"):
            self.testcase.assertEqual(len(ddict["params"][0]), 2)
            # domain params end with a .
            param1 = ddict["params"][0][0]
            self.testcase.assertEqual(param1[-1], ".")
        elif meth.startswith("dnszone_"):
            self.testcase.assertEqual(len(ddict["params"][0]), 1)
            param1 = ddict["params"][0][0]
            self.testcase.assertEqual(param1[-1], ".")

        rc = {}
        if self.needauth:
            self.needauth = False  # reset
            return MockResponse(401, json.dumps(rc))
        if self.error:
            rc["error"] = {"code": self.error}
            self.error = None  # reset
        else:
            rc["error"] = None
        return MockResponse(200, json.dumps(rc))
Example #5
0
    def process_request(self, request):
        headers = request.headers

        try:
            if headers['X-Identity-Status'] is 'Invalid':
                # TODO(graham) fix the return to use non-flask resources
                return flask.Response(status=401)
        except KeyError:
            # If the key is valid, Keystone does not include this header at all
            pass

        if headers.get('X-Service-Catalog'):
            catalog = json.loads(headers.get('X-Service-Catalog'))
        else:
            catalog = None

        roles = headers.get('X-Roles').split(',')

        context = DesignateContext(auth_token=headers.get('X-Auth-Token'),
                                   user=headers.get('X-User-ID'),
                                   tenant=headers.get('X-Tenant-ID'),
                                   roles=roles,
                                   service_catalog=catalog)

        # Store the context where oslo-log exepcts to find it.
        local.store.context = context

        # Attach the context to the request environment
        request.environ['context'] = context
Example #6
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)
Example #7
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)
Example #8
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'
Example #9
0
    def get(self, path, **kw):
        expected_status_code = kw.pop('status_code', 200)

        resp = self.client.get(path=path)

        LOG.debug('Response Body: %r' % resp.data)

        self.assertEqual(resp.status_code, expected_status_code)

        try:
            resp.json = json.loads(resp.data)
        except ValueError:
            resp.json = None

        return resp
Example #10
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'
Example #11
0
    def get(self, path, **kw):
        expected_status_code = kw.pop('status_code', 200)

        resp = self.client.get(path=path)

        LOG.debug('Response Body: %r' % resp.data)

        self.assertEqual(resp.status_code, expected_status_code)

        try:
            resp.json = json.loads(resp.data)
        except ValueError:
            resp.json = None

        return resp
Example #12
0
    def put(self, path, data, content_type="application/json", **kw):
        expected_status_code = kw.pop("status_code", 200)

        content = json.dumps(data)
        resp = self.client.put(path=path, content_type=content_type, data=content)

        LOG.debug("Response Body: %r" % resp.data)

        self.assertEqual(resp.status_code, expected_status_code)

        try:
            resp.json = json.loads(resp.data)
        except ValueError:
            resp.json = None

        return resp
Example #13
0
    def put(self, path, data, content_type="application/json", **kw):
        expected_status_code = kw.pop('status_code', 200)

        content = json.dumps(data)
        resp = self.client.put(path=path, content_type=content_type,
                               data=content)

        LOG.debug('Response Body: %r' % resp.data)

        self.assertEqual(resp.status_code, expected_status_code)

        try:
            resp.json = json.loads(resp.data)
        except ValueError:
            resp.json = None

        return resp
Example #14
0
 def _call_and_handle_error(self, ipareq):
     if 'version' not in ipareq['params'][1]:
         ipareq['params'][1]['version'] = cfg.CONF[self.name].ipa_version
     need_reauth = False
     while True:
         status_code = 200
         try:
             if need_reauth:
                 self.request.auth.refresh_auth()
             rawresp = self.request.post(self.jsonurl,
                                         data=json.dumps(ipareq))
             status_code = rawresp.status_code
         except IPAAuthError:
             status_code = 401
         if status_code == 401:
             if self.ntries == 0:
                 # persistent inability to auth
                 LOG.error("Error: could not authenticate to IPA - "
                           "please check for correct keytab file")
                 # reset for next time
                 self.ntries = cfg.CONF[self.name].ipa_connect_retries
                 raise IPACommunicationFailure()
             else:
                 LOG.debug("Refresh authentication")
                 need_reauth = True
                 self.ntries -= 1
                 time.sleep(1)
         else:
             # successful - reset
             self.ntries = cfg.CONF[self.name].ipa_connect_retries
             break
     try:
         resp = json.loads(rawresp.text)
     except ValueError:
         # response was not json - some sort of error response
         LOG.debug("Error: unknown error from IPA [%s]" % rawresp.text)
         raise IPAUnknownError("unable to process response from IPA")
     # raise the appropriate exception, if error
     exclass = self._ipa_error_to_exception(resp, ipareq)
     if exclass:
         # could add additional info/message to exception here
         raise exclass()
     return resp
Example #15
0
 def _call_and_handle_error(self, ipareq):
     if 'version' not in ipareq['params'][1]:
         ipareq['params'][1]['version'] = cfg.CONF[self.name].ipa_version
     need_reauth = False
     while True:
         status_code = 200
         try:
             if need_reauth:
                 self.request.auth.refresh_auth()
             rawresp = self.request.post(self.jsonurl,
                                         data=json.dumps(ipareq))
             status_code = rawresp.status_code
         except IPAAuthError:
             status_code = 401
         if status_code == 401:
             if self.ntries == 0:
                 # persistent inability to auth
                 LOG.error(_LE("Error: could not authenticate to IPA - "
                           "please check for correct keytab file"))
                 # reset for next time
                 self.ntries = cfg.CONF[self.name].ipa_connect_retries
                 raise IPACommunicationFailure()
             else:
                 LOG.debug("Refresh authentication")
                 need_reauth = True
                 self.ntries -= 1
                 time.sleep(1)
         else:
             # successful - reset
             self.ntries = cfg.CONF[self.name].ipa_connect_retries
             break
     try:
         resp = json.loads(rawresp.text)
     except ValueError:
         # response was not json - some sort of error response
         LOG.debug("Error: unknown error from IPA [%s]" % rawresp.text)
         raise IPAUnknownError("unable to process response from IPA")
     # raise the appropriate exception, if error
     exclass = self._ipa_error_to_exception(resp, ipareq)
     if exclass:
         # could add additional info/message to exception here
         raise exclass()
     return resp
Example #16
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
Example #17
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
Example #18
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
Example #19
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
Example #20
0
    def process_request(self, request):
        headers = request.headers

        try:
            if headers["X-Identity-Status"] is "Invalid":
                # TODO(graham) fix the return to use non-flask resources
                return flask.Response(status=401)
        except KeyError:
            # If the key is valid, Keystone does not include this header at all
            pass

        if headers.get("X-Service-Catalog"):
            catalog = json.loads(headers.get("X-Service-Catalog"))
        else:
            catalog = None

        roles = headers.get("X-Roles").split(",")

        context = DesignateContext(
            auth_token=headers.get("X-Auth-Token"),
            user=headers.get("X-User-ID"),
            tenant=headers.get("X-Tenant-ID"),
            roles=roles,
            service_catalog=catalog,
        )

        # Store the context where oslo-log exepcts to find it.
        local.store.context = context

        # Attempt to sudo, if requested.
        sudo_tenant_id = headers.get("X-Designate-Sudo-Tenant-ID", None)

        if sudo_tenant_id and (uuidutils.is_uuid_like(sudo_tenant_id) or sudo_tenant_id.isdigit()):
            context.sudo(sudo_tenant_id)

        # Attach the context to the request environment
        request.environ["context"] = context
Example #21
0
    def process_request(self, request):
        headers = request.headers

        try:
            if headers['X-Identity-Status'] is 'Invalid':
                # TODO(graham) fix the return to use non-flask resources
                return flask.Response(status=401)
        except KeyError:
            # If the key is valid, Keystone does not include this header at all
            pass

        if headers.get('X-Service-Catalog'):
            catalog = json.loads(headers.get('X-Service-Catalog'))
        else:
            catalog = None

        roles = headers.get('X-Roles').split(',')

        self.make_context(request,
                          auth_token=headers.get('X-Auth-Token'),
                          user=headers.get('X-User-ID'),
                          tenant=headers.get('X-Tenant-ID'),
                          roles=roles,
                          service_catalog=catalog)
Example #22
0
def _deserialize(data):
    """Deserialization wrapper."""
    LOG.debug(_("Deserializing: %s"), data)
    return jsonutils.loads(data)
Example #23
0
 def _from_json(self, datastring):
     try:
         return jsonutils.loads(datastring)
     except ValueError:
         msg = _("cannot understand JSON")
         raise exception.MalformedRequestBody(reason=msg)
Example #24
0
 def _from_json(self, datastring):
     try:
         return jsonutils.loads(datastring)
     except ValueError:
         msg = _("cannot understand JSON")
         raise exception.MalformedRequestBody(reason=msg)
Example #25
0
def _deserialize(data):
    """
    Deserialization wrapper
    """
    LOG.debug(_("Deserializing: %s"), data)
    return jsonutils.loads(data)