Example #1
0
def setup_app(config=None):
    if not config:
        config = get_pecan_config()

    q_config.set_config_defaults()

    app_conf = dict(config.app)

    db_api.setup_db()

    if cfg.CONF.api.enable_job_handler:
        LOG.info('Starting periodic tasks...')
        periodics.start_job_handler()

    app = pecan.make_app(
        app_conf.pop('root'),
        hooks=lambda: [ctx.ContextHook(), ctx.AuthHook()],
        logging=getattr(config, 'logging', {}),
        **app_conf)

    # Set up access control.
    app = access_control.setup(app)

    # Create HTTPProxyToWSGI wrapper
    app = http_proxy_to_wsgi_middleware.HTTPProxyToWSGI(app, cfg.CONF)

    # Create a CORS wrapper, and attach mistral-specific defaults that must be
    # included in all CORS responses.
    return cors_middleware.CORS(app, cfg.CONF)
Example #2
0
def _wrap_app(app):
    app = request_id.RequestId(app)
    if cfg.CONF.auth_strategy == 'noauth':
        pass
    elif cfg.CONF.auth_strategy == 'keystone':
        app = auth_token.AuthProtocol(app, {})
    else:
        raise n_exc.InvalidConfigurationOption(
            opt_name='auth_strategy', opt_value=cfg.CONF.auth_strategy)

    # version can be unauthenticated so it goes outside of auth
    app = versions.Versions(app)

    # handle cases where neutron-server is behind a proxy
    app = http_proxy_to_wsgi.HTTPProxyToWSGI(app)

    # This should be the last middleware in the list (which results in
    # it being the first in the middleware chain). This is to ensure
    # that any errors thrown by other middleware, such as an auth
    # middleware - are annotated with CORS headers, and thus accessible
    # by the browser.
    app = cors.CORS(app, cfg.CONF)
    app.set_latent(allow_headers=[
        'X-Auth-Token', 'X-Identity-Status', 'X-Roles', 'X-Service-Catalog',
        'X-User-Id', 'X-Tenant-Id', 'X-OpenStack-Request-ID', 'X-Trace-Info',
        'X-Trace-HMAC'
    ],
                   allow_methods=['GET', 'PUT', 'POST', 'DELETE', 'PATCH'],
                   expose_headers=[
                       'X-Auth-Token', 'X-Subject-Token', 'X-Service-Token',
                       'X-OpenStack-Request-ID', 'X-Trace-Info', 'X-Trace-HMAC'
                   ])

    return app
Example #3
0
def _wrap_app(app):
    """Wraps wsgi app with additional middlewares."""
    app = request_id.RequestId(app)

    if CONF.audit.enabled:
        try:
            app = audit_middleware.AuditMiddleware(
                app,
                audit_map_file=CONF.audit.audit_map_file,
                ignore_req_list=CONF.audit.ignore_req_list)
        except (EnvironmentError, OSError,
                audit_middleware.PycadfAuditApiConfigError) as e:
            raise exceptions.InputFileError(
                file_name=CONF.audit.audit_map_file, reason=e)

    if cfg.CONF.api_settings.auth_strategy == constants.KEYSTONE:
        app = keystone.SkippingAuthProtocol(app, {})

    app = http_proxy_to_wsgi.HTTPProxyToWSGI(app)

    # This should be the last middleware in the list (which results in
    # it being the first in the middleware chain). This is to ensure
    # that any errors thrown by other middleware, such as an auth
    # middleware - are annotated with CORS headers, and thus accessible
    # by the browser.
    app = cors.CORS(app, cfg.CONF)
    cors.set_defaults(
        allow_headers=['X-Auth-Token', 'X-Openstack-Request-Id'],
        allow_methods=['GET', 'PUT', 'POST', 'DELETE'],
        expose_headers=['X-Auth-Token', 'X-Openstack-Request-Id'])

    return app
Example #4
0
    def test_backward_compat(self):
        @webob.dec.wsgify()
        def fake_app(req):
            return util.application_uri(req.environ)

        self.middleware = http_proxy_to_wsgi.HTTPProxyToWSGI(fake_app)
        response = self.request.get_response(self.middleware)
        self.assertEqual(b"http://localhost:80/", response.body)
Example #5
0
    def setUp(self):
        super(TestHTTPProxyToWSGI, self).setUp()

        @webob.dec.wsgify()
        def fake_app(req):
            return util.application_uri(req.environ)

        self.middleware = http_proxy_to_wsgi.HTTPProxyToWSGI(fake_app)
        self.request = webob.Request.blank('/foo/bar', method='POST')
Example #6
0
    def setUp(self):
        super(TestHTTPProxyToWSGI, self).setUp()

        @webob.dec.wsgify()
        def fake_app(req):
            return util.application_uri(req.environ)

        self.middleware = http_proxy_to_wsgi.HTTPProxyToWSGI(fake_app)
        self.middleware.oslo_conf.set_override('enable_proxy_headers_parsing',
                                               True,
                                               group='oslo_middleware')
        self.request = webob.Request.blank('/foo/bar', method='POST')
Example #7
0
def setup_app(pecan_config=None, extra_hooks=None):
    app_hooks = [
        hooks.ConfigHook(),
        hooks.DBHook(),
        hooks.ContextHook(pecan_config.app.acl_public_routes),
        hooks.RPCHook(),
        hooks.NoExceptionTracebackHook(),
        hooks.PublicUrlHook()
    ]
    if extra_hooks:
        app_hooks.extend(extra_hooks)

    if not pecan_config:
        pecan_config = get_pecan_config()

    if pecan_config.app.enable_acl:
        app_hooks.append(hooks.TrustedCallHook())

    pecan.configuration.set_config(dict(pecan_config), overwrite=True)

    app = pecan.make_app(
        pecan_config.app.root,
        static_root=pecan_config.app.static_root,
        debug=CONF.pecan_debug,
        force_canonical=getattr(pecan_config.app, 'force_canonical', True),
        hooks=app_hooks,
        wrap_app=middleware.ParsableErrorMiddleware,
    )

    if pecan_config.app.enable_acl:
        app = acl.install(app, cfg.CONF, pecan_config.app.acl_public_routes)

    # Create a CORS wrapper, and attach ironic-specific defaults that must be
    # included in all CORS responses.
    app = cors_middleware.CORS(app, CONF)
    app.set_latent(
        allow_headers=[Version.max_string, Version.min_string, Version.string],
        allow_methods=['GET', 'PUT', 'POST', 'DELETE', 'PATCH'],
        expose_headers=[
            Version.max_string, Version.min_string, Version.string
        ])

    # Insert the proxy support middleware to generate decent application links.
    app = proxy_middleware.HTTPProxyToWSGI(app, CONF)

    return app
Example #8
0
def setup_app(config=None):
    if not config:
        config = get_pecan_config()

    m_config.set_config_defaults()

    app_conf = dict(config.app)

    db_api_v2.setup_db()

    # TODO(rakhmerov): Why do we run cron triggers in the API layer?
    # Should we move it to engine?s
    if cfg.CONF.cron_trigger.enabled:
        periodic.setup()

    coordination.Service('api_group').register_membership()

    app = pecan.make_app(
        app_conf.pop('root'),
        hooks=lambda: [ctx.AuthHook(), ctx.ContextHook()],
        logging=getattr(config, 'logging', {}),
        **app_conf)

    # Set up access control.
    app = access_control.setup(app)

    # TODO(rakhmerov): need to get rid of this call.
    # Set up RPC related flags in config
    rpc.get_transport()

    # Set up profiler.
    if cfg.CONF.profiler.enabled:
        app = osprofiler.web.WsgiMiddleware(
            app,
            hmac_keys=cfg.CONF.profiler.hmac_keys,
            enabled=cfg.CONF.profiler.enabled)

    # Create HTTPProxyToWSGI wrapper
    app = http_proxy_to_wsgi_middleware.HTTPProxyToWSGI(app, cfg.CONF)

    # Create a CORS wrapper, and attach mistral-specific defaults that must be
    # included in all CORS responses.
    return cors_middleware.CORS(app, cfg.CONF)
Example #9
0
    def test_forwarded_for_headers(self):
        @webob.dec.wsgify()
        def fake_app(req):
            return req.environ['REMOTE_ADDR']

        self.middleware = http_proxy_to_wsgi.HTTPProxyToWSGI(fake_app)
        forwarded_for_addr = '1.2.3.4'
        forwarded_addr = '8.8.8.8'

        # If both X-Forwarded-For and Fowarded headers are present, it should
        # use the Forwarded header and ignore the X-Forwarded-For header.
        self.request.headers['Forwarded'] = (
            "for=%s;proto=https;host=example.com:8043" % (forwarded_addr))
        self.request.headers['X-Forwarded-For'] = forwarded_for_addr
        response = self.request.get_response(self.middleware)
        self.assertEqual(forwarded_addr.encode(), response.body)

        # Now if only X-Forwarded-For header is present, it should be used.
        del self.request.headers['Forwarded']
        response = self.request.get_response(self.middleware)
        self.assertEqual(forwarded_for_addr.encode(), response.body)
Example #10
0
def setup_app(pecan_config=None, extra_hooks=None):
    app_hooks = [
        hooks.ConfigHook(),
        hooks.DBHook(),
        hooks.ContextHook(pecan_config.app.acl_public_routes),
        hooks.RPCHook(),
        hooks.NoExceptionTracebackHook(),
        hooks.PublicUrlHook()
    ]
    if extra_hooks:
        app_hooks.extend(extra_hooks)

    if not pecan_config:
        pecan_config = get_pecan_config()

    pecan.configuration.set_config(dict(pecan_config), overwrite=True)

    app = pecan.make_app(
        pecan_config.app.root,
        debug=CONF.pecan_debug,
        static_root=pecan_config.app.static_root if CONF.pecan_debug else None,
        force_canonical=getattr(pecan_config.app, 'force_canonical', True),
        hooks=app_hooks,
        wrap_app=middleware.ParsableErrorMiddleware,
        # NOTE(dtantsur): enabling this causes weird issues with nodes named
        # as if they had a known mime extension, e.g. "mynode.1". We do
        # simulate the same behaviour for .json extensions for backward
        # compatibility through JsonExtensionMiddleware.
        guess_content_type_from_ext=False,
    )

    if CONF.audit.enabled:
        try:
            app = audit_middleware.AuditMiddleware(
                app,
                audit_map_file=CONF.audit.audit_map_file,
                ignore_req_list=CONF.audit.ignore_req_list)
        except (EnvironmentError, OSError,
                audit_middleware.PycadfAuditApiConfigError) as e:
            raise exception.InputFileError(file_name=CONF.audit.audit_map_file,
                                           reason=e)

    auth_middleware = None
    if CONF.auth_strategy == "keystone":
        auth_middleware = auth_token.AuthProtocol(
            app, {"oslo_config_config": cfg.CONF})
    elif CONF.auth_strategy == "http_basic":
        auth_middleware = auth_basic.BasicAuthMiddleware(
            app, cfg.CONF.http_basic_auth_user_file)

    if auth_middleware:
        app = auth_public_routes.AuthPublicRoutes(
            app,
            auth=auth_middleware,
            public_api_routes=pecan_config.app.acl_public_routes)

    if CONF.profiler.enabled:
        app = osprofiler_web.WsgiMiddleware(app)

    # NOTE(pas-ha) this registers oslo_middleware.enable_proxy_headers_parsing
    # option, when disabled (default) this is noop middleware
    app = http_proxy_to_wsgi.HTTPProxyToWSGI(app, CONF)

    # add in the healthcheck middleware if enabled
    # NOTE(jroll) this is after the auth token middleware as we don't want auth
    # in front of this, and WSGI works from the outside in. Requests to
    # /healthcheck will be handled and returned before the auth middleware
    # is reached.
    if CONF.healthcheck.enabled:
        app = healthcheck.Healthcheck(app, CONF)

    # Create a CORS wrapper, and attach ironic-specific defaults that must be
    # included in all CORS responses.
    app = IronicCORS(app, CONF)
    cors_middleware.set_defaults(
        allow_methods=['GET', 'PUT', 'POST', 'DELETE', 'PATCH'],
        expose_headers=[
            base.Version.max_string, base.Version.min_string,
            base.Version.string
        ])

    app = json_ext.JsonExtensionMiddleware(app)

    return app