Пример #1
0
 def __init__(self, message=None, **kwargs):
     if not message:
         if kwargs.get('host', None):
             self.message = _("Service %(service_id)s could not be "
                              "found on host %(host)s.")
         else:
             self.message = _("Service %(service_id)s could not be found.")
     super(ServiceNotFound, self).__init__(message, **kwargs)
Пример #2
0
 def __init__(self, code=None, message=None):
     if not code:
         # code is 408 means Request Timeout
         code = 408
     if not message:
         message = _('Wait Time Out')
     super(TimeoutHttpException, self).__init__(code, message)
Пример #3
0
def verify_password(password, hash_password):
    """Hash a password. Harder."""
    
    params = {}
    password_utf8 = verify_length_and_trunc_password(password).encode('utf-8')
    conf_hasher = CONF.identity.password_hash_algorithm
    hasher = _HASHER_NAME_MAP.get(conf_hasher)

    if hasher is None:
        raise RuntimeError(
        _('Password Hash Algorithm %s not found') % 
        CONF.identity.password_hash_algorithm)
    
    if CONF.identity.password_hash_rounds:
        params['rounds'] = CONF.identity.password_hash_rounds
    if hasher is passlib.hash.scrypt:
        if CONF.identity.scrypt_block_size:
            params['block_size'] = CONF.identity.scrypt_block_size
        if CONF.identity.scrypt_parallelism:
            params['parallelism'] = CONF.identity.scrypt_parallelism
        if CONF.identity.salt_bytesize:
            params['salt_size'] = CONF.identity.salt_bytesize
    if hasher is passlib.hash.pbkdf2_sha512:
        if CONF.identity.salt_bytesize:
            params['salt_size'] = CONF.identity.salt_bytesize
    
    return hasher.using(**params).verify(password_utf8, hash_password)
Пример #4
0
    def _error(self, inner, req):
        LOG.exception("Caught error: %(type)s %(error)s", {
            'type': type(inner),
            'error': 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("%(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:
            msg = (inner.msg if isinstance(inner, exception.HamalException)
                   else six.text_type(inner))
            params = {
                'exception': inner.__class__.__name__,
                'explanation': msg
            }
            outer.explanation = _('%(exception)s: %(explanation)s') % params
        return wsgi.Fault(outer)
Пример #5
0
class HamalException(Exception):
    """Base Hamal Exception

    To correctly use this class, inherit from it and define
    a 'message' property. That message will get printf'd
    with the keyword arguments provided to the constructor.

    """
    message = _("An unknown exception occurred.")
    code = 500
    headers = {}
    safe = False

    def __init__(self, message=None, **kwargs):
        self.kwargs = kwargs
        self.kwargs['message'] = message

        if 'code' not in self.kwargs:
            try:
                self.kwargs['code'] = self.code
            except AttributeError:
                pass

        for k, v in self.kwargs.items():
            if isinstance(v, Exception):
                self.kwargs[k] = six.text_type(v)

        if self._should_format():
            try:
                message = self.message % kwargs

            except Exception:
                exc_info = sys.exc_info()
                # kwargs doesn't match a variable in the message
                # log the issue and the kwargs
                LOG.exception('Exception in string format operation')
                for name, value in kwargs.items():
                    LOG.error("%(name)s: %(value)s",
                              {'name': name, 'value': value})
                if CONF.fatal_exception_format_errors:
                    six.reraise(*exc_info)
                # at least get the core message out if something happened
                message = self.message
        elif isinstance(message, Exception):
            message = six.text_type(message)

        # NOTE(luisg): We put the actual message in 'msg' so that we can access
        # it, because if we try to access the message via 'message' it will be
        # overshadowed by the class' message attribute
        self.msg = message
        super(HamalException, self).__init__(message)

    def _should_format(self):
        return self.kwargs['message'] is None or '%(message)' in self.message

    # NOTE(tommylikehu): This method can be used to
    # translate translatable variables (Message object here), do not
    # wrap it with str(), unicode(), six.text_type().
    def __unicode__(self):
        return self.msg
Пример #6
0
def action_peek_json(body):
    """Determine action to invoke."""

    try:
        decoded = jsonutils.loads(body)
    except ValueError:
        msg = _("cannot understand JSON")
        raise exception.MalformedRequestBody(reason=msg)

    # Make sure there's exactly one key...
    if len(decoded) != 1:
        msg = _("too many body keys")
        raise exception.MalformedRequestBody(reason=msg)

    # Return the action and the decoded body...
    return decoded.keys()[0]
Пример #7
0
    def __init__(self, name, loader=None, use_ssl=False):
        """Initialize, but do not start the WSGI server.

        :param name: The name of the WSGI server given to the loader.
        :param loader: Loads the WSGI application using the given name.
        :returns: None

        """
        self.name = name
        self.manager = self._get_manager()
        self.loader = loader or wsgi_common.Loader()
        self.app = self.loader.load_app(name)
        self.host = getattr(CONF, '%s_listen' % name, "0.0.0.0")
        self.port = getattr(CONF, '%s_listen_port' % name, 9278)
        self.workers = (getattr(CONF, '%s_workers' % name, None)
                        or processutils.get_worker_count())
        if self.workers and self.workers < 1:
            worker_name = '%s_workers' % name
            msg = (_("{0} value of {1} is invalid, must be greater than 0.") %
                   (worker_name, self.workers))
            raise exception.InvalidInput(msg)

        self.use_ssl = use_ssl or CONF.wsgi.use_ssl
        self.server = wsgi.Server(name,
                                  self.app,
                                  host=self.host,
                                  port=self.port,
                                  use_ssl=self.use_ssl)
Пример #8
0
    def __call__(self, environ, start_response):
        r"""Subclasses will probably want to implement __call__ like this:

        @webob.dec.wsgify(RequestClass=Request)
        def __call__(self, req):
          # Any of the following objects work as responses:

          # Option 1: simple string
          res = 'message\n'

          # Option 2: a nicely formatted HTTP exception page
          res = exc.HTTPForbidden(explanation='Nice try')

          # Option 3: a webob Response object (in case you need to play with
          # headers, or you want to be treated like an iterable)
          res = Response();
          res.app_iter = open('somefile')

          # Option 4: any wsgi app to be run next
          res = self.application

          # Option 5: you can get a Response object for a wsgi app, too, to
          # play with headers etc
          res = req.get_response(self.application)

          # You can then just return your response...
          return res
          # ... or set req.response and return None.
          req.response = res

        See the end of http://pythonpaste.org/webob/modules/dec.html
        for more info.

        """
        raise NotImplementedError(_('You must implement __call__'))
Пример #9
0
def model_query(context, model, *args, **kwargs):
    """Query helper that accounts for context's `read_deleted` field.

    :param context: context to query under
    :param session: if present, the session to use
    :param read_deleted: if present, overrides context's read_deleted field.
    """
    session = kwargs.get('session') or get_session()
    read_deleted = kwargs.get('read_deleted') or context.read_deleted

    query = session.query(model, *args)

    if read_deleted == 'no':
        query = query.filter_by(deleted=False)
    elif read_deleted == 'yes':
        pass  # omit the filter to include deleted and active
    elif read_deleted == 'only':
        query = query.filter_by(deleted=True)
    elif read_deleted == 'int_no':
        query = query.filter_by(deleted=0)
    else:
        raise Exception(
            _("Unrecognized read_deleted value '%s'") % read_deleted)

    return query
Пример #10
0
class ValidationError(Error):
    message_format = _("Exception to find %(attribute)s in %(target)s."
                       " The server could not comply with the request"
                       " since it is either malformed or otherwise"
                       " incorrect. The client is assumed to be in error.")
    code = int(http.client.BAD_REQUEST)
    title = http.client.responses[http.client.BAD_REQUEST]
Пример #11
0
def _get_hasher_from_ident(hashed):
    try:
        return _HASHER_NAME_MAP[hashed[0:hashed.index('$', 1) + 1]]
    except KeyError:
        raise ValueError(
        _('UnSupported password hashing algorithm ident: %s') % hashed[0:hashed.index('$', 1) + 1]
    )
Пример #12
0
    def _extract_tag(body):
        tag = None
        attr = "%s:tag" % Demo_tag.alias
        try:
            if attr in body:
                tag = body[attr]
        except ValueError:
            msg = _("malformed demo attribute")
            raise webob.exc.HTTPBadRequest(explanation=msg)

        return tag
Пример #13
0
    def __init__(self, ext_mgr=None):
        if ext_mgr is None:
            if self.ExtensionManager:
                ext_mgr = self.ExtensionManager()
            else:
                raise Exception(_("Must specify an ExtensionManager class"))

        mapper = ProjectMapper()
        self.resources = {}
        self._setup_routes(mapper)
        self._setup_ext_routes(mapper, ext_mgr)
        self._setup_extensions(ext_mgr)
        super(APIRouter, self).__init__(mapper)
Пример #14
0
 def _from_json(self, datastring):
     try:
         return jsonutils.loads(datastring)
     except ValueError:
         msg = _("cannot understand JSON")
         raise exception.MalformedRequestBody(reason=msg)
Пример #15
0
    def _process_stack(self, request, action, action_args, content_type, body,
                       accept):
        """Implement the processing stack."""

        # Get the implementing method
        try:
            meth, extensions = self.get_method(request, action, content_type,
                                               body)
        except (AttributeError, TypeError):
            return Fault(webob.exc.HTTPNotFound())
        except KeyError as ex:
            msg = _("There is no such action: %s") % ex.args[0]
            return Fault(webob.exc.HTTPBadRequest(explanation=msg))
        except exception.MalformedRequestBody:
            msg = _("Malformed request body")
            return Fault(webob.exc.HTTPBadRequest(explanation=msg))

        # Now, deserialize the request body...
        try:
            if content_type:
                contents = self.deserialize(meth, content_type, body)
            else:
                contents = {}
        except exception.InvalidContentType:
            msg = _("Unsupported Content-Type")
            return Fault(webob.exc.HTTPBadRequest(explanation=msg))
        except exception.MalformedRequestBody:
            msg = _("Malformed request body")
            return Fault(webob.exc.HTTPBadRequest(explanation=msg))

        # Update the action args
        action_args.update(contents)

        project_id = action_args.pop("project_id", None)
        context = request.environ.get('hamal.context')
        if (context and project_id and (project_id != context.project_id)):
            msg = _("Malformed request url")
            return Fault(webob.exc.HTTPBadRequest(explanation=msg))

        # Run pre-processing extensions
        response, post = self.pre_process_extensions(extensions, request,
                                                     action_args)

        if not response:
            try:
                with ResourceExceptionHandler():
                    action_result = self.dispatch(meth, request, action_args)
            except Fault as ex:
                response = ex

        if not response:
            # No exceptions; convert action_result into a
            # ResponseObject
            resp_obj = None
            if type(action_result) is dict or action_result is None:
                resp_obj = ResponseObject(action_result)
            elif isinstance(action_result, ResponseObject):
                resp_obj = action_result
            else:
                response = action_result

            # Run post-processing extensions
            if resp_obj:
                _set_request_id_header(request, resp_obj)
                # Do a preserialize to set up the response object
                serializers = getattr(meth, 'wsgi_serializers', {})
                resp_obj._bind_method_serializers(serializers)
                if hasattr(meth, 'wsgi_code'):
                    resp_obj._default_code = meth.wsgi_code
                resp_obj.preserialize(accept, self.default_serializers)

                # Process post-processing extensions
                response = self.post_process_extensions(
                    post, resp_obj, request, action_args)

            if resp_obj and not response:
                response = resp_obj.serialize(request, accept,
                                              self.default_serializers)

        try:
            msg_dict = dict(url=request.url, status=response.status_int)
            msg = _("%(url)s returned with HTTP %(status)d") % msg_dict
        except AttributeError as e:
            msg_dict = dict(url=request.url, e=e)
            msg = _("%(url)s returned a fault: %(e)s") % msg_dict

        LOG.info(msg)

        return response
Пример #16
0
class NotAuthorized(HamalException):
    message = _("Not authorized.")
    code = 403
Пример #17
0
    def start(self):
        """Start serving a WSGI application.

        :returns: None
        :raises: hamal.exception.InvalidInput

        """
        # The server socket object will be closed after server exits,
        # but the underlying file descriptor will remain open, and will
        # give bad file descriptor error. So duplicating the socket object,
        # to keep file descriptor usable.

        dup_socket = self._socket.dup()
        dup_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # sockets can hang around forever without keepalive
        dup_socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)

        # This option isn't available in the OS X version of eventlet
        if hasattr(socket, 'TCP_KEEPIDLE'):
            dup_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE,
                                  CONF.wsgi.tcp_keepidle)

        if self._use_ssl:
            try:
                ca_file = CONF.wsgi.ssl_ca_file
                cert_file = CONF.wsgi.ssl_cert_file
                key_file = CONF.wsgi.ssl_key_file

                if cert_file and not os.path.exists(cert_file):
                    raise RuntimeError(
                        _("Unable to find cert_file : %s") % cert_file)

                if ca_file and not os.path.exists(ca_file):
                    raise RuntimeError(
                        _("Unable to find ca_file : %s") % ca_file)

                if key_file and not os.path.exists(key_file):
                    raise RuntimeError(
                        _("Unable to find key_file : %s") % key_file)

                if self._use_ssl and (not cert_file or not key_file):
                    raise RuntimeError(
                        _("When running server in SSL mode, you must "
                          "specify both a cert_file and key_file "
                          "option value in your configuration file"))
                ssl_kwargs = {
                    'server_side': True,
                    'certfile': cert_file,
                    'keyfile': key_file,
                    'cert_reqs': ssl.CERT_NONE,
                }

                if CONF.wsgi.ssl_ca_file:
                    ssl_kwargs['ca_certs'] = ca_file
                    ssl_kwargs['cert_reqs'] = ssl.CERT_REQUIRED

                dup_socket = eventlet.wrap_ssl(dup_socket, **ssl_kwargs)
            except Exception:
                with excutils.save_and_reraise_exception():
                    LOG.error(("Failed to start %(name)s on %(host)s"
                               ":%(port)s with SSL support"), {
                                   'name': self.name,
                                   'host': self.host,
                                   'port': self.port
                               })

        wsgi_kwargs = {
            'func': eventlet.wsgi.server,
            'sock': dup_socket,
            'site': self.app,
            'protocol': self._protocol,
            'custom_pool': self._pool,
            'log': self._logger,
            'debug': False,
            'keepalive': CONF.wsgi.wsgi_keep_alive,
            'socket_timeout': self.client_socket_timeout
        }

        self._server = eventlet.spawn(**wsgi_kwargs)
Пример #18
0
class Invalid(HamalException):
    message = _("Unacceptable parameters.")
    code = 400
Пример #19
0
class PasteAppNotFound(NotFound):
    message = _("Could not load paste app '%(name)s' from %(path)s")
Пример #20
0
class ConfigNotFound(NotFound):
    message = _("Could not find config at %(path)s")
Пример #21
0
class NotFound(HamalException):
    message = _("Resource could not be found.")
    code = 404
    safe = True
Пример #22
0
def serve(server, workers=None):
    global _launcher
    if _launcher:
        raise RuntimeError(_('serve() can only be called once'))

    _launcher = service.launch(CONF, server, workers=workers)
Пример #23
0
class InvalidInput(Invalid):
    message = _("Invalid input received: %(reason)s")
Пример #24
0
    def __init__(self,
                 name,
                 app,
                 host=None,
                 port=None,
                 pool_size=None,
                 protocol=eventlet.wsgi.HttpProtocol,
                 backlog=128,
                 use_ssl=False):
        """Initialize, but do not start, a WSGI server.

        :param name: Pretty name for logging.
        :param app: The WSGI application to serve.
        :param host: IP address to serve the application.
        :param port: Port number to server the application.
        :param pool_size: Maximum number of eventlets to spawn concurrently.
        
        :returns: None

        """
        # Allow operators to customize http requests max header line size.
        eventlet.wsgi.MAX_HEADER_LINE = CONF.wsgi.max_header_line
        self.client_socket_timeout = CONF.wsgi.client_socket_timeout or None
        self.name = name
        self.app = app
        self._host = host or "0.0.0.0"
        self._port = port or 0
        self._server = None
        self._socket = None
        self._protocol = protocol
        self.pool_size = pool_size or self.default_pool_size
        self._pool = eventlet.GreenPool(self.pool_size)
        self._logger = logging.getLogger("hamal.%s.wsgi.server" % self.name)
        self._use_ssl = use_ssl

        if backlog < 1:
            raise exception.InvalidInput(
                reason=_('The backlog must be more than 1'))

        bind_addr = (host, port)
        # TODO(dims): eventlet's green dns/socket module does not actually
        # support IPv6 in getaddrinfo(). We need to get around this in the
        # future or monitor upstream for a fix
        try:
            info = socket.getaddrinfo(bind_addr[0], bind_addr[1],
                                      socket.AF_UNSPEC, socket.SOCK_STREAM)[0]
            family = info[0]
            bind_addr = info[-1]
        except Exception:
            family = socket.AF_INET

        try:
            self._socket = eventlet.listen(bind_addr, family, backlog=backlog)
        except EnvironmentError:
            LOG.error(_LE("Could not bind to %(host)s:%(port)s"), {
                'host': host,
                'port': port
            })
            raise

        (self._host, self._port) = self._socket.getsockname()[0:2]
        LOG.info(_LI("%(name)s listening on %(_host)s:%(_port)s"), {
            'name': self.name,
            '_host': self._host,
            '_port': self._port
        })
Пример #25
0
class MalformedRequestBody(HamalException):
    message = _("Malformed message body: %(reason)s")
Пример #26
0
class PasswordValidationError(ValidationError):
    message_format = _("The password does not match the requirements:"
                       " %(detail)s.")
Пример #27
0
class InvalidContentType(Invalid):
    message = _("Invalid content type %(content_type)s.")