def __init__( self, app, identifiers, authenticators, challengers, mdproviders, classifier, challenge_decider, log_stream=None, log_level=logging.INFO, remote_user_key="REMOTE_USER", ): PluggableAuthenticationMiddleware.__init__( self, app, identifiers, authenticators, challengers, mdproviders, classifier, challenge_decider, log_stream, log_level, remote_user_key, )
def make_auth_app(global_conf, **app_conf): """example authenticated app with an htpasswd file""" assert 'auth.htpasswd' in app_conf assert os.path.exists(app_conf['auth.htpasswd']) app_conf['traclegos.auth'] = True # make the app app = make_app(global_conf, **app_conf) # wrap in repoze.who authentication middleware htpasswd_auth = HTPasswdPlugin(app_conf['auth.htpasswd'], check) auth_tkt = AuthTktCookiePlugin('secret', 'auth_tkt') form = RedirectingFormPlugin('/', '/login', '/logout', 'auth_tkt') identifiers = [('form', form), ('auth_tkt', auth_tkt)] authenticators = [('htpasswd_auth', htpasswd_auth)] challengers = [('form', form)] from repoze.who.classifiers import default_request_classifier from repoze.who.classifiers import default_challenge_decider log_stream = None return PluggableAuthenticationMiddleware(app, identifiers, authenticators, challengers, [], default_request_classifier, default_challenge_decider, log_stream=None, log_level=logging.DEBUG)
def main(): import zope.app.wsgi zope_conf = os.path.join(here, 'zope.conf') zope = zope.app.wsgi.getWSGIApplication(zope_conf) from repoze.who.middleware import PluggableAuthenticationMiddleware from repoze.who.config import WhoConfig parser = WhoConfig(here) parser.parse(open(os.path.join(here, 'who.ini'))) log_stream = sys.stdout log_level = logging.DEBUG app = PluggableAuthenticationMiddleware( zope, parser.identifiers, parser.authenticators, parser.challengers, parser.mdproviders, parser.request_classifier, parser.challenge_decider, log_stream, log_level, ) from paste import httpserver httpserver.serve(app, host='0.0.0.0', port='9876')
def setUp(self): self.plugin = MACAuthPlugin() application = PluggableAuthenticationMiddleware( stub_application, [["mac", self.plugin]], [["mac", self.plugin]], [["mac", self.plugin]], [], stub_request_classifier, stub_challenge_decider) self.app = TestApp(application)
def fas_make_who_middleware(app, log_stream): faswho = FASWhoPlugin(fasurl) csrf_mdprovider = CSRFMetadataProvider(login_handler=tg.config.get( 'moksha.csrf.login_handler', '/login_handler')) form = RedirectingFormPlugin('/community/login', '/login_handler', '/logout', rememberer_name='fasident', reason_param='ec') # only for browser form.classifications = {IIdentifier: ['browser'], IChallenger: ['browser']} identifiers = [('form', form), ('fasident', faswho)] authenticators = [('fasauth', faswho)] challengers = [('form', form)] mdproviders = [('fasmd', faswho), ('csrfmd', csrf_mdprovider)] if os.environ.get('FAS_WHO_LOG'): log_stream = sys.stdout app = PluggableAuthenticationMiddleware(app, identifiers, authenticators, challengers, mdproviders, default_request_classifier, default_challenge_decider, log_stream=log_stream) return app
def make_middleware_with_config(app, global_conf, config_file, log_file=None, log_level=None): parser = WhoConfig(global_conf['here']) with open(config_file) as f: parser.parse(f) log_stream = None if log_level is None: log_level = logging.INFO elif not isinstance(log_level, int): log_level = _LEVELS[log_level.lower()] if log_file is not None: if log_file.lower() == 'stdout': log_stream = sys.stdout else: log_stream = open(log_file, 'wb') else: log_stream = logging.getLogger('repoze.who') log_stream.addHandler(NullHandler()) log_stream.setLevel(log_level or 0) return PluggableAuthenticationMiddleware( app, parser.identifiers, parser.authenticators, parser.challengers, parser.mdproviders, parser.request_classifier, parser.challenge_decider, log_stream, log_level, parser.remote_user_key, )
def make_middleware_with_config(app, global_conf, config_file, log_file=None, log_level=None): parser = WhoConfig(global_conf['here']) parser.parse(open(config_file)) log_stream = None if log_file is not None: if log_file.lower() == 'stdout': log_stream = sys.stdout else: log_stream = open(log_file, 'wb') if log_level is None: log_level = logging.INFO else: log_level = _LEVELS[log_level.lower()] return PluggableAuthenticationMiddleware( app, parser.identifiers, parser.authenticators, parser.challengers, parser.mdproviders, parser.request_classifier, parser.challenge_decider, log_stream, log_level, parser.remote_user_key, )
def __init__( self, app, identifiers, authenticators, challengers, mdproviders, classifier, challenge_decider, log_stream=None, log_level=logging.INFO, remote_user_key='REMOTE_USER', ): PluggableAuthenticationMiddleware.__init__(self, app, identifiers, authenticators, challengers, mdproviders, classifier, challenge_decider, log_stream, log_level, remote_user_key)
def setUp(self): self.plugin = VEPAuthPlugin(audiences=["localhost"], verifier=vep.DummyVerifier(), token_manager=StubTokenManager()) application = PluggableAuthenticationMiddleware(stub_application, [["vep", self.plugin]], [["vep", self.plugin]], [["vep", self.plugin]], [], stub_request_classifier, stub_challenge_decider) self.app = TestApp(application)
def _wsgi_app(self): parser = WhoConfig("") parser.parse(WHO_CONFIG) def application(environ, start_response): start_response("401 Unauthorized", []) return [""] return PluggableAuthenticationMiddleware( application, parser.identifiers, parser.authenticators, parser.challengers, parser.mdproviders, parser.request_classifier, parser.challenge_decider)
def make_ldap_auth_app(global_conf, **app_conf): """example authenticated app with ldap""" assert 'auth.base_dn' in app_conf, "No base_dn specified" assert 'auth.ldap_host' in app_conf, "No ldap_host specified" app_conf['traclegos.auth'] = True # make the app app = make_app(global_conf, **app_conf) # XXX bad touch # this should really be passed to the make_app factory and used there # but there's no current way of doing this intelligently app.application.remote_user_name = ldap_remote_user # get the ldap connection conn = ldap.open(app_conf['auth.ldap_host']) if app_conf.get('auth.use_tls', 'False').lower() == 'true': conn.start_tls_s() # wrap in repoze.who authentication middleware ldap_auth = LDAPAuthenticatorPlugin(conn, app_conf['auth.base_dn']) auth_tkt = AuthTktCookiePlugin('secret', 'auth_tkt') form = RedirectingFormPlugin('/', '/login', '/logout', 'auth_tkt') identifiers = [('form', form), ('auth_tkt', auth_tkt)] authenticators = [('ldap_auth', ldap_auth)] challengers = [('form', form)] from repoze.who.classifiers import default_request_classifier from repoze.who.classifiers import default_challenge_decider log_stream = None #import logging #logger = logging.getLogger('something') #logger.setLevel(logging.DEBUG) return PluggableAuthenticationMiddleware(app, identifiers, authenticators, challengers, [], default_request_classifier, default_challenge_decider, log_stream=None, log_level=logging.DEBUG)
def make_middleware(skip_authentication=False, *args, **kwargs): """ Return the requested authentication middleware. :param skip_authentication: If ``True``, an instance of :class:`AuthenticationForgerMiddleware` will be returned instead of :class:`repoze.who.middleware.PluggableAuthenticationMiddleware` :type skip_authentication: bool ``args`` and ``kwargs`` are the positional and named arguments, respectively, to be passed to the relevant authentication middleware. """ if asbool(skip_authentication): # We must replace the middleware: return AuthenticationForgerMiddleware(*args, **kwargs) else: return PluggableAuthenticationMiddleware(*args, **kwargs)
def AuthenticationMiddleware(app): import isitopen.model as model import isitopen.lib.helpers as h modelpassword = ModelPasswordPlugin(model) basicauth = BasicAuthPlugin('repoze.who') auth_tkt = AuthTktCookiePlugin('secret', 'auth_tkt') form = RedirectingFormPlugin( login_form_url=h.url_for(controller='account', action='login'), login_handler_path=h.url_for('login-handler'), logout_handler_path=h.url_for('logout-handler'), rememberer_name='auth_tkt', ) form.classifications = { IIdentifier:['browser'], IChallenger:['browser'] } # only for browser identifiers = [('form', form),('auth_tkt',auth_tkt),('basicauth',basicauth)] authenticators = [('modelpassword', modelpassword)] challengers = [('form',form), ('basicauth',basicauth)] mdproviders = [] from repoze.who.classifiers import default_request_classifier from repoze.who.classifiers import default_challenge_decider log_stream = None import os if os.environ.get('WHO_LOG'): log_stream = sys.stdout return PluggableAuthenticationMiddleware( app, identifiers, authenticators, challengers, mdproviders, default_request_classifier, default_challenge_decider, log_stream = log_stream, log_level = logging.DEBUG )
def authentication_middleware(app, config): return PluggableAuthenticationMiddleware(app, **who_args(config))
def make_faswho_middleware(app, log_stream=None, login_handler='/login_handler', login_form_url='/login', logout_handler='/logout_handler', post_login_url='/post_login', post_logout_url=None, fas_url=FAS_URL, insecure=False, ssl_cookie=True, httponly=True): ''' :arg app: WSGI app that is being wrapped :kwarg log_stream: :class:`logging.Logger` to log auth messages :kwarg login_handler: URL where the login form is submitted :kwarg login_form_url: URL where the login form is displayed :kwarg logout_handler: URL where the logout form is submitted :kwarg post_login_url: URL to redirect the user to after login :kwarg post_logout_url: URL to redirect the user to after logout :kwarg fas_url: Base URL to the FAS server :kwarg insecure: Allow connecting to a fas server without checking the server's SSL certificate. Opens you up to MITM attacks but can be useful when testing. *Do not enable this in production* :kwarg ssl_cookie: If :data:`True` (default), tell the browser to only send the session cookie back over https. :kwarg httponly: If :data:`True` (default), tell the browser that the session cookie should only be read for sending to a server, not for access by JavaScript or other clientside technology. This prevents using the session cookie to pass information to JavaScript clients but also prevents XSS attacks from stealing the session cookie information. ''' # Because of the way we override values (via a dict in AppConfig), we # need to make this a keyword arg and then check it here to make it act # like a positional arg. if not log_stream: raise TypeError( 'log_stream must be set when calling make_fasauth_middleware()') faswho = FASWhoPlugin(fas_url, insecure=insecure, ssl_cookie=ssl_cookie, httponly=httponly) csrf_mdprovider = CSRFMetadataProvider() form = FriendlyFormPlugin(login_form_url, login_handler, post_login_url, logout_handler, post_logout_url, rememberer_name='fasident', charset='utf-8') form.classifications = { IIdentifier: ['browser'], IChallenger: ['browser'] } # only for browser basicauth = BasicAuthPlugin('repoze.who') identifiers = [('form', form), ('fasident', faswho), ('basicauth', basicauth)] authenticators = [('fasauth', faswho)] challengers = [('form', form), ('basicauth', basicauth)] mdproviders = [('fasmd', faswho), ('csrfmd', csrf_mdprovider)] if os.environ.get('FAS_WHO_LOG'): log_stream = sys.stdout app = CSRFProtectionMiddleware(app) app = PluggableAuthenticationMiddleware( app, identifiers, authenticators, challengers, mdproviders, fas_request_classifier, default_challenge_decider, log_stream=log_stream, ) return app
def make_app(global_conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment load_environment(global_conf, app_conf) # The Pylons WSGI app app = PylonsApp() for plugin in PluginImplementations(IMiddleware): app = plugin.make_middleware(app, config) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map']) app = SessionMiddleware(app, config) app = CacheMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) #app = QueueLogMiddleware(app) if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, global_conf, **config['pylons.errorware']) # Display error documents for 401, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app, [400, 404]) else: app = StatusCodeRedirect(app, [400, 404, 500]) # Initialize repoze.who who_parser = WhoConfig(global_conf['here']) who_parser.parse(open(app_conf['who.config_file'])) if asbool(config.get('openid_enabled', 'true')): from repoze.who.plugins.openid.identification import OpenIdIdentificationPlugin who_parser.identifiers = [i for i in who_parser.identifiers if \ not isinstance(i, OpenIdIdentificationPlugin)] who_parser.challengers = [i for i in who_parser.challengers if \ not isinstance(i, OpenIdIdentificationPlugin)] app = PluggableAuthenticationMiddleware( app, who_parser.identifiers, who_parser.authenticators, who_parser.challengers, who_parser.mdproviders, who_parser.request_classifier, who_parser.challenge_decider, logging.getLogger('repoze.who'), logging.WARN, # ignored who_parser.remote_user_key, ) # Establish the Registry for this application app = RegistryManager(app) if asbool(static_files): # Serve static files static_max_age = None if not asbool(config.get('ckan.cache_enabled')) \ else int(config.get('ckan.static_max_age', 3600)) static_app = StaticURLParser(config['pylons.paths']['static_files'], cache_max_age=static_max_age) static_parsers = [static_app, app] # Configurable extra static file paths extra_static_parsers = [] for public_path in config.get('extra_public_paths', '').split(','): if public_path.strip(): extra_static_parsers.append( StaticURLParser(public_path.strip(), cache_max_age=static_max_age)) app = Cascade(extra_static_parsers + static_parsers) return app
def make_flask_stack(conf, **app_conf): """ This has to pass the flask app through all the same middleware that Pylons used """ root = os.path.dirname( os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) debug = asbool(conf.get('debug', conf.get('DEBUG', False))) testing = asbool(app_conf.get('testing', app_conf.get('TESTING', False))) app = flask_app = CKANFlask(__name__) app.debug = debug app.testing = testing app.template_folder = os.path.join(root, 'templates') app.app_ctx_globals_class = CKAN_AppCtxGlobals app.url_rule_class = CKAN_Rule app.jinja_options = jinja_extensions.get_jinja_env_options() # Update Flask config with the CKAN values. We use the common config # object as values might have been modified on `load_environment` if config: app.config.update(config) else: app.config.update(conf) app.config.update(app_conf) # Do all the Flask-specific stuff before adding other middlewares # Secret key needed for flask-debug-toolbar and sessions if not app.config.get('SECRET_KEY'): app.config['SECRET_KEY'] = config.get('beaker.session.secret') if not app.config.get('SECRET_KEY'): raise RuntimeError(u'You must provide a value for the secret key' ' with the SECRET_KEY config option') if debug: from flask_debugtoolbar import DebugToolbarExtension app.config['DEBUG_TB_INTERCEPT_REDIRECTS'] = False DebugToolbarExtension(app) # Use Beaker as the Flask session interface class BeakerSessionInterface(SessionInterface): def open_session(self, app, request): if 'beaker.session' in request.environ: return request.environ['beaker.session'] def save_session(self, app, session, response): session.save() namespace = 'beaker.session.' session_opts = dict([(k.replace('beaker.', ''), v) for k, v in config.iteritems() if k.startswith(namespace)]) if (not session_opts.get('session.data_dir') and session_opts.get('session.type', 'file') == 'file'): cache_dir = app_conf.get('cache_dir') or app_conf.get('cache.dir') session_opts['session.data_dir'] = '{data_dir}/sessions'.format( data_dir=cache_dir) app.wsgi_app = SessionMiddleware(app.wsgi_app, session_opts) app.session_interface = BeakerSessionInterface() # Add Jinja2 extensions and filters app.jinja_env.filters['empty_and_escape'] = \ jinja_extensions.empty_and_escape # Common handlers for all requests app.before_request(ckan_before_request) app.after_request(ckan_after_request) # Template context processors app.context_processor(helper_functions) app.context_processor(c_object) @app.context_processor def ungettext_alias(): u''' Provide `ungettext` as an alias of `ngettext` for backwards compatibility ''' return dict(ungettext=ungettext) # Babel pairs = [(os.path.join(root, u'i18n'), 'ckan') ] + [(p.i18n_directory(), p.i18n_domain()) for p in PluginImplementations(ITranslation)] i18n_dirs, i18n_domains = zip(*pairs) app.config[u'BABEL_TRANSLATION_DIRECTORIES'] = ';'.join(i18n_dirs) app.config[u'BABEL_DOMAIN'] = 'ckan' app.config[u'BABEL_MULTIPLE_DOMAINS'] = ';'.join(i18n_domains) babel = CKANBabel(app) babel.localeselector(get_locale) @app.route('/hello', methods=['GET']) def hello_world(): return 'Hello World, this is served by Flask' @app.route('/hello', methods=['POST']) def hello_world_post(): return 'Hello World, this was posted to Flask' # Auto-register all blueprints defined in the `views` folder _register_core_blueprints(app) _register_error_handler(app) # Set up each IBlueprint extension as a Flask Blueprint for plugin in PluginImplementations(IBlueprint): if hasattr(plugin, 'get_blueprint'): app.register_extension_blueprint(plugin.get_blueprint()) lib_plugins.register_group_plugins(app) lib_plugins.register_package_plugins(app) # Set flask routes in named_routes for rule in app.url_map.iter_rules(): if '.' not in rule.endpoint: continue controller, action = rule.endpoint.split('.') needed = list(rule.arguments - set(rule.defaults or {})) route = { rule.endpoint: { 'action': action, 'controller': controller, 'highlight_actions': action, 'needed': needed } } config['routes.named_routes'].update(route) # Start other middleware for plugin in PluginImplementations(IMiddleware): app = plugin.make_middleware(app, config) # Fanstatic if debug: fanstatic_config = { 'versioning': True, 'recompute_hashes': True, 'minified': False, 'bottom': True, 'bundle': False, } else: fanstatic_config = { 'versioning': True, 'recompute_hashes': False, 'minified': True, 'bottom': True, 'bundle': True, } root_path = config.get('ckan.root_path', None) if root_path: root_path = re.sub('/{{LANG}}', '', root_path) fanstatic_config['base_url'] = root_path app = Fanstatic(app, **fanstatic_config) for plugin in PluginImplementations(IMiddleware): try: app = plugin.make_error_log_middleware(app, config) except AttributeError: log.critical('Middleware class {0} is missing the method' 'make_error_log_middleware.'.format( plugin.__class__.__name__)) # Initialize repoze.who who_parser = WhoConfig(conf['here']) who_parser.parse(open(app_conf['who.config_file'])) app = PluggableAuthenticationMiddleware( app, who_parser.identifiers, who_parser.authenticators, who_parser.challengers, who_parser.mdproviders, who_parser.request_classifier, who_parser.challenge_decider, logging.getLogger('repoze.who'), logging.WARN, # ignored who_parser.remote_user_key) # Update the main CKAN config object with the Flask specific keys # that were set here or autogenerated flask_config_keys = set(flask_app.config.keys()) - set(config.keys()) for key in flask_config_keys: config[key] = flask_app.config[key] # Add a reference to the actual Flask app so it's easier to access app._wsgi_app = flask_app return app
def make_flask_stack(conf): """ This has to pass the flask app through all the same middleware that Pylons used """ root = os.path.dirname( os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) debug = asbool(conf.get('debug', conf.get('DEBUG', False))) testing = asbool(conf.get('testing', conf.get('TESTING', False))) app = flask_app = CKANFlask(__name__, static_url_path='') # Register storage for accessing group images, site logo, etc. storage_folder = [] storage = uploader.get_storage_path() if storage: storage_folder = [os.path.join(storage, 'storage')] # Static files folders (core and extensions) public_folder = config.get(u'ckan.base_public_folder') app.static_folder = config.get( 'extra_public_paths', '' ).split(',') + [os.path.join(root, public_folder)] + storage_folder app.jinja_options = jinja_extensions.get_jinja_env_options() app.jinja_env.policies['ext.i18n.trimmed'] = True app.debug = debug app.testing = testing app.template_folder = os.path.join(root, 'templates') app.app_ctx_globals_class = CKAN_AppCtxGlobals app.url_rule_class = CKAN_Rule # Update Flask config with the CKAN values. We use the common config # object as values might have been modified on `load_environment` if config: app.config.update(config) else: app.config.update(conf) # Do all the Flask-specific stuff before adding other middlewares # Secret key needed for flask-debug-toolbar and sessions if not app.config.get('SECRET_KEY'): app.config['SECRET_KEY'] = config.get('beaker.session.secret') if not app.config.get('SECRET_KEY'): raise RuntimeError(u'You must provide a value for the secret key' ' with the SECRET_KEY config option') root_path = config.get('ckan.root_path', None) if debug: from flask_debugtoolbar import DebugToolbarExtension app.config['DEBUG_TB_INTERCEPT_REDIRECTS'] = False debug_ext = DebugToolbarExtension() # register path that includes `ckan.site_root` before # initializing debug app. In such a way, our route receives # higher precedence. # TODO: After removal of Pylons code, switch to # `APPLICATION_ROOT` config value for flask application. Right # now it's a bad option because we are handling both pylons # and flask urls inside helpers and splitting this logic will # bring us tons of headache. if root_path: app.add_url_rule( root_path.replace('{{LANG}}', '').rstrip('/') + '/_debug_toolbar/static/<path:filename>', '_debug_toolbar.static', debug_ext.send_static_file ) debug_ext.init_app(app) from werkzeug.debug import DebuggedApplication app.wsgi_app = DebuggedApplication(app.wsgi_app, True) # Use Beaker as the Flask session interface class BeakerSessionInterface(SessionInterface): def open_session(self, app, request): if 'beaker.session' in request.environ: return request.environ['beaker.session'] def save_session(self, app, session, response): session.save() namespace = 'beaker.session.' session_opts = {k.replace('beaker.', ''): v for k, v in six.iteritems(config) if k.startswith(namespace)} if (not session_opts.get('session.data_dir') and session_opts.get('session.type', 'file') == 'file'): cache_dir = conf.get('cache_dir') or conf.get('cache.dir') session_opts['session.data_dir'] = '{data_dir}/sessions'.format( data_dir=cache_dir) app.wsgi_app = SessionMiddleware(app.wsgi_app, session_opts) app.session_interface = BeakerSessionInterface() # Add Jinja2 extensions and filters app.jinja_env.filters['empty_and_escape'] = \ jinja_extensions.empty_and_escape # Common handlers for all requests app.before_request(ckan_before_request) app.after_request(ckan_after_request) # Template context processors app.context_processor(helper_functions) app.context_processor(c_object) @app.context_processor def ungettext_alias(): u''' Provide `ungettext` as an alias of `ngettext` for backwards compatibility ''' return dict(ungettext=ungettext) # Babel _ckan_i18n_dir = i18n.get_ckan_i18n_dir() pairs = [ (_ckan_i18n_dir, u'ckan') ] + [ (p.i18n_directory(), p.i18n_domain()) for p in PluginImplementations(ITranslation) ] i18n_dirs, i18n_domains = zip(*pairs) app.config[u'BABEL_TRANSLATION_DIRECTORIES'] = ';'.join(i18n_dirs) app.config[u'BABEL_DOMAIN'] = 'ckan' app.config[u'BABEL_MULTIPLE_DOMAINS'] = ';'.join(i18n_domains) babel = CKANBabel(app) babel.localeselector(get_locale) # WebAssets _setup_webassets(app) # Auto-register all blueprints defined in the `views` folder _register_core_blueprints(app) _register_error_handler(app) # Set up each IBlueprint extension as a Flask Blueprint for plugin in PluginImplementations(IBlueprint): if hasattr(plugin, 'get_blueprint'): plugin_blueprints = plugin.get_blueprint() if not isinstance(plugin_blueprints, list): plugin_blueprints = [plugin_blueprints] for blueprint in plugin_blueprints: app.register_extension_blueprint(blueprint) lib_plugins.register_package_blueprints(app) lib_plugins.register_group_blueprints(app) # Set flask routes in named_routes # TODO: refactor whatever helper is using this to not do it if 'routes.named_routes' not in config: config['routes.named_routes'] = {} for rule in app.url_map.iter_rules(): if '.' not in rule.endpoint: continue controller, action = rule.endpoint.split('.') needed = list(rule.arguments - set(rule.defaults or {})) route = { rule.endpoint: { 'action': action, 'controller': controller, 'highlight_actions': action, 'needed': needed } } config['routes.named_routes'].update(route) # Start other middleware for plugin in PluginImplementations(IMiddleware): app = plugin.make_middleware(app, config) for plugin in PluginImplementations(IMiddleware): try: app = plugin.make_error_log_middleware(app, config) except AttributeError: log.critical('Middleware class {0} is missing the method' 'make_error_log_middleware.' .format(plugin.__class__.__name__)) # Initialize repoze.who who_parser = WhoConfig(conf['here']) who_parser.parse(open(conf['who.config_file'])) app = PluggableAuthenticationMiddleware( RepozeAdapterMiddleware(app), who_parser.identifiers, who_parser.authenticators, who_parser.challengers, who_parser.mdproviders, who_parser.request_classifier, who_parser.challenge_decider, logging.getLogger('repoze.who'), logging.WARN, # ignored who_parser.remote_user_key ) # Update the main CKAN config object with the Flask specific keys # that were set here or autogenerated flask_config_keys = set(flask_app.config.keys()) - set(config.keys()) for key in flask_config_keys: config[key] = flask_app.config[key] # Prevent the host from request to be added to the new header location. app = HostHeaderMiddleware(app) if six.PY3: app = I18nMiddleware(app) if asbool(config.get('ckan.tracking_enabled', 'false')): app = TrackingMiddleware(app, config) # Add a reference to the actual Flask app so it's easier to access app._wsgi_app = flask_app return app
def make_app(global_conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment load_environment(global_conf, app_conf) # The Pylons WSGI app app = PylonsApp() # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map']) app = SessionMiddleware(app, config) app = CacheMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) basicauth = BasicAuthPlugin('OpenSpending') auth_tkt = AuthTktCookiePlugin( 'RANDOM_KEY_THAT_ONLY_LOOKS_LIKE_A_PLACEHOLDER', cookie_name='openspending_login', timeout=86400 * 90, reissue_time=3600) form = FriendlyFormPlugin('/login', '/perform_login', '/after_login', '/logout', '/after_logout', rememberer_name='auth_tkt') identifiers = [('auth_tkt', auth_tkt), ('basicauth', basicauth), ('form', form)] authenticators = [('auth_tkt', auth_tkt), ('username', UsernamePasswordAuthenticator()), ('apikey', ApiKeyAuthenticator())] challengers = [('form', form), ('basicauth', basicauth)] log_stream = sys.stdout app = PluggableAuthenticationMiddleware(app, identifiers, authenticators, challengers, [], default_request_classifier, default_challenge_decider, log_stream=log_stream, log_level=logging.WARN) if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, global_conf, **config['pylons.errorware']) # Display error documents for 401, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app) else: app = StatusCodeRedirect(app, [400, 401, 403, 404, 500]) # Establish the Registry for this application app = RegistryManager(app) if asbool(static_files): max_age = None if asbool(config['debug']) else 3600 # Serve static files static_app = StaticURLParser(config['pylons.paths']['static_files'], cache_max_age=max_age) static_parsers = [static_app, app] app = Cascade(static_parsers) return app
def make_app(conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment load_environment(conf, app_conf) # The Pylons WSGI app app = PylonsApp() # set pylons globals app_globals.reset() for plugin in PluginImplementations(IMiddleware): app = plugin.make_middleware(app, config) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map']) # we want to be able to retrieve the routes middleware to be able to update # the mapper. We store it in the pylons config to allow this. config['routes.middleware'] = app app = SessionMiddleware(app, config) app = CacheMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) #app = QueueLogMiddleware(app) # Fanstatic if asbool(config.get('debug', False)): fanstatic_config = { 'versioning': True, 'recompute_hashes': True, 'minified': False, 'bottom': True, 'bundle': False, } else: fanstatic_config = { 'versioning': True, 'recompute_hashes': False, 'minified': True, 'bottom': True, 'bundle': True, } app = Fanstatic(app, **fanstatic_config) if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, conf, **config['pylons.errorware']) # Display error documents for 401, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app, [400, 404]) else: app = StatusCodeRedirect(app, [400, 404, 500]) # Initialize repoze.who who_parser = WhoConfig(conf['here']) who_parser.parse(open(app_conf['who.config_file'])) if asbool(config.get('openid_enabled', 'true')): from repoze.who.plugins.openid.identification import OpenIdIdentificationPlugin # Monkey patches for repoze.who.openid # Fixes #1659 - enable log-out when CKAN mounted at non-root URL from ckan.lib import repoze_patch OpenIdIdentificationPlugin.identify = repoze_patch.identify OpenIdIdentificationPlugin.redirect_to_logged_in = repoze_patch.redirect_to_logged_in OpenIdIdentificationPlugin._redirect_to_loginform = repoze_patch._redirect_to_loginform OpenIdIdentificationPlugin.challenge = repoze_patch.challenge who_parser.identifiers = [i for i in who_parser.identifiers if \ not isinstance(i, OpenIdIdentificationPlugin)] who_parser.challengers = [i for i in who_parser.challengers if \ not isinstance(i, OpenIdIdentificationPlugin)] app = PluggableAuthenticationMiddleware(app, who_parser.identifiers, who_parser.authenticators, who_parser.challengers, who_parser.mdproviders, who_parser.request_classifier, who_parser.challenge_decider, logging.getLogger('repoze.who'), logging.WARN, # ignored who_parser.remote_user_key, ) # Establish the Registry for this application app = RegistryManager(app) app = I18nMiddleware(app, config) if asbool(static_files): # Serve static files static_max_age = None if not asbool(config.get('ckan.cache_enabled')) \ else int(config.get('ckan.static_max_age', 3600)) static_app = StaticURLParser(config['pylons.paths']['static_files'], cache_max_age=static_max_age) static_parsers = [static_app, app] # Configurable extra static file paths extra_static_parsers = [] for public_path in config.get('extra_public_paths', '').split(','): if public_path.strip(): extra_static_parsers.append( StaticURLParser(public_path.strip(), cache_max_age=static_max_age) ) app = Cascade(extra_static_parsers + static_parsers) # Page cache if asbool(config.get('ckan.page_cache_enabled')): app = PageCacheMiddleware(app, config) # Tracking if asbool(config.get('ckan.tracking_enabled', 'false')): app = TrackingMiddleware(app, config) return app
def add_auth_middleware(self, app, skip_authentication): """ """ log_stream = config.get('who.log_stream', 'stdout') log_stream = LOG_STREAMS.get(log_stream, log_stream) if isinstance(log_stream, basestring): log_stream = logging.getLogger(log_stream) log_level = LOG_LEVELS.get(config['who.log_level'], logging.ERROR) log.debug("LOG_STREAM %s LOG_LEVEL %s", str(log_stream), str(log_level)) if 'who.config_file' in config and asbool( config.get('bisque.has_database')): parser = WhoConfig(config['here']) parser.parse(open(config['who.config_file'])) if not asbool(skip_authentication): app = PluggableAuthenticationMiddleware( app, parser.identifiers, parser.authenticators, parser.challengers, parser.mdproviders, parser.request_classifier, parser.challenge_decider, log_stream=log_stream, log_level=log_level, remote_user_key=parser.remote_user_key, ) else: app = AuthenticationForgerMiddleware( app, parser.identifiers, parser.authenticators, parser.challengers, parser.mdproviders, parser.request_classifier, parser.challenge_decider, log_stream=log_stream, log_level=log_level, remote_user_key=parser.remote_user_key, ) else: log.info("MEX auth only") # Add mex only authentication from repoze.who.plugins.basicauth import BasicAuthPlugin from bq.core.lib.mex_auth import make_plugin from repoze.who.classifiers import default_request_classifier from repoze.who.classifiers import default_challenge_decider basicauth = BasicAuthPlugin('repoze.who') mexauth = make_plugin() identifiers = [('mexauth', mexauth)] authenticators = [('mexauth', mexauth)] challengers = [] mdproviders = [] app = PluggableAuthenticationMiddleware( app, identifiers, authenticators, challengers, mdproviders, default_request_classifier, default_challenge_decider, log_stream=log_stream, log_level=log_level, ) return app
def setup_auth(app, authmetadata, form_plugin=None, form_identifies=True, cookie_secret='secret', cookie_name='authtkt', login_url='/login', login_handler='/login_handler', post_login_url=None, logout_handler='/logout_handler', post_logout_url=None, login_counter_name=None, cookie_timeout=None, cookie_reissue_time=None, **who_args): """ Sets :mod:`repoze.who` up with the provided authenticators and options to create FriendlyFormPlugin/FastFormPlugin. It returns a middleware that provides identification, authentication and authorization in a way that is compatible with repoze.who and repoze.what. """ if 'charset' in who_args: #pragma: no cover log.warn('charset argument in authentication setup is ignored') who_args.pop('charset') # If no identifiers are provided in repoze setup arguments # then create a default one using AuthTktCookiePlugin. if 'identifiers' not in who_args: from repoze.who.plugins.auth_tkt import AuthTktCookiePlugin cookie = AuthTktCookiePlugin(cookie_secret, cookie_name, timeout=cookie_timeout, reissue_time=cookie_reissue_time) who_args['identifiers'] = [('cookie', cookie)] who_args['authenticators'].insert(0, ('cookie', cookie)) # If no form plugin is provided then create a default # one using the provided options. if form_plugin is None: from tg.configuration.auth.fastform import FastFormPlugin form = FastFormPlugin(login_url, login_handler, post_login_url, logout_handler, post_logout_url, rememberer_name='cookie', login_counter_name=login_counter_name) else: form = form_plugin if form_identifies: who_args['identifiers'].insert(0, ('main_identifier', form)) # Setting the repoze.who challengers: if 'challengers' not in who_args: who_args['challengers'] = [] who_args['challengers'].append(('form', form)) # Including logging log_file = who_args.pop('log_file', None) if log_file is not None: if log_file.lower() == 'stdout': log_stream = sys.stdout elif log_file.lower() == 'stderr': log_stream = sys.stderr else: log_stream = open(log_file, 'wb') who_args['log_stream'] = log_stream log_level = who_args.get('log_level', None) if log_level is None: log_level = logging.INFO else: log_level = _LEVELS[log_level.lower()] who_args['log_level'] = log_level # Setting up the metadata provider for the user informations if 'mdproviders' not in who_args: who_args['mdproviders'] = [] if authmetadata: authmd = _AuthMetadataProvider(authmetadata) who_args['mdproviders'].append(('authmd', authmd)) # Set up default classifier if 'classifier' not in who_args: who_args['classifier'] = default_request_classifier # Set up default challenger decider if 'challenge_decider' not in who_args: who_args['challenge_decider'] = turbogears_challenge_decider skip_authn = who_args.pop('skip_authentication', False) if asbool(skip_authn): return _AuthenticationForgerMiddleware(app, **who_args) else: return PluggableAuthenticationMiddleware(app, **who_args)
def make_pylons_stack(conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # The Pylons WSGI app app = pylons_app = CKANPylonsApp() for plugin in PluginImplementations(IMiddleware): app = plugin.make_middleware(app, config) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map']) # we want to be able to retrieve the routes middleware to be able to update # the mapper. We store it in the pylons config to allow this. config['routes.middleware'] = app app = SessionMiddleware(app, config) app = CacheMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) # app = QueueLogMiddleware(app) if asbool(config.get('ckan.use_pylons_response_cleanup_middleware', True)): app = execute_on_completion(app, config, cleanup_pylons_response_string) # Fanstatic if asbool(config.get('debug', False)): fanstatic_config = { 'versioning': True, 'recompute_hashes': True, 'minified': False, 'bottom': True, 'bundle': False, } else: fanstatic_config = { 'versioning': True, 'recompute_hashes': False, 'minified': True, 'bottom': True, 'bundle': True, } app = Fanstatic(app, **fanstatic_config) for plugin in PluginImplementations(IMiddleware): try: app = plugin.make_error_log_middleware(app, config) except AttributeError: log.critical('Middleware class {0} is missing the method' 'make_error_log_middleware.'.format( plugin.__class__.__name__)) if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, conf, **config['pylons.errorware']) # Display error documents for 400, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app, [400, 403, 404]) else: app = StatusCodeRedirect(app, [400, 403, 404, 500]) # Initialize repoze.who who_parser = WhoConfig(conf['here']) who_parser.parse(open(app_conf['who.config_file'])) app = PluggableAuthenticationMiddleware( app, who_parser.identifiers, who_parser.authenticators, who_parser.challengers, who_parser.mdproviders, who_parser.request_classifier, who_parser.challenge_decider, logging.getLogger('repoze.who'), logging.WARN, # ignored who_parser.remote_user_key) # Establish the Registry for this application app = RegistryManager(app) app = common_middleware.I18nMiddleware(app, config) if asbool(static_files): # Serve static files static_max_age = None if not asbool( config.get('ckan.cache_enabled')) \ else int(config.get('ckan.static_max_age', 3600)) static_app = StaticURLParser(config['pylons.paths']['static_files'], cache_max_age=static_max_age) static_parsers = [static_app, app] storage_directory = uploader.get_storage_path() if storage_directory: path = os.path.join(storage_directory, 'storage') try: os.makedirs(path) except OSError, e: # errno 17 is file already exists if e.errno != 17: raise storage_app = StaticURLParser(path, cache_max_age=static_max_age) static_parsers.insert(0, storage_app) # Configurable extra static file paths extra_static_parsers = [] for public_path in config.get('extra_public_paths', '').split(','): if public_path.strip(): extra_static_parsers.append( StaticURLParser(public_path.strip(), cache_max_age=static_max_age)) app = Cascade(extra_static_parsers + static_parsers)