Exemple #1
0
    def update(self, req, id, body):
        """ Updates the server name or password """
        if len(req.body) == 0:
            raise exc.HTTPUnprocessableEntity()

        if not body:
            return wsgi.Fault(exc.HTTPUnprocessableEntity())

        ctxt = req.environ['nova.context']
        update_dict = {}

        if 'name' in body['server']:
            name = body['server']['name']
            self._validate_server_name(name)
            update_dict['display_name'] = name.strip()

        if 'description' in body['server']:
            description = body['server']['description']
            update_dict['display_description'] = description.strip()

        self._parse_update(ctxt, id, body, update_dict)

        try:
            self.compute_api.update(ctxt, id, **update_dict)
        except exception.NotFound:
            return wsgi.Fault(exc.HTTPNotFound())

        return exc.HTTPNoContent()
Exemple #2
0
    def __call__(self, req):
        if not self.has_authentication(req):
            return self.authenticate(req)
        user_id = self.get_user_by_authentication(req)
        if not user_id:
            token = req.headers["X-Auth-Token"]
            msg = _("%(user_id)s could not be found with token '%(token)s'")
            LOG.warn(msg % locals())
            return wsgi.Fault(webob.exc.HTTPUnauthorized())

        # Get all valid projects for the user
        projects = self.auth.get_projects(user_id)
        if not projects:
            return wsgi.Fault(webob.exc.HTTPUnauthorized())

        project_id = ""
        path_parts = req.path.split('/')
        # TODO(wwolf): this v1.1 check will be temporary as
        # keystone should be taking this over at some point
        if len(path_parts) > 1 and path_parts[1] in ('v1.1', 'v2'):
            project_id = path_parts[2]
            # Check that the project for project_id exists, and that user
            # is authorized to use it
            try:
                self.auth.get_project(project_id)
            except exception.ProjectNotFound:
                return wsgi.Fault(webob.exc.HTTPUnauthorized())
            if project_id not in [p.id for p in projects]:
                return wsgi.Fault(webob.exc.HTTPUnauthorized())
        else:
            # As a fallback, set project_id from the headers, which is the v1.0
            # behavior. As a last resort, be forgiving to the user and set
            # project_id based on a valid project of theirs.
            try:
                project_id = req.headers["X-Auth-Project-Id"]
            except KeyError:
                project_id = projects[0].id

        is_admin = self.auth.is_admin(user_id)
        remote_address = getattr(req, 'remote_address', '127.0.0.1')
        if FLAGS.use_forwarded_for:
            remote_address = req.headers.get('X-Forwarded-For', remote_address)
        ctx = context.RequestContext(user_id,
                                     project_id,
                                     is_admin=is_admin,
                                     remote_address=remote_address)
        req.environ['nova.context'] = ctx

        if not is_admin and not self.auth.is_project_member(
                user_id, project_id):
            msg = _("%(user_id)s must be an admin or a "
                    "member of %(project_id)s")
            LOG.warn(msg % locals())
            return wsgi.Fault(webob.exc.HTTPUnauthorized())

        return self.application
Exemple #3
0
    def authenticate(self, req):
        # Unless the request is explicitly made against /<version>/ don't
        # honor it
        path_info = req.path_info
        if len(path_info) > 1:
            msg = _("Authentication requests must be made against a version "
                    "root (e.g. /v2).")
            LOG.warn(msg)
            return wsgi.Fault(webob.exc.HTTPUnauthorized(explanation=msg))

        def _get_auth_header(key):
            """Ensures that the KeyError returned is meaningful."""
            try:
                return req.headers[key]
            except KeyError as ex:
                raise KeyError(key)

        try:
            username = _get_auth_header('X-Auth-User')
            key = _get_auth_header('X-Auth-Key')
        except KeyError as ex:
            msg = _("Could not find %s in request.") % ex
            LOG.warn(msg)
            return wsgi.Fault(webob.exc.HTTPUnauthorized(explanation=msg))

        token, user = self._authorize_user(username, key, req)
        if user and token:
            res = webob.Response()
            res.headers['X-Auth-Token'] = token['token_hash']
            _x_server_url = 'X-Server-Management-Url'
            _server_url = 'server_management_url'
            res.headers[_x_server_url] = token[_server_url]

            if token['storage_url']:
                _x_storage_url = 'X-Storage-Url'
                _storage_url = 'storage_url'
                res.headers[_x_storage_url] = token[_storage_url]

            if token['cdn_management_url']:
                _x_cdn_url = 'X-CDN-Management-Url'
                _cdn_url = 'cdn_management_url'
                res.headers[_x_cdn_url] = token[_cdn_url]

            res.content_type = 'text/plain'
            res.status = '204'
            LOG.debug(_("Successfully authenticated '%s'") % username)
            return res
        else:
            return wsgi.Fault(webob.exc.HTTPUnauthorized())
Exemple #4
0
    def _error(self, inner, req):
        LOG.exception(_LE("Caught error: %s"), unicode(inner))

        safe = getattr(inner, 'safe', False)
        headers = getattr(inner, 'headers', None)
        status = getattr(inner, 'code', 500)
        if status is None:
            status = 500

        msg_dict = dict(url=req.url, status=status)
        LOG.info(_LI("%(url)s returned with HTTP %(status)d"), msg_dict)
        outer = self.status_to_type(status)
        if headers:
            outer.headers = headers
        # NOTE(johannes): We leave the explanation empty here on
        # purpose. It could possibly have sensitive information
        # that should not be returned back to the user. See
        # bugs 868360 and 874472
        # NOTE(eglynn): However, it would be over-conservative and
        # inconsistent with the EC2 API to hide every exception,
        # including those that are safe to expose, see bug 1021373
        if safe:
            user_locale = req.best_match_language()
            inner_msg = translate(inner.message, user_locale)
            outer.explanation = '%s: %s' % (inner.__class__.__name__,
                                            inner_msg)

        notifications.send_api_fault(req.url, status, inner)
        return wsgi.Fault(outer)
Exemple #5
0
    def test_429_fault_json(self):
        # Test fault serialized to JSON via file-extension and/or header.
        requests = [
            webob.Request.blank('/.json'),
            webob.Request.blank('/', headers={"Accept": "application/json"}),
        ]

        for request in requests:
            exc = webob.exc.HTTPTooManyRequests
            # NOTE(aloga): we intentionally pass an integer for the
            # 'Retry-After' header. It should be then converted to a str
            fault = wsgi.Fault(
                exc(explanation='sorry', headers={'Retry-After': 4}))
            response = request.get_response(fault)

            expected = {
                "overLimit": {
                    "message": "sorry",
                    "code": 429,
                    "retryAfter": "4",
                },
            }
            actual = jsonutils.loads(response.body)

            self.assertEqual(response.content_type, "application/json")
            self.assertEqual(expected, actual)
Exemple #6
0
 def __call__(self, req):
     try:
         return req.get_response(self.application)
     except Exception as ex:
         LOG.exception(_("Caught error: %s"), unicode(ex))
         exc = webob.exc.HTTPInternalServerError()
         return wsgi.Fault(exc)
Exemple #7
0
    def test_xml_serializer(self):
        # Ensure that a v1.1 request responds with a v1.1 xmlns.
        request = webob.Request.blank('/v1.1',
                                      headers={"Accept": "application/xml"})

        fault = wsgi.Fault(webob.exc.HTTPBadRequest(explanation='scram'))
        response = request.get_response(fault)

        self.assertTrue(common.XML_NS_V11 in response.body)
        self.assertEqual(response.content_type, "application/xml")
        self.assertEqual(response.status_int, 400)
Exemple #8
0
 def __call__(self, req):
     try:
         return req.get_response(self.application)
     except Exception as ex:
         LOG.exception(_("Caught error: %s"), unicode(ex))
         msg_dict = dict(url=req.url, status=500)
         LOG.info(_("%(url)s returned with HTTP %(status)d") % msg_dict)
         exc = webob.exc.HTTPInternalServerError()
         # NOTE(johannes): We leave the explanation empty here on
         # purpose. It could possibly have sensitive information
         # that should not be returned back to the user. See
         # bugs 868360 and 874472
         return wsgi.Fault(exc)
Exemple #9
0
    def rate_limited_request(self, req, application):
        """Rate limit the request.

        If the request should be rate limited, return a 413 status with a
        Retry-After header giving the time when the request would succeed.
        """
        action_name = self.get_action_name(req)
        if not action_name:
            # Not rate limited
            return application
        delay = self.get_delay(action_name,
                               req.environ['nova.context'].user_id)
        if delay:
            # TODO(gundlach): Get the retry-after format correct.
            exc = webob.exc.HTTPRequestEntityTooLarge(
                explanation=('Too many requests.'),
                headers={'Retry-After': time.time() + delay})
            raise os_wsgi.Fault(exc)
        return application
Exemple #10
0
    def test_400_fault_json(self):
        # Test fault serialized to JSON via file-extension and/or header.
        requests = [
            webob.Request.blank('/.json'),
            webob.Request.blank('/', headers={"Accept": "application/json"}),
        ]

        for request in requests:
            fault = wsgi.Fault(webob.exc.HTTPBadRequest(explanation='scram'))
            response = request.get_response(fault)

            expected = {
                "badRequest": {
                    "message": "scram",
                    "code": 400,
                },
            }
            actual = jsonutils.loads(response.body)

            self.assertEqual(response.content_type, "application/json")
            self.assertEqual(expected, actual)
Exemple #11
0
 def _error(self,
            req,
            class_name,
            explanation,
            headers=None,
            status=500,
            safe=False):
     LOG.exception(_("Caught error: %s"), explanation)
     msg_dict = dict(url=req.url, status=status)
     LOG.info(_("%(url)s returned with HTTP %(status)d") % msg_dict)
     outer = self.status_to_type(status)
     if headers:
         outer.headers = headers
     # NOTE(johannes): We leave the explanation empty here on
     # purpose. It could possibly have sensitive information
     # that should not be returned back to the user. See
     # bugs 868360 and 874472
     # NOTE(eglynn): However, it would be over-conservative and
     # inconsistent with the EC2 API to hide every exception,
     # including those that are safe to expose, see bug 1021373
     if safe:
         outer.explanation = '%s: %s' % (class_name, explanation)
     return wsgi.Fault(outer)
Exemple #12
0
    def test_413_fault_json(self):
        # Test fault serialized to JSON via file-extension and/or header.
        requests = [
            webob.Request.blank('/.json'),
            webob.Request.blank('/', headers={"Accept": "application/json"}),
        ]

        for request in requests:
            exc = webob.exc.HTTPRequestEntityTooLarge
            fault = wsgi.Fault(
                exc(explanation='sorry', headers={'Retry-After': 4}))
            response = request.get_response(fault)

            expected = {
                "overLimit": {
                    "message": "sorry",
                    "code": 413,
                    "retryAfter": 4,
                },
            }
            actual = jsonutils.loads(response.body)

            self.assertEqual(response.content_type, "application/json")
            self.assertEqual(expected, actual)
 def raise_api_fault(req):
     exc = webob.exc.HTTPNotFound(explanation='Raised a webob.exc')
     return wsgi.Fault(exc)
Exemple #14
0
 def test_fault_has_status_int(self):
     # Ensure the status_int is set correctly on faults.
     fault = wsgi.Fault(webob.exc.HTTPBadRequest(explanation='what?'))
     self.assertEqual(fault.status_int, 400)
Exemple #15
0
 def raiser(req):
     raise wsgi.Fault(webob.exc.HTTPForbidden(explanation='whut?'))
Exemple #16
0
 def raiser(req):
     raise wsgi.Fault(webob.exc.HTTPNotFound(explanation='whut?'))