Exemple #1
0
    def setup_kws_server(self):
        """
        sets up the KWS server to run on a separate port
        """
        # based on http://docs.cherrypy.org/stable/refman/process/servers.html

        if not self.config['keyword_search']['kws_service_on']:
            return

        # load KWSWebService here since it will be loaded after self.configure
        # which brings secmodv2 into cherrypy.tools
        from DAS.web.kws_web_srv import KWSWebService
        kws_service = KWSWebService(self.config)
        kws_wsgi_app = _cptree.Tree()
        kws_wsgi_app.mount(kws_service, '/das')

        config = self.config['web_server']
        port = int(config.get("kws_port", 8214))
        host = config.get("kws_host", '0.0.0.0')

        if CherryPyWSGIServer:
            kws_server = CherryPyWSGIServer(
                bind_addr=(host, port),
                wsgi_app=kws_wsgi_app,
                numthreads=int(config.get("thread_pool_kws", 10)),
                request_queue_size=cpconfig["server.socket_queue_size"],
                # below are cherrypy default settings...
                # max=-1,
                # timeout=10,
                # shutdown_timeout=5
            )
            srv_adapter = ServerAdapter(engine, kws_server)
            srv_adapter.subscribe()
Exemple #2
0
    def setup_kws_server(self):
        """
        sets up the KWS server to run on a separate port
        """
        # based on http://docs.cherrypy.org/stable/refman/process/servers.html

        if not self.config['keyword_search']['kws_service_on']:
            return

        kws_service = KWSWebService(self.config)
        kws_wsgi_app = _cptree.Tree()
        kws_wsgi_app.mount(kws_service, '/das')

        config = self.config['web_server']
        port = int(config.get("kws_port", 8214))
        host = config.get("kws_host", '0.0.0.0')

        kws_server = CherryPyWSGIServer(
            bind_addr=(host, port),
            wsgi_app=kws_wsgi_app,
            numthreads=int(config.get("thread_pool_kws", 10)),
            request_queue_size=cpconfig["server.socket_queue_size"],
            # below are cherrypy default settings...
            # max=-1,
            # timeout=10,
            # shutdown_timeout=5
        )
        srv_adapter = ServerAdapter(engine, kws_server)
        srv_adapter.subscribe()
    def run(self):
        http_config = self.config['http']
        https_config = self.config['https']

        wsgi_app = wsgi.WSGIPathInfoDispatcher({'/': self.app})
        cherrypy.server.unsubscribe()
        cherrypy.config.update({'environment': 'production'})

        if https_config['enabled']:
            try:
                bind_addr_https = (https_config['listen'],
                                   https_config['port'])
                server_https = wsgi.WSGIServer(bind_addr=bind_addr_https,
                                               wsgi_app=wsgi_app)
                server_https.ssl_adapter = http_helpers.ssl_adapter(
                    https_config['certificate'], https_config['private_key'])

                ServerAdapter(cherrypy.engine, server_https).subscribe()
                logger.debug(
                    'WSGIServer starting... uid: %s, listen: %s:%s',
                    os.getuid(),
                    bind_addr_https[0],
                    bind_addr_https[1],
                )
            except IOError as e:
                logger.warning("HTTPS server won't start: %s", e)
        else:
            logger.debug('HTTPS server is disabled')

        if http_config['enabled']:
            bind_addr_http = (http_config['listen'], http_config['port'])
            server_http = wsgi.WSGIServer(bind_addr=bind_addr_http,
                                          wsgi_app=wsgi_app)
            ServerAdapter(cherrypy.engine, server_http).subscribe()
            logger.debug(
                'WSGIServer starting... uid: %s, listen: %s:%s',
                os.getuid(),
                bind_addr_http[0],
                bind_addr_http[1],
            )
        else:
            logger.debug('HTTP server is disabled')

        if not http_config['enabled'] and not https_config['enabled']:
            logger.critical('No HTTP/HTTPS server enabled')
            exit()

        list_routes(self.app)

        try:
            cherrypy.engine.start()
            cherrypy.engine.wait(states.EXITING)
        except KeyboardInterrupt:
            logger.warning('Stopping wazo-phoned: KeyboardInterrupt')
            cherrypy.engine.exit()
Exemple #4
0
def run_server(app):
    http_config = app.config['rest_api']['http']
    https_config = app.config['rest_api']['https']

    signal.signal(signal.SIGTERM, signal_handler)
    if app.config['profile']:
        app.wsgi_app = ProfilerMiddleware(app.wsgi_app,
                                          profile_dir=app.config['profile'])

    wsgi_app = wsgiserver.WSGIPathInfoDispatcher({'/': app})

    cherrypy.server.unsubscribe()
    cherrypy.config.update({'environment': 'production'})

    if not (http_config['enabled'] or https_config['enabled']):
        logger.critical('No HTTP/HTTPS server enabled')
        exit()

    if https_config['enabled']:
        try:
            bind_addr_https = (https_config['listen'], https_config['port'])
            server_https = CherryPyWSGIServer(bind_addr=bind_addr_https,
                                              wsgi_app=wsgi_app)
            server_https.ssl_adapter = http_helpers.ssl_adapter(https_config['certificate'],
                                                                https_config['private_key'],
                                                                https_config['ciphers'])
            ServerAdapter(cherrypy.engine, server_https).subscribe()

            logger.debug('HTTPS server starting on %s:%s', *bind_addr_https)

        except IOError as e:
            logger.warning("HTTPS server won't start: %s", e)
    else:
        logger.debug('HTTPS server is disabled')

    if http_config['enabled']:
        bind_addr_http = (http_config['listen'], http_config['port'])
        server_http = CherryPyWSGIServer(bind_addr=bind_addr_http,
                                         wsgi_app=wsgi_app)
        ServerAdapter(cherrypy.engine, server_http).subscribe()

        logger.debug('HTTP server starting on %s:%s', *bind_addr_http)
    else:
        logger.debug('HTTP server is disabled')

    try:
        cherrypy.engine.start()
        cherrypy.engine.block()
    except KeyboardInterrupt:
        cherrypy.engine.stop()
Exemple #5
0
    def run(self):
        wsgi_app_https = ReverseProxied(
            ProxyFix(wsgi.WSGIPathInfoDispatcher({'/': app})))
        wsgi_app_http = ReverseProxied(
            ProxyFix(wsgi.WSGIPathInfoDispatcher({'/': adapter_app})))
        cherrypy.server.unsubscribe()
        cherrypy.config.update({'environment': 'production'})

        bind_addr = (self.config['listen'], self.config['port'])

        server_https = wsgi.WSGIServer(bind_addr=bind_addr,
                                       wsgi_app=wsgi_app_https)
        server_https.ssl_adapter = http_helpers.ssl_adapter(
            self.config['certificate'], self.config['private_key'])
        ServerAdapter(cherrypy.engine, server_https).subscribe()
        logger.debug('WSGIServer starting... uid: %s, listen: %s:%s',
                     os.getuid(), bind_addr[0], bind_addr[1])

        for route in http_helpers.list_routes(app):
            logger.debug(route)

        if self.adapter_config['enabled']:
            bind_addr = (self.adapter_config['listen'],
                         self.adapter_config['port'])
            server_adapter = wsgi.WSGIServer(bind_addr=bind_addr,
                                             wsgi_app=wsgi_app_http)
            ServerAdapter(cherrypy.engine, server_adapter).subscribe()
            logger.debug('WSGIServer starting... uid: %s, listen: %s:%s',
                         os.getuid(), bind_addr[0], bind_addr[1])

            for route in http_helpers.list_routes(adapter_app):
                logger.debug(route)

        else:
            logger.debug('Adapter server is disabled')

        try:
            cherrypy.engine.start()
            cherrypy.engine.wait(states.EXITING)
        except KeyboardInterrupt:
            logger.warning('Stopping xivo-ctid-ng: KeyboardInterrupt')
            cherrypy.engine.exit()
Exemple #6
0
    def add_server(self, netloc, path, config):
        """Add a new CherryPy Application for a Virtual Host.
        Creates a new CherryPy WSGI Server instance if the host resolves
        to a different IP address or port.
        """

        from cherrypy._cpwsgi_server import CPWSGIServer
        from cherrypy.process.servers import ServerAdapter

        host, port = urllib.splitnport(netloc, 80)
        host = socket.gethostbyname(host)
        bind_addr = (host, port)
        if bind_addr not in self.servers:
            self.servers.append(bind_addr)
            server = CPWSGIServer()
            server.bind_addr = bind_addr
            adapter = ServerAdapter(cherrypy.engine, server, server.bind_addr)
            adapter.subscribe()
        self.domains[netloc] = cherrypy.Application(
            root=None, config={path.rstrip('/') or '/': config})
Exemple #7
0
    def add_server(self, netloc, path, config):
        """Add a new CherryPy Application for a Virtual Host.
 
        Creates a new CherryPy WSGI Server instance if the host resolves
        to a different IP address or port.
 
        """
        from cherrypy._cpwsgi_server import CPWSGIServer
        from cherrypy.process.servers import ServerAdapter
 
        host, port = urllib.splitnport(netloc, 80)
        host = socket.gethostbyname(host)
        bind_addr = (host, port)
        if bind_addr not in self.servers:
            self.servers.append(bind_addr)
            server = CPWSGIServer()
            server.bind_addr = bind_addr
            adapter = ServerAdapter(cherrypy.engine, server, server.bind_addr)
            adapter.subscribe()
        self.domains[netloc] = cherrypy.Application(root=None,
            config={path.rstrip('/') or '/': config})
Exemple #8
0
def configure_http_server(port):
    # Mount the application
    from kolibri.deployment.default.wsgi import application

    whitenoise_settings = {
        "static_root": settings.STATIC_ROOT,
        "static_prefix": settings.STATIC_URL,
        # Use 1 day as the default cache time for static assets
        "max_age": 24 * 60 * 60,
        # Add a test for any file name that contains a semantic version number
        # or a 32 digit number (assumed to be a file hash)
        # these files will be cached indefinitely
        "immutable_file_test":
        r"((0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)|[a-f0-9]{32})",
        "autorefresh": getattr(settings, "DEVELOPER_MODE", False),
    }

    # Mount static files
    application = DjangoWhiteNoise(application, **whitenoise_settings)

    cherrypy.tree.graft(application, "/")

    # Mount media files
    cherrypy.tree.mount(
        cherrypy.tools.staticdir.handler(section="/", dir=settings.MEDIA_ROOT),
        settings.MEDIA_URL,
    )

    # Mount content files
    CONTENT_ROOT = "/" + paths.get_content_url(
        conf.OPTIONS["Deployment"]["URL_PATH_PREFIX"]).lstrip("/")
    content_dirs = [paths.get_content_dir_path()
                    ] + paths.get_content_fallback_paths()
    dispatcher = MultiStaticDispatcher(content_dirs)
    content_handler = cherrypy.tree.mount(
        None,
        CONTENT_ROOT,
        config={
            "/": {
                "tools.caching.on": False,
                "request.dispatch": dispatcher
            }
        },
    )

    cherrypy_server_config = {
        "server.socket_host":
        LISTEN_ADDRESS,
        "server.socket_port":
        port,
        "server.thread_pool":
        conf.OPTIONS["Server"]["CHERRYPY_THREAD_POOL"],
        "server.socket_timeout":
        conf.OPTIONS["Server"]["CHERRYPY_SOCKET_TIMEOUT"],
        "server.accepted_queue_size":
        conf.OPTIONS["Server"]["CHERRYPY_QUEUE_SIZE"],
        "server.accepted_queue_timeout":
        conf.OPTIONS["Server"]["CHERRYPY_QUEUE_TIMEOUT"],
    }

    # Configure the server
    cherrypy.config.update(cherrypy_server_config)

    alt_port_addr = (
        LISTEN_ADDRESS,
        conf.OPTIONS["Deployment"]["ZIP_CONTENT_PORT"],
    )

    # Mount static files
    alt_port_app = wsgi.PathInfoDispatcher({
        "/": get_application(),
        CONTENT_ROOT: content_handler
    })
    alt_port_app = DjangoWhiteNoise(alt_port_app, **whitenoise_settings)

    alt_port_server = ServerAdapter(
        cherrypy.engine,
        wsgi.Server(
            alt_port_addr,
            alt_port_app,
            numthreads=conf.OPTIONS["Server"]["CHERRYPY_THREAD_POOL"],
            request_queue_size=conf.OPTIONS["Server"]["CHERRYPY_QUEUE_SIZE"],
            timeout=conf.OPTIONS["Server"]["CHERRYPY_SOCKET_TIMEOUT"],
            accepted_queue_size=conf.OPTIONS["Server"]["CHERRYPY_QUEUE_SIZE"],
            accepted_queue_timeout=conf.OPTIONS["Server"]
            ["CHERRYPY_QUEUE_TIMEOUT"],
        ),
        alt_port_addr,
    )
    # Subscribe these servers
    cherrypy.server.subscribe()
    alt_port_server.subscribe()
Exemple #9
0
def configure():
    """
    Configures the cherrypy server (sets up the tree, cherrypy config, etc.).
    """
    global configured
    # Setup the session storage directory if it does not exist
    if config.get('sessions.on') and config.get('sessions.storage_type') == 'file':
        path = config['sessions.storage_path']
        if not os.path.exists(path):
            try:
                os.makedirs(path) # By default these will be 0777
            except:
                warnings.warn("Unable to create the session directory: {0}".format(path))
                  
    cherrypy.config.update({
        "server.socket_host": config['server.socket_host'],
        "server.socket_port": config['server.socket_port'],
        
        "checker.on": False,
        "log.screen": False,
        #"engine.autoreload_on": False,
        "engine.autoreload_on": config.as_bool("debug"),
        
        "tools.sessions.on": config.as_bool('sessions.on'),
        "tools.sessions.persistent": config.as_bool('sessions.persistent'),
        "tools.sessions.path": config['sessions.path'],
        "tools.sessions.timeout": config['sessions.timeout'],
        "tools.sessions.storage_type": config['sessions.storage_type'],
        "tools.sessions.storage_path": config['sessions.storage_path'],
        "tools.sessions.secure": config['sessions.secure'],

        "request.show_tracebacks": config.as_bool("debug"),
        "checker.on": False,
        "tools.caching.on": False,
        "tools.expires.on": True,
        "tools.expires.secs": 0,
        "tools.expires.force": True,
        "tools.log_headers.on": False,
        "engine.autoreload_on": config.as_bool("debug"),
        
        "tools.encode.on": True,
        "tools.encode.encoding": "utf8",
        
        "error_page.default": error_handler
        })
    
    if config['server.behind_proxy']:
        cherrypy.config.update({"tools.proxy.on": True})
    
    if config['server.ssl_certificate']:
        # Make this conditional so we can host behind apache?
        cherrypy.config.update({
        "server.ssl_certificate": config['server.ssl_certificate'],
        "server.ssl_private_key": config['server.ssl_private_key'],
        "server.ssl_certificate_chain": config['server.ssl_certificate_chain'],
        })
        
    
    def rollback_dbsession():
        log.info("Rolling back SA transaction.")
        session = meta.Session()
        session.rollback()
    
    def commit_dbsession():
        log.info("Committing SA transaction.")
        session = meta.Session()
        session.commit()
    
    cherrypy.tools.dbsession_rollback = cherrypy.Tool('before_error_response', rollback_dbsession)
    cherrypy.tools.dbsession_commit = cherrypy.Tool('on_end_resource', commit_dbsession)
    
    # This is a "flow-control" exception.       
    class _LoginFailed(Exception):
        pass
        
    # TODO: Refactor to combine with the ensconce.webapp.tree methods
    def checkpassword(realm, username, password):
        auth_providers = get_configured_providers()
        try:
            for auth_provider in auth_providers:
                try:
                    auth_provider.authenticate(username, password)
                except exc.InsufficientPrivileges:
                    # Fail fast in this case; we don't want to continue on to try other authenticators.
                    raise _LoginFailed()
                except exc.AuthError:
                    # Swallow other auth errors so it goes onto next authenticator in the list.
                    pass
                except:
                    # Other exceptions needs to get logged at least.
                    log.exception("Unexpected error authenticating user using {0!r}".format(auth_provider))
                else:
                    log.info("Authentication succeeded for username {0} using provider {1}".format(username, auth_provider))
                    break
            else:
                log.debug("Authenticators exhausted; login failed.")
                raise _LoginFailed()
        except _LoginFailed:
            auditlog.log(auditlog.CODE_AUTH_FAILED, comment=username)
            return False
        else:
            # Resolve the user using the *current value* for auth_provider (as that is the one that passed the auth.
            user = auth_provider.resolve_user(username)
            
            log.debug("Setting up cherrypy session with username={0}, user_id={1}".format(username, user.id))    
            cherrypy.session['username'] = username # @UndefinedVariable
            cherrypy.session['user_id'] = user.id # @UndefinedVariable
            
            auditlog.log(auditlog.CODE_AUTH_LOGIN)
            return True
        
    app_conf = {
        "/static": {
            "tools.staticdir.on": True,
            "tools.staticdir.dir": config['static_dir'],
            "tools.staticdir.index": "index.html"
        },
        "/jsonrpc": {
            'tools.auth_basic.on': True,
            'tools.auth_basic.realm': 'api',
            'tools.auth_basic.checkpassword': checkpassword,
        }
    }
    
    # Add a plugin that will run the Crypto.Random.atfork() method, since this must
    # be called after forking (and we run this as a daemon in production)
    util.RNGInitializer(cherrypy.engine).subscribe()


    # Wire up our daemon tasks
    background_tasks = []
    if config.get('sessions.on'):
        background_tasks.append(tasks.DaemonTask(tasks.remove_old_session_files, interval=60))
        
    if config.get('backups.on'):
        backup_interval = config['backups.interval_minutes'] * 60
        background_tasks.append(tasks.DaemonTask(tasks.backup_database, interval=backup_interval, wait_first=True))
        background_tasks.append(tasks.DaemonTask(tasks.remove_old_backups, interval=3600, wait_first=True)) # This checks a day-granularity interval internally.
    
    
    # Unsubscribe anything that is already there, so that this method is idempotent
    # (This surfaces as nasty bugs in testing otherwise.)
    for channel in cherrypy.engine.listeners:
        for callback in cherrypy.engine.listeners[channel]:
            log.debug("Unsubscribing {0}:{1!r}".format(channel, callback))
#            log.debug("Unsubscribing {0}:{1!r}".format(channel, callback))
#            cherrypy.engine.unsubscribe(channel, callback)
        
    
    for task in background_tasks:
        cherrypy.engine.subscribe("start", task.start, priority=99)
        cherrypy.engine.subscribe("stop", task.stop)
    
    # Setup the basic/top-level webapp API
    root = tree.Root()
    
    # Iterate over all the modules in the ensconce.webapp.tree package and add
    # their 'Root' classes to the tree
    pkgpath = os.path.dirname(tree.__file__)
    for modname in [name for (_, name, _) in pkgutil.iter_modules([pkgpath])]:
        module = __import__("ensconce.webapp.tree." + modname, fromlist=["Root"])
        module_root = module.Root()
        setattr(root, modname, module_root)
    
    # I think this is here because we want to explicitly specify the ServerAdapter below
    # rather than use a default one.
    cherrypy.server.unsubscribe()
    
    app = cherrypy.tree.mount(root, "/", app_conf)
    app.log.error_log.level = cherrypy.log.error_log.level  # @UndefinedVariable
    app.log.access_log.level = cherrypy.log.access_log.level  # @UndefinedVariable
    
    addr = (config["server.socket_host"], config["server.socket_port"])
    server = CherryPyWSGIServer(addr, app, numthreads=50, timeout=2)  # TODO: make numthreads and keepalive timeout configurable
    
    
    # TODO: This is also mentioned in the cherrypy config above .... ?  One of these is probably redundant.
    server.ssl_certificate = config["server.ssl_certificate"]
    server.ssl_private_key = config["server.ssl_private_key"]
    if config["server.ssl_certificate_chain"]:
        server.ssl_certificate_chain = config["server.ssl_certificate_chain"]
        
    adapter = ServerAdapter(cherrypy.engine, server, server.bind_addr)
    adapter.subscribe()
    
    configured = True