def __init__(self, realm): BasicAuthAuthenticationPolicy.__init__(self, check=None, realm=realm) # TODO - G.M - 2018-09-21 - Disable callback is needed to have BasicAuth # correctly working, if enabled, callback method will try check method # who is now disabled (uneeded because we use directly # authenticated_user_id) and failed. self.callback = None
def includeme(config): authentication_policy = BasicAuthAuthenticationPolicy(check) authorization_policy = ACLAuthorizationPolicy() config.set_authentication_policy(authentication_policy) config.set_authorization_policy(authorization_policy) config.set_root_factory(lambda request: RootFactory())
def main(global_config, **settings): settings["global_config"] = global_config config = Configurator(settings=settings) # Jinja 2 templates as .html files config.include('pyramid_jinja2') config.add_jinja2_renderer('.html') config.add_jinja2_search_path('pyramid_notebook:demo/templates', name='.html') config.add_route('home', '/') config.add_route('login', '/login') config.add_route('shell1', '/shell1') config.add_route('shell2', '/shell2') config.add_route('shutdown_notebook', '/notebook/shutdown') config.add_route('notebook_proxy', '/notebook/*remainder') config.scan(views) authn_policy = auth.AuthTktAuthenticationPolicy('seekrITT', callback=auth.groupfinder) config.set_authentication_policy(BasicAuthAuthenticationPolicy(mycheck)) config.set_authorization_policy(authn_policy) # Make sure we can target Pyramid router debug messages in logging configuration pyramid_debug_logger = logging.getLogger("pyramid_debug") config.registry.registerUtility(pyramid_debug_logger, IDebugLogger) return config.make_wsgi_app()
def main(): '''Start the infirmary server''' args = _parseArgs() logging.basicConfig(level=args.loglevel) _logger.info('🏥 Infirmary version %s', VERSION) config = Configurator(registry=getGlobalSiteManager(), root_factory=Root) config.setup_registry() config.set_authentication_policy(BasicAuthAuthenticationPolicy(_checkCredentials)) config.set_authorization_policy(ACLAuthorizationPolicy()) config.add_route('home', '/') config.add_route('ping', '/ping') config.add_route('hello', '/hello/{name}', factory=Root) config.add_route('clinicalCores', '/clinicalCores', factory=Root) config.add_route('clinicalCore', '/clinicalCores/{participant_ID}', factory=Root) config.add_route('organs', '/organs', factory=Root) config.add_route('organ', '/organs/{identifier}', factory=Root) config.add_route('specimens', '/specimens', factory=Root) config.add_route('specimen', '/specimens/{specimen_ID}', factory=Root) config.add_route('genomics', '/genomics', factory=Root) config.add_route('genomic', '/genomics/{specimen_ID}', factory=Root) config.add_route('images', '/images', factory=Root) config.add_route('image', '/images/{identifier}', factory=Root) config.add_subscriber(cors_callback, NewRequest) config.scan() provideUtility(AppStats(sys.argv[0])) provideUtility(Directory(args.ldap_server)) provideUtility(Database(args.database)) app = config.make_wsgi_app() _logger.debug('🏃♀️ Starting server on port %d', args.port) server = make_server('0.0.0.0', args.port, app) server.serve_forever()
def main(): # Stupid workaround to wait for mysql actually starting inside of a container time.sleep(15) # Just init the database at the start for simplicity db.create.init() p = BackgroundEventPersister(Events) p.start() DBSession.configure(bind=Engine) Base.metadata.bind = Engine with Configurator() as config: config.include('pyramid_tm') config.add_request_method(get_user, 'user', reify=True) config.add_route('place_order', '/orders', request_method='POST') config.add_route('list_orders', '/orders', request_method='GET') config.add_route('cancel_order', '/order/{orderId}', request_method='DELETE') config.scan('views') auth_policy = BasicAuthAuthenticationPolicy(check_credentials) config.set_authentication_policy(auth_policy) config.set_authorization_policy(ACLAuthorizationPolicy()) config.set_root_factory(lambda request: Root()) app = config.make_wsgi_app() serve(app, host='0.0.0.0', port=8888)
def create_authentication(settings): timeout = settings.get("authtkt_timeout") timeout = None if timeout is None else int(timeout) reissue_time = settings.get("reissue_time") reissue_time = None if reissue_time is None else int(reissue_time) http_only = settings.get("authtkt_http_only", "True") http_only = http_only.lower() in ("true", "yes", "1") secure = settings.get("authtkt_secure", "True") secure = secure.lower() in ("true", "yes", "1") samesite = settings.get("authtkt_samesite", "Lax") secret = settings["authtkt_secret"] if len(secret) < 64: raise Exception( '"authtkt_secret should be at least 64 characters.' 'See https://docs.pylonsproject.org/projects/pyramid/en/latest/api/session.html' ) cookie_authentication_policy = AuthTktAuthenticationPolicy( secret, callback=defaultgroupsfinder, cookie_name=settings["authtkt_cookie_name"], samesite=None if samesite == '' else samesite, timeout=timeout, max_age=timeout, reissue_time=reissue_time, hashalg="sha512", http_only=http_only, secure=secure, ) basic_authentication_policy = BasicAuthAuthenticationPolicy( c2cgeoportal_check) policies = [cookie_authentication_policy, basic_authentication_policy] return MultiAuthenticationPolicy(policies)
def main(*args, **settings): from pyramid.config import Configurator from pyramid.events import NewRequest, ContextFound from pyramid.authentication import BasicAuthAuthenticationPolicy from pyramid.authorization import ACLAuthorizationPolicy from pyramid.renderers import JSON, JSONP logger.info('Start registry api...') read_users(settings['auth.file']) config = Configurator(autocommit=True, settings=settings, authentication_policy=BasicAuthAuthenticationPolicy( auth_check, __name__), authorization_policy=ACLAuthorizationPolicy(), root_factory=Root, route_prefix=ROUTE_PREFIX) config.include('pyramid_exclog') config.add_forbidden_view(forbidden) config.add_request_method(request_params, 'params', reify=True) config.add_request_method(authenticated_role, reify=True) config.add_renderer('prettyjson', JSON(indent=4)) config.add_renderer('jsonp', JSONP(param_name='opt_jsonp')) config.add_renderer('prettyjsonp', JSONP(indent=4, param_name='opt_jsonp')) config.add_subscriber(add_logging_context, NewRequest) config.add_subscriber(set_logging_context, ContextFound) config.add_subscriber(set_renderer, NewRequest) config.add_route('health', '/health') config.add_route('registry', '/registry/{param}.json') config.scan('openprocurement.medicines.registry.api.views') return config.make_wsgi_app()
def setup_basic_http_auth(config): """ Initialize HTTP Basic Auth support. """ realm = "Sandglass API" basic_auth = BasicAuthAuthenticationPolicy(auth_callback, realm=realm) config.set_authentication_policy(basic_auth) config.add_forbidden_view(handle_basic_auth_challenge)
def main(global_config, **settings): from openprocurement.integrations.edr.auth import (authenticated_role) from openprocurement.integrations.edr.utils import ( forbidden, add_logging_context, set_logging_context, request_params, set_renderer, Root, read_users) from openprocurement.integrations.edr.utils import auth_check from pyramid.authentication import BasicAuthAuthenticationPolicy from pyramid.authorization import ACLAuthorizationPolicy from pyramid.config import Configurator from pyramid.events import NewRequest, ContextFound from pyramid.renderers import JSON, JSONP LOGGER.info('Start edr api') read_users(settings['auth.file']) config = Configurator( autocommit=True, settings=settings, authentication_policy=BasicAuthAuthenticationPolicy( auth_check, __name__), authorization_policy=ACLAuthorizationPolicy(), root_factory=Root, route_prefix=ROUTE_PREFIX, ) config.include('pyramid_exclog') config.add_forbidden_view(forbidden) config.add_request_method(request_params, 'params', reify=True) config.add_request_method(authenticated_role, reify=True) config.add_renderer('prettyjson', JSON(indent=4)) config.add_renderer('jsonp', JSONP(param_name='opt_jsonp')) config.add_renderer('prettyjsonp', JSONP(indent=4, param_name='opt_jsonp')) config.add_renderer( 'yaml', 'openprocurement.integrations.edr.renderers.YAMLRenderer') config.add_subscriber(add_logging_context, NewRequest) config.add_subscriber(set_logging_context, ContextFound) config.add_subscriber(set_renderer, NewRequest) # Init edr connection config.registry.edr_client = EdrClient( settings.get('edr_api_server'), settings.get('edr_api_token'), int(settings.get('edr_api_port')), float(settings.get('edr_timeout_min', 1)), float(settings.get('edr_timeout_max', 60)), float(settings.get('edr_timeout_step', 2)), settings.get('edr_timeout_mode', 'mult')) config.registry.cache_db = Db(settings) config.registry.time_to_live = settings.get("time_to_live", 300) config.registry.time_to_live_negative = settings.get( "time_to_live_negative", 30) LOGGER.info("SANDBOX_MODE = {}".format(SANDBOX_MODE)) # Include views config.add_route('verify', '/verify') config.add_route('details', '/details/{id}') config.add_route('health', '/health') config.scan("openprocurement.integrations.edr.views") return config.make_wsgi_app()
def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ with Configurator(settings=settings) as config: config.route_prefix = 'api' config.include('cornice') config.include('cornice_swagger') swagger_data = SWAGGER if settings.get('api.swagger'): swagger_data.update(read_datafile(settings.get('api.swagger'))) config.registry.settings['api_specs'] = swagger_data config.add_route('cornice_swagger.open_api_path', '/swagger.json') config.add_route('health', '/health') config.add_route('self.schema', '/release-schema.json') config.cornice_enable_openapi_explorer(api_explorer_path='/swagger.ui') config.include('.models') config.add_renderer('simplejson', JSON(serializer=simplejson.dumps)) config.add_request_method(release_package, name='release_package') config.add_request_method(record_package, name='record_package') config.registry.page_size = int(settings.get('api.page_size', 100)) config.registry.publisher = read_datafile( settings.get('api.publisher')) config.registry.schema = read_datafile(settings.get('api.schema')) config.registry.merge_rules = get_merge_rules( settings.get('api.schema')) BASE['extensions'] = settings.get('api.extensions', '').split() config.registry.models = { 'Release': config.registry.schema, 'Record': RECORD } config.set_authorization_policy(ACLAuthorizationPolicy()) tokens = [t.strip() for t in settings.get('api.tokens', '').split(',')] if tokens: config.registry.tokens = frozenset(tokens) config.set_authentication_policy( BasicAuthAuthenticationPolicy(check_credentials)) config.registry.validator = None if settings.get('api.force_validation', False): config.registry.validator = fastjsonschema.compile( config.registry.schema) apps = settings.get('apps', '').split(',') for pname in apps: if not pname: continue try: app = getattr(config.maybe_dotted(pname), 'includeme', '') if app: app(config) logger.info(f"Installed app {pname}") except KeyError as e: logger.error( f"Unable to load {pname} plugin. Error: {repr(e)}") config.scan() return config.make_wsgi_app()
def includeme(config): if auth_activated(config.registry): logger.debug("basic authentication is activated.") # Security policies for basic auth authn_policy = BasicAuthAuthenticationPolicy(check=groupfinder, realm="Birdhouse") authz_policy = ACLAuthorizationPolicy() config.set_authentication_policy(authn_policy) config.set_authorization_policy(authz_policy) config.set_root_factory(root_factory) config.add_request_method(_get_username, 'username', reify=True) config.add_request_method(_get_password, 'password', reify=True)
def create_authentication( settings: Dict[str, Any]) -> MultiAuthenticationPolicy: timeout = settings.get("authtkt_timeout") timeout = None if timeout is None or timeout.lower() == "none" else int( timeout) reissue_time = settings.get("authtkt_reissue_time") reissue_time = None if reissue_time is None or reissue_time.lower( ) == "none" else int(reissue_time) max_age = settings.get("authtkt_max_age") max_age = None if max_age is None or max_age.lower() == "none" else int( max_age) http_only = settings.get("authtkt_http_only", "True") http_only = http_only.lower() in ("true", "yes", "1") secure = settings.get("authtkt_secure", "True") secure = secure.lower() in ("true", "yes", "1") samesite = settings.get("authtkt_samesite", "Lax") secret = settings["authtkt_secret"] basicauth = settings.get("basicauth", "False").lower() in ("true", "yes", "1") if len(secret) < 64: raise Exception( '"authtkt_secret should be at least 64 characters.' "See https://docs.pylonsproject.org/projects/pyramid/en/latest/api/session.html" ) policies = [] url_authentication_policy = UrlAuthenticationPolicy( settings.get("urllogin", {}).get("aes_key"), defaultgroupsfinder, ) policies.append(url_authentication_policy) cookie_authentication_policy = AuthTktAuthenticationPolicy( secret, callback=defaultgroupsfinder, cookie_name=settings["authtkt_cookie_name"], samesite=None if samesite == "" else samesite, timeout=timeout, max_age=max_age, reissue_time=reissue_time, hashalg="sha512", http_only=http_only, secure=secure, ) policies.append(cookie_authentication_policy) if basicauth: basic_authentication_policy = BasicAuthAuthenticationPolicy( c2cgeoportal_check) policies.append(basic_authentication_policy) return MultiAuthenticationPolicy(policies)
def setUp(self): settings = { 'pyramlson.apidef_path': os.path.join(DATA_DIR, 'test-api.raml'), } auth_policy = BasicAuthAuthenticationPolicy(dummy_check, 'TEST REALM') self.config = testing.setUp(settings=settings) self.config.set_authorization_policy(ACLAuthorizationPolicy()) self.config.set_authentication_policy(auth_policy) self.config.include('pyramlson') self.config.scan('.resource') from webtest import TestApp self.testapp = TestApp(self.config.make_wsgi_app())
def create_authentication(settings): timeout = settings.get("authtkt_timeout", None) timeout = None if timeout is None else int(timeout) cookie_authentication_policy = AuthTktAuthenticationPolicy( settings["authtkt_secret"], callback=defaultgroupsfinder, cookie_name=settings["authtkt_cookie_name"], timeout=timeout, max_age=timeout, hashalg="sha512", http_only=True, ) basic_authentication_policy = BasicAuthAuthenticationPolicy(c2cgeoportal_check) policies = [cookie_authentication_policy, basic_authentication_policy] return MultiAuthenticationPolicy(policies)
def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ read_users(settings['auth.file']) config = Configurator( settings=settings, authentication_policy=BasicAuthAuthenticationPolicy( auth_check, __name__), authorization_policy=ACLAuthorizationPolicy(), root_factory=Root, ) config.add_request_method(request_params, 'params', reify=True) config.add_subscriber(new_request_subscriber, NewRequest) config.add_subscriber(add_logging_context, ContextFound) config.include('pyramid_exclog') config.add_route('status', '/') config.add_route('register', '/register') config.add_route('upload', '/upload') config.add_route('upload_file', '/upload/{doc_id}') config.add_route('get', '/get/{doc_id}') config.scan(ignore='openprocurement.documentservice.tests') config.registry.signer = signer = Signer( settings.get('dockey', '').decode('hex')) config.registry.dockey = dockey = signer.hex_vk()[:8] verifier = Verifier(signer.hex_vk()) config.registry.dockeyring = dockeyring = {dockey: verifier} dockeys = settings.get( 'dockeys') if 'dockeys' in settings else Signer().hex_vk() for key in dockeys.split('\0'): dockeyring[key[:8]] = Verifier(key) config.registry.keyring = keyring = {dockey: verifier} apikeys = settings.get( 'apikeys') if 'apikeys' in settings else Signer().hex_vk() for key in apikeys.split('\0'): keyring[key[:8]] = Verifier(key) config.registry.apikey = key[:8] config.registry.upload_host = settings.get('upload_host') config.registry.get_host = settings.get('get_host') # search for storage storage = settings.get('storage') for entry_point in iter_entry_points( 'openprocurement.documentservice.plugins', storage): plugin = entry_point.load() config.registry.storage = plugin(config) return config.make_wsgi_app()
def __init__(self, secret, realm='Realm', hardcoded=()): """ We need to initialise variables here for both forms of auth which we're planning on using. :param secret: A hashing secret for AuthTkt, which should be generated outside the Pyhton process. :param realm: The Basic Auth realm which is probably set to eos_db. :param hardcoded: Triplets of user:password:group that should not be looked up in the database. """ self.hardcoded = {x[0]: (x[1], x[2]) for x in hardcoded} #DELETE ME #self.check = check # Password check routine passed to the constructor. #self.realm = realm # Basic Auth realm. # Now initialise both Auth Policies. AuthTkt has sha256 specified in # place of the default MD5 in order to suppress warnings about # security. self.bap = BasicAuthAuthenticationPolicy(check=self.passwordcheck, realm=realm) self.tap = AuthTktAuthenticationPolicy(secret=secret, callback=self.groupfinder, cookie_name='auth_tkt', hashalg='sha256')
def setUp(self): def check_cred(username, *args, **kwargs): return [username] @implementer(IAuthorizationPolicy) class AuthorizationPolicy(object): def permits(self, context, principals, permission): return permission in principals self.config = testing.setUp() self.config.include('cornice') self.config.add_route('noservice', '/noservice') self.config.set_authorization_policy(AuthorizationPolicy()) self.config.set_authentication_policy( BasicAuthAuthenticationPolicy(check_cred)) self.config.set_default_permission('readwrite') self.config.scan('cornice.tests.test_cors') self.app = TestApp(CatchErrors(self.config.make_wsgi_app()))
def includeme(config): config.include('pyramid_contextauth') tkt_policy = AuthTktAuthenticationPolicy('secret') config.register_authentication_policy( tkt_policy, Context1, ) config.register_authentication_policy( BasicAuthAuthenticationPolicy('realm'), Context2, ) config.register_authentication_policy(Context345Policy(), (Context3, Context4)) config.register_authentication_policy(LocationAwarePolicy(), Root) config.commit()
def includeme(config): """ For inclusion by Pyramid. """ config.add_request_method(get_user, str('user'), reify=True) config.add_request_method(get_acls, str('acls'), reify=True) config.add_request_method(get_settings, str('settings'), reify=True) settings = config.registry.settings authn_policy = PluginAuthenticationPolicy( SessionAuthenticationPolicy(callback=find_princs), { '/dav': DigestAuthenticationPolicy( settings.get('netprofile.auth.secret'), find_princs_digest, realm=settings.get('netprofile.auth.digest.realm', 'NetProfile UI'), check_timestamp=asbool( settings.get('netprofile.auth.digest.check_timestamp', 'true')), timestamp_max_ahead=int( settings.get('netprofile.auth.digest.timestamp_max_ahead', 5)), timestamp_max_behind=int( settings.get('netprofile.auth.digest.timestamp_max_behind', 120))), '/api': BasicAuthAuthenticationPolicy( find_princs_basic, settings.get('netprofile.auth.rpc_realm', 'NetProfile RPC'), settings.get('netprofile.debug')) }) authz_policy = ACLAuthorizationPolicy() config.set_authorization_policy(authz_policy) config.set_authentication_policy(authn_policy) config.add_subscriber(_auth_to_db, ContextFound) config.add_subscriber(_check_session, PluginPolicySelected)
def make_app(server_config): config = Configurator(settings=server_config, root_factory=APIFactory, default_permission="access") config.include("pyramid_jinja2") def check_function(username, password, request): if (password == server_config["admin_secret"] and username == server_config["admin_user"]): return "admin", username return None authn_policy = BasicAuthAuthenticationPolicy(check_function, realm="ChannelStream") authz_policy = ACLAuthorizationPolicy() config.set_authentication_policy(authn_policy) config.set_authorization_policy(authz_policy) json_renderer = JSON(serializer=json.dumps, indent=4) json_renderer.add_adapter(datetime.datetime, datetime_adapter) json_renderer.add_adapter(uuid.UUID, uuid_adapter) config.add_renderer("json", json_renderer) config.add_subscriber("channelstream.subscribers.handle_new_request", "pyramid.events.NewRequest") config.add_request_method("channelstream.utils.handle_cors", "handle_cors") config.include("channelstream.wsgi_views") config.scan("channelstream.wsgi_views.server") config.scan("channelstream.wsgi_views.error_handlers") config.scan("channelstream.events") config.include("pyramid_apispec.views") config.pyramid_apispec_add_explorer( spec_route_name="openapi_spec", script_generator="channelstream.utils:swagger_ui_script_template", permission=NO_PERMISSION_REQUIRED, ) app = config.make_wsgi_app() return app
def __init__(self, secret, realm='Realm', hardcoded=()): """ We need to initialise variables here for both forms of auth which we're planning on using. :param secret: A hashing secret for AuthTkt, which should be generated outside the Pyhton process. :param realm: The Basic Auth realm which is probably set to eos_db. :param hardcoded: Triplets of user:password:group that should not be looked up in the database. """ self.hardcoded = { x[0]: (x[1],x[2]) for x in hardcoded } #DELETE ME #self.check = check # Password check routine passed to the constructor. #self.realm = realm # Basic Auth realm. # Now initialise both Auth Policies. AuthTkt has sha256 specified in # place of the default MD5 in order to suppress warnings about # security. self.bap = BasicAuthAuthenticationPolicy(check=self.passwordcheck, realm=realm) self.tap = AuthTktAuthenticationPolicy(secret=secret, callback=self.groupfinder, cookie_name='auth_tkt', hashalg='sha256')
def create_authentication(settings): timeout = settings.get("authtkt_timeout") timeout = None if timeout is None else int(timeout) reissue_time = settings.get("reissue_time") reissue_time = None if reissue_time is None else int(reissue_time) http_only = settings.get("authtk_http_only") http_only = True if http_only is None else http_only != "False" secure = settings.get("authtk_secure") secure = True if secure is None else secure != "False" cookie_authentication_policy = AuthTktAuthenticationPolicy( settings["authtkt_secret"], callback=defaultgroupsfinder, cookie_name=settings["authtkt_cookie_name"], timeout=timeout, max_age=timeout, reissue_time=reissue_time, hashalg="sha512", http_only=http_only, secure=secure, ) basic_authentication_policy = BasicAuthAuthenticationPolicy( c2cgeoportal_check) policies = [cookie_authentication_policy, basic_authentication_policy] return MultiAuthenticationPolicy(policies)
def create_authentication(settings): timeout = settings.get("authtkt_timeout") timeout = None if timeout is None else int(timeout) reissue_time = settings.get("reissue_time") reissue_time = None if reissue_time is None else int(reissue_time) http_only = settings.get("authtkt_http_only", "True") http_only = http_only.lower() in ("true", "yes", "1") secure = settings.get("authtkt_secure", "True") secure = secure.lower() in ("true", "yes", "1") cookie_authentication_policy = AppAwareAuthTktAuthenticationPolicy( settings["authtkt_secret"], callback=defaultgroupsfinder, cookie_name=settings["authtkt_cookie_name"], timeout=timeout, max_age=timeout, reissue_time=reissue_time, hashalg="sha512", http_only=http_only, secure=secure, parent_domain=True) basic_authentication_policy = BasicAuthAuthenticationPolicy( c2cgeoportal_check) policies = [cookie_authentication_policy, basic_authentication_policy] return MultiAuthenticationPolicy(policies)
def main(settings): """Create and return a WSGI application.""" config = Configurator() config.registry.engine = init_db(settings) def db(request): connection = request.registry.engine.connect() transaction = connection.begin() def cleanup(request): if request.exception is not None: transaction.rollback() else: transaction.commit() connection.close() request.add_finished_callback(cleanup) return connection config.add_request_method(db, reify=True) # Configure authentication / authorization authn_policy = BasicAuthAuthenticationPolicy(check_credentials) config.set_authentication_policy(authn_policy) config.set_authorization_policy(ACLAuthorizationPolicy()) config.set_root_factory(lambda request: Root()) config.add_forbidden_view(forbidden_view) config.add_view(view=error_view, context=Exception, renderer="json") config.add_static_view(name="static", path="../../queryduck-web/static") config.add_route("post_query", "/{target}/query", request_method="POST") config.add_route("get_query", "/{target}/query", request_method="GET") config.add_route("get_statements", "/statements", request_method="GET") config.add_route("submit_transaction", "/statements/transaction", request_method="POST") config.add_route("get_statement", "/statements/{reference}", request_method="GET") config.add_route("create_statements", "/statements", request_method="POST") config.add_route("create_volume", "/volumes/{reference}", request_method="PUT") config.add_route("delete_volume", "/volumes/{reference}", request_method="DELETE") config.add_route("get_volume", "/volumes/{reference}") config.add_route("list_volumes", "/volumes") config.add_route("create_blob", "/blobs/new", request_method="POST") config.add_route("get_blob", "/blobs/{reference}") config.add_route("list_blobs", "/blobs") config.add_route("list_volume_files", "/volumes/{volume_reference}/files", request_method="GET") config.add_route( "mutate_volume_files", "/volumes/{volume_reference}/files", request_method="POST", ) config.add_route( "get_volume_file", "/volumes/{volume_reference}/files/{file_path}", request_method="GET", ) config.scan(".controllers") config.scan(".transaction.controllers") config.scan(".storage.controllers") app = config.make_wsgi_app() return app
def __init__(self, check=None): if check is None: check = AuthClientPolicy.check self._basic_auth_policy = BasicAuthAuthenticationPolicy(check=check)
class HybridAuthenticationPolicy(): """ HybridAuthenticationPolicy. Called in the same way as other auth policies, but wraps Basic and AuthTkt. This policy also caches password lookups by remembering them in the request object. """ def __init__(self, secret, realm='Realm', hardcoded=()): """ We need to initialise variables here for both forms of auth which we're planning on using. :param secret: A hashing secret for AuthTkt, which should be generated outside the Pyhton process. :param realm: The Basic Auth realm which is probably set to eos_db. :param hardcoded: Triplets of user:password:group that should not be looked up in the database. """ self.hardcoded = { x[0]: (x[1],x[2]) for x in hardcoded } #DELETE ME #self.check = check # Password check routine passed to the constructor. #self.realm = realm # Basic Auth realm. # Now initialise both Auth Policies. AuthTkt has sha256 specified in # place of the default MD5 in order to suppress warnings about # security. self.bap = BasicAuthAuthenticationPolicy(check=self.passwordcheck, realm=realm) self.tap = AuthTktAuthenticationPolicy(secret=secret, callback=self.groupfinder, cookie_name='auth_tkt', hashalg='sha256') #Utility functions to interact with eos_db.server def groupfinder(self, username, request): """ Return the user group (just one) associated with the user. This uses a server function to check which group a user has been associated with. This provides the standard callback wanted by AuthTktAuthenticationPolicy. An alternative would be to encode the groups in the Tkt. The mapping of groups to actual capabilities is stored in views.PermissionsMap """ group = server.get_user_group(username) if group: return ["group:" + str(group)] def passwordcheck(self, login, password, request): """Password checking callback. """ hc = self.hardcoded if login in hc and hc[login][0] == password: return ['group:' + hc[login][1]] elif server.check_password(login, password): user_group = server.get_user_group(login) log.debug("Found user group %s" % user_group) return ['group:' + user_group] else: log.debug("Password chack failed for user %s" % login) return None def unauthenticated_userid(self, request): """ Return the userid parsed from the auth ticket cookie. If this does not exist, then check the basic auth header, and return that, if it exists. """ #Allow forcing the auth_tkt cookie. Helpful for JS calls. #Maybe move this to a callback so it only ever happens once? if request.headers.get('auth_tkt'): request.cookies['auth_tkt'] = request.headers['auth_tkt'] #Or, surely: return ( self.tap.unauthenticated_userid(request) or self.bap.unauthenticated_userid(request) ) def authenticated_userid(self, request): """ Return the Auth Ticket user ID if that exists. If not, then check for a user ID in Basic Auth. """ try: return request.cached_authenticated_userid except: #Proceed to look-up then pass #Allow forcing the auth_tkt cookie. if request.headers.get('auth_tkt'): request.cookies['auth_tkt'] = request.headers['auth_tkt'] request.cached_authenticated_userid = ( self.tap.unauthenticated_userid(request) or self.bap.unauthenticated_userid(request) ) return request.cached_authenticated_userid def effective_principals(self, request): """ Returns the list of effective principles from the auth policy under which the user is currently authenticated. Auth ticket takes precedence. """ try: return request.cached_effective_principals except: #Proceed to look-up then pass #Allow forcing the auth_tkt cookie. if request.headers.get('auth_tkt'): request.cookies['auth_tkt'] = request.headers['auth_tkt'] userid = self.tap.authenticated_userid(request) if userid: request.cached_effective_principals = self.tap.effective_principals(request) else: request.cached_effective_principals = self.bap.effective_principals(request) return request.cached_effective_principals def remember(self, request, principal, **kw): """Causes the session info to be remembered by passing the appropriate AuthTkt into the response. """ # We always rememeber by creating an AuthTkt, but only if there is something to remember # and if the user was not in the hard-coded list. if principal and principal not in self.hardcoded: return self.tap.remember(request, principal, **kw) else: return () def forget(self, request): """ Forget both sessions. """ return self.bap.forget(request) + self.tap.forget(request) def get_forbidden_view(self, request): """ Fire a 401 when authentication needed. """ # FIXME - this doesn't distinguish between unauthenticated and # unauthorized. Should it? if request.headers.get('auth_tkt'): return HTTPRequestTimeout() #print ("Access Forbidden") response = HTTPUnauthorized() response.headers.extend(self.bap.forget(request)) return response
def __init__(self): BasicAuthAuthenticationPolicy.__init__( self, check=check_auth, )
def main(global_config, **settings): Service.cors_origins = ('*', ) settings = settings_expandvars(settings) config = Configurator(settings=settings, root_factory=RootFactory) config.include("cornice") # Redirect to the current version of the API if the prefix isn't used. config.add_route(name='redirect_to_version', pattern='/{path:(?!%s).*}' % API_VERSION) config.add_view(view=redirect_to_version, route_name='redirect_to_version') config.route_prefix = '/%s' % API_VERSION # Permission management policies = [ BasicAuthAuthenticationPolicy(check_credentials), HawkAuthenticationPolicy(decode_hawk_id=get_credentials), ] authn_policy = MultiAuthenticationPolicy(policies) # Unauthorized view config.add_forbidden_view(forbidden_view) # Global permissions model_creators = settings.get("daybed.can_create_model", "Everyone") token_creators = settings.get("daybed.can_create_token", "Everyone") token_managers = settings.get("daybed.can_manage_token", None) authz_policy = DaybedAuthorizationPolicy( model_creators=build_list(model_creators), token_creators=build_list(token_creators), token_managers=build_list(token_managers), ) config.set_authentication_policy(authn_policy) config.set_authorization_policy(authz_policy) # We need to scan AFTER setting the authn / authz policies config.scan("daybed.views") # Attach the token to the request, coming from Pyramid as userid def get_credentials_id(request): try: credentials_id, _ = get_credentials(request, request.authenticated_userid) return credentials_id except ValueError: return None config.add_request_method(get_credentials_id, 'credentials_id', reify=True) # Events # Helper for notifying events def notify(request, event, *args): klass = config.maybe_dotted('daybed.events.' + event) event = klass(*(args + (request, ))) request.registry.notify(event) config.add_request_method(notify, 'notify') # Backend config.registry.tokenHmacKey = settings['daybed.tokenHmacKey'] # backend initialisation backend_class = config.maybe_dotted(settings['daybed.backend']) config.registry.backend = backend_class.load_from_config(config) # Indexing # Connect client to hosts in conf index_hosts = build_list( settings.get('elasticsearch.hosts', "localhost:9200")) indices_prefix = settings.get('elasticsearch.indices_prefix', 'daybed_') config.registry.index = index = indexer.ElasticSearchIndexer( index_hosts, indices_prefix) # Suscribe index methods to API events config.add_subscriber(index.on_model_created, events.ModelCreated) config.add_subscriber(index.on_model_updated, events.ModelUpdated) config.add_subscriber(index.on_model_deleted, events.ModelDeleted) config.add_subscriber(index.on_record_created, events.RecordCreated) config.add_subscriber(index.on_record_updated, events.RecordUpdated) config.add_subscriber(index.on_record_deleted, events.RecordDeleted) # Renderers # Force default accept header to JSON def add_default_accept(event): json_mime = 'application/json' accept = event.request.headers.get('Accept', json_mime) if json_mime in accept: accept = json_mime event.request.headers["Accept"] = accept config.add_subscriber(add_default_accept, NewRequest) # JSONP config.add_renderer('jsonp', JSONP(param_name='callback')) # Geographic data renderer config.add_renderer('geojson', GeoJSON()) # Requests attachments def attach_objects_to_request(event): event.request.db = config.registry.backend event.request.index = config.registry.index http_scheme = event.request.registry.settings.get('daybed.http_scheme') if http_scheme: event.request.scheme = http_scheme config.add_subscriber(attach_objects_to_request, NewRequest) # Plugins try: config.include("daybed_browserid") except ImportError: pass return config.make_wsgi_app()
def create_authentication( settings: Dict[str, Any]) -> MultiAuthenticationPolicy: """Create all the authentication policies.""" timeout = settings.get("authtkt_timeout") timeout = None if timeout is None or timeout.lower() == "none" else int( timeout) reissue_time = settings.get("authtkt_reissue_time") reissue_time = None if reissue_time is None or reissue_time.lower( ) == "none" else int(reissue_time) max_age = settings.get("authtkt_max_age") max_age = None if max_age is None or max_age.lower() == "none" else int( max_age) http_only = settings.get("authtkt_http_only", "True") http_only = http_only.lower() in ("true", "yes", "1") secure = settings.get("authtkt_secure", "True") secure = secure.lower() in ("true", "yes", "1") samesite = settings.get("authtkt_samesite", "Lax") secret = settings["authtkt_secret"] basicauth = settings.get("basicauth", "False").lower() in ("true", "yes", "1") if len(secret) < 64: raise Exception( '"authtkt_secret should be at least 64 characters.' "See https://docs.pylonsproject.org/projects/pyramid/en/latest/api/session.html" ) policies = [] policies.append( UrlAuthenticationPolicy( settings.get("urllogin", {}).get("aes_key"), defaultgroupsfinder, )) policies.append( AuthTktAuthenticationPolicy( secret, callback=defaultgroupsfinder, cookie_name=settings["authtkt_cookie_name"], samesite=None if samesite == "" else samesite, timeout=timeout, max_age=max_age, reissue_time=reissue_time, hashalg="sha512", http_only=http_only, secure=secure, )) policies.append(OAuth2AuthenticationPolicy()) if basicauth: if settings["authentication"].get("two_factor", False): LOG.warning( "Basic auth and tow factor auth should not be enable toogether, " "you should use OAuth2 instead of Basic auth") basic_authentication_policy = BasicAuthAuthenticationPolicy( c2cgeoportal_check) policies.append(basic_authentication_policy) # Consider empty string as not configured if "DEV_LOGINNAME" in os.environ and os.environ["DEV_LOGINNAME"]: policies.append(DevAuthenticationPolicy()) return MultiAuthenticationPolicy(policies)
def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ authn_policy = BasicAuthAuthenticationPolicy( groupfinder, realm=settings['reliquary.realm'], debug=settings['pyramid.debug']) authz_policy = ACLAuthorizationPolicy() engine = engine_from_config(settings, 'sqlalchemy.') DBSession.configure(bind=engine) Base.metadata.bind = engine config = Configurator( settings=settings, authentication_policy=authn_policy, authorization_policy=authz_policy, root_factory=Root, ) config.include('pyramid_chameleon') #config.add_static_view('static', 'static', cache_max_age=3600) # ui config.add_route('home', '/api/v1/', request_method='GET') # basic api config.add_route('put_relic', '/api/v1/raw/{channel}/{index}/{relic_name}', request_method='PUT') config.add_route('get_relic', '/api/v1/raw/{channel}/{index}/{relic_name}', request_method='GET') # autoindex (nginx autogenerate index page compatible) config.add_route('autoindex', '/api/v1/autoindex/{channel}/{index}/', request_method='GET') # python package index (PEP-503 compliant) # PROXY config.add_route('pypi_proxy_simple_package', '/api/v1/python/proxy/{channel}/{index}/simple/{package}/', request_method='GET') config.add_route('pypi_proxy_simple', '/api/v1/python/proxy/{channel}/{index}/simple/', request_method='GET') # just to keep compat with pypi.python.org package locations -- calls out # to upstream or to get_relic route config.add_route('pypi_proxy_package', '/api/v1/python/proxy/{channel}/{index}/packages/{parta}/{partb}/{hash}/{package}', request_method='GET') # SELF-HOSTED config.add_route('pypi_simple_package', '/api/v1/python/{channel}/{index}/simple/{package}/', request_method='GET') config.add_route('pypi_simple', '/api/v1/python/{channel}/{index}/simple/', request_method='GET') # commonjs registry (http://wiki.commonjs.org/wiki/Packages/Registry) # npmjs.org is historically based on this, and npm should be compatible # PROXY # these mostly try to replicate the npmjs registry public api in function # npmjs registry api: https://github.com/npm/registry/blob/master/docs/REGISTRY-API.md # set the registry used with npm-config (.npmrc files): https://docs.npmjs.com/files/npmrc # http://registry.npmjs.org/<name>/<version> config.add_route('commonjs_proxy_registry_package_version', '/api/v1/commonjs/proxy/{channel}/{index}/{package}/{version}/', request_method='GET') # http://registry.npmjs.org/<name>/ config.add_route('commonjs_proxy_registry_package_root', '/api/v1/commonjs/proxy/{channel}/{index}/{package}/', request_method='GET') # http://registry.npmjs.org/-/all config.add_route('commonjs_proxy_registry_root', '/api/v1/commonjs/proxy/{channel}/{index}/', request_method='GET') # http://registry.npmjs.org/-/<package>-<version>.tgz config.add_route('commonjs_proxy_package', '/api/v1/commonjs/proxy/package/{channel}/{index}/{package}/{version}', request_method='GET') # SELF HOSTED config.add_route('commonjs_registry_root', '/api/v1/commonjs/{channel}/{index}/', request_method='GET') config.add_route('commonjs_registry_package_root', '/api/v1/commonjs/{channel}/{index}/{package}/', request_method='GET') config.add_route('commonjs_registry_package_version', '/api/v1/commonjs/{channel}/{index}/{package}/{version}/', request_method='GET') # debian repository (https://wiki.debian.org/RepositoryFormat) # additional info: http://www.ibiblio.org/gferg/ldp/giles/repository/repository-2.html # these are the minimum required paths # example sources.list entry: deb http://127.0.0.1/api/v1/debian/wildcard trusty main config.add_route('debian_distrelease', '/api/v1/debian/{channel}/dist/{index}/Release', request_method='GET') config.add_route('debian_archrelease', '/api/v1/debian/{channel}/dist/{index}/main/binary-{arch}/Release', request_method='GET') config.add_route('debian_archpackages', '/api/v1/debian/{channel}/dist/{index}/main/binary-{arch}/Packages', request_method='GET') config.add_route('debian_archpackagesgz', '/api/v1/debian/{channel}/dist/{index}/main/binary-{arch}/Packages.gz', request_method='GET') config.add_route('debian_archpackagesbz2', '/api/v1/debian/{channel}/dist/{index}/main/binary-{arch}/Packages.bz2', request_method='GET') config.add_route('debian_poolpackage', '/api/v1/debian/{channel}/pool/{index}/{relic_name}', request_method='GET') # additional paths that could be just a directory listing of some sort (like autoindex) config.add_route('debian_archindex', '/api/v1/debian/{channel}/dist/{index}/main/binary-{arch}/', request_method='GET') config.add_route('debian_compindex', '/api/v1/debian/{channel}/dist/{index}/main/', request_method='GET') config.add_route('debian_distindex', '/api/v1/debian/{channel}/dist/{index}/', request_method='GET') config.add_route('debian_distrootindex', '/api/v1/debian/{channel}/dist/', request_method='GET') config.add_route('debian_channelindex', '/api/v1/debian/{channel}/', request_method='GET') config.add_route('debian_pooldistindex', '/api/v1/debian/{channel}/pool/{index}/', request_method='GET') config.add_route('debian_poolrootindex', '/api/v1/debian/{channel}/pool/', request_method='GET') config.add_notfound_view(notfound, append_slash=True) config.scan('.views') return config.make_wsgi_app()
class AuthClientPolicy: """ An authentication policy for registered AuthClients Authentication for a request to API routes with HTTP Basic Authentication credentials that represent a registered AuthClient with grant type of ``client_credentials`` in the db. Authentication can be of two types: * The client itself: Some endpoints allow an authenticated auth_client to take action on users within its authority, such as creating a user or adding a user to a group. In this case, assuming credentials are valid, the request will be authenticated, but no ``authenticated_userid`` (and thus no request.user) will be set * A user within the client's associated authority: If an HTTP ``X-Forwarded-User`` header is present, its value will be treated as a ``userid`` and, if the client credentials are valid _and_ the userid represents an extant user within the client's authority, the request will be authenticated as that user. In this case, ``authenticated_userid`` will be set and there will ultimately be a request.user available. Note: To differentiate between request with a Token-authenticated user and a request with an auth_client forwarded user, the latter has an additional principal, ``client:{client_id}@{authority}`` to mark it as being authenticated on behalf of an auth_client """ def __init__(self, check=None): if check is None: check = AuthClientPolicy.check self._basic_auth_policy = BasicAuthAuthenticationPolicy(check=check) def unauthenticated_userid(self, request): """ Return the forwarded userid or the auth_client's id If a forwarded user header is set, return the ``userid`` (its value) Otherwise return the username parsed from the Basic Auth header :return: :py:attr:`h.models.user.User.userid` or :py:attr:`h.models.auth_client.AuthClient.id` :rtype: str """ forwarded_userid = AuthClientPolicy._forwarded_userid(request) if forwarded_userid is not None: return forwarded_userid # username from BasicAuth header return self._basic_auth_policy.unauthenticated_userid(request) def authenticated_userid(self, request): """ Return any forwarded userid or None Rely mostly on :py:meth:`pyramid.authentication.BasicAuthAuthenticationPolicy.authenticated_userid`, but don't actually return a ``userid`` unless there is a forwarded user header set—the auth client itself is not a "user" Although this looks as if it trusts the return value of :py:meth:`pyramid.authentication.BasicAuthAuthenticationPolicy.authenticated_userid` irrationally, rest assured that :py:meth:`~h.auth.policy.AuthClientPolicy.check` will always be called (via :py:meth:`pyramid.authentication.BasicAuthAuthenticationPolicy.callback`) before any non-None value is returned. :rtype: :py:attr:`h.models.user.User.userid` or ``None`` """ forwarded_userid = AuthClientPolicy._forwarded_userid(request) # only evaluate setting an authenticated_userid if forwarded user is present if forwarded_userid is None: return None # username extracted from BasicAuth header auth_userid = self._basic_auth_policy.unauthenticated_userid(request) # authentication of BasicAuth and forwarded user—this will invoke check callback_ok = self._basic_auth_policy.callback(auth_userid, request) if callback_ok is not None: return (forwarded_userid ) # This should always be a userid, not an auth_client id def effective_principals(self, request): """ Return a list of principals for the request This will concatenate the principals returned by :py:meth:`~h.auth.policy.AuthClientPolicy.check` (which is a list or None) with Pyramid's system principal(s). If :py:meth:`~h.auth.policy.AuthClientPolicy.check` returns None—that is, if authentication is unsuccessful—the returned principals will only contain Pyramid's ``system.Everyone`` principal (and Pyramid will not consider the request as authenticated). :rtype: list ``['system.Everyone']`` concatenated with any principals from a successful authentication """ return self._basic_auth_policy.effective_principals(request) def remember(self, request, userid, **kw): """Not implemented for basic auth client policy.""" return [] def forget(self, request): """Not implemented for basic auth client policy.""" return [] @staticmethod def check(username, password, request): """ Return list of appropriate principals or None if authentication is unsuccessful. Validate the basic auth credentials from the request by matching them to an auth_client record in the DB. If an HTTP ``X-Forwarded-User`` header is present in the request, this represents the intent to authenticate "on behalf of" a user within the auth_client's authority. If this header is present, the user indicated by its value (a :py:attr:`h.models.user.User.userid`) _must_ exist and be within the auth_client's authority, or authentication will fail. :param username: username parsed out of Authorization header (Basic) :param password: password parsed out of Authorization header (Basic) :returns: additional principals for the auth_client or None :rtype: list or None """ client_id = username client_secret = password # validate that the credentials in BasicAuth header # match an AuthClient record in the db client = util.verify_auth_client(client_id, client_secret, request.db) if client is None: return None forwarded_userid = AuthClientPolicy._forwarded_userid(request) if (forwarded_userid is None ): # No forwarded user; set principals for basic auth_client return util.principals_for_auth_client(client) user_service = request.find_service(name="user") try: user = user_service.fetch(forwarded_userid) except ValueError: # raised if userid is invalid format return None # invalid user, so we are failing here if user and user.authority == client.authority: return util.principals_for_auth_client_user(user, client) return None @staticmethod def _forwarded_userid(request): """Return forwarded userid or None""" return request.headers.get("X-Forwarded-User", None)
class AuthClientPolicy(object): """ An authentication policy for registered AuthClients Authentication for a request to API routes with HTTP Basic Authentication credentials that represent a registered AuthClient with grant type of ``client_credentials`` in the db. Authentication can be of two types: * The client itself: Some endpoints allow an authenticated auth_client to take action on users within its authority, such as creating a user or adding a user to a group. In this case, assuming credentials are valid, the request will be authenticated, but no ``authenticated_userid`` (and thus no request.user) will be set * A user within the client's associated authority: If an HTTP ``X-Forwarded-User`` header is present, its value will be treated as a ``userid`` and, if the client credentials are valid _and_ the userid represents an extant user within the client's authority, the request will be authenticated as that user. In this case, ``authenticated_userid`` will be set and there will ultimately be a request.user available. Note: To differentiate between request with a Token-authenticated user and a request with an auth_client forwarded user, the latter has an additional principal, ``client:{client_id}@{authority}`` to mark it as being authenticated on behalf of an auth_client """ def __init__(self, check=None): if check is None: check = AuthClientPolicy.check self._basic_auth_policy = BasicAuthAuthenticationPolicy(check=check) def unauthenticated_userid(self, request): """ Return the forwarded userid or the auth_client's id If a forwarded user header is set, return the ``userid`` (its value) Otherwise return the username parsed from the Basic Auth header :return: :py:attr:`h.models.user.User.userid` or :py:attr:`h.models.auth_client.AuthClient.id` :rtype: str """ forwarded_userid = AuthClientPolicy._forwarded_userid(request) if forwarded_userid is not None: return forwarded_userid # username from BasicAuth header return self._basic_auth_policy.unauthenticated_userid(request) def authenticated_userid(self, request): """ Return any forwarded userid or None Rely mostly on :py:meth:`pyramid.authentication.BasicAuthAuthenticationPolicy.authenticated_userid`, but don't actually return a ``userid`` unless there is a forwarded user header set—the auth client itself is not a "user" Although this looks as if it trusts the return value of :py:meth:`pyramid.authentication.BasicAuthAuthenticationPolicy.authenticated_userid` irrationally, rest assured that :py:meth:`~h.auth.policy.AuthClientPolicy.check` will always be called (via :py:meth:`pyramid.authentication.BasicAuthAuthenticationPolicy.callback`) before any non-None value is returned. :rtype: :py:attr:`h.models.user.User.userid` or ``None`` """ forwarded_userid = AuthClientPolicy._forwarded_userid(request) # only evaluate setting an authenticated_userid if forwarded user is present if forwarded_userid is None: return None # username extracted from BasicAuth header auth_userid = self._basic_auth_policy.unauthenticated_userid(request) # authentication of BasicAuth and forwarded user—this will invoke check callback_ok = self._basic_auth_policy.callback(auth_userid, request) if callback_ok is not None: return ( forwarded_userid ) # This should always be a userid, not an auth_client id def effective_principals(self, request): """ Return a list of principals for the request This will concatenate the principals returned by :py:meth:`~h.auth.policy.AuthClientPolicy.check` (which is a list or None) with Pyramid's system principal(s). If :py:meth:`~h.auth.policy.AuthClientPolicy.check` returns None—that is, if authentication is unsuccessful—the returned principals will only contain Pyramid's ``system.Everyone`` principal (and Pyramid will not consider the request as authenticated). :rtype: list ``['system.Everyone']`` concatenated with any principals from a successful authentication """ return self._basic_auth_policy.effective_principals(request) def remember(self, request, userid, **kw): """Not implemented for basic auth client policy.""" return [] def forget(self, request): """Not implemented for basic auth client policy.""" return [] @staticmethod def check(username, password, request): """ Return list of appropriate principals or None if authentication is unsuccessful. Validate the basic auth credentials from the request by matching them to an auth_client record in the DB. If an HTTP ``X-Forwarded-User`` header is present in the request, this represents the intent to authenticate "on behalf of" a user within the auth_client's authority. If this header is present, the user indicated by its value (a :py:attr:`h.models.user.User.userid`) _must_ exist and be within the auth_client's authority, or authentication will fail. :param username: username parsed out of Authorization header (Basic) :param password: password parsed out of Authorization header (Basic) :returns: additional principals for the auth_client or None :rtype: list or None """ client_id = username client_secret = password # validate that the credentials in BasicAuth header # match an AuthClient record in the db client = util.verify_auth_client(client_id, client_secret, request.db) if client is None: return None forwarded_userid = AuthClientPolicy._forwarded_userid(request) if ( forwarded_userid is None ): # No forwarded user; set principals for basic auth_client return util.principals_for_auth_client(client) user_service = request.find_service(name="user") try: user = user_service.fetch(forwarded_userid) except ValueError: # raised if userid is invalid format return None # invalid user, so we are failing here if user and user.authority == client.authority: return util.principals_for_auth_client_user(user, client) return None @staticmethod def _forwarded_userid(request): """Return forwarded userid or None""" userid = request.headers.get("X-Forwarded-User", None) if userid is not None: # In Python 2 request header values are byte strings, so we need to # decode them to get unicode. # FIXME: Remove this once we've moved to Python 3. userid = pyramid.compat.text_(userid) return userid
def getBasicAuthAuthenticationPolicy(): """Define the authentication policy for a basic auth""" return BasicAuthAuthenticationPolicy( Configuration.get('pyramid_basicauth_check'), debug=Configuration.get('pyramid_authentication_debug'))
def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ load_processing_settings(settings) load_local_settings(settings, settings["appname"]) settings.update({"version": version}) config = Configurator(root_factory=Root, settings=settings) config.set_authorization_policy(ACLAuthorizationPolicy()) config.set_authentication_policy( BasicAuthAuthenticationPolicy(check=groupfinder, )) # set forbidden view to basic auth def forbidden_view(request): resp = HTTPUnauthorized() resp.www_authenticate = 'Basic realm="Thinkhazard"' return resp config.add_forbidden_view(forbidden_view) config.include("pyramid_jinja2") config.include("papyrus") config.include("thinkhazard.session") config.add_tween("thinkhazard.tweens.notmodified_tween_factory", over=MAIN) config.add_static_view("static", "static", cache_max_age=3600) config.add_static_view("lib", settings.get("node_modules"), cache_max_age=86000) config.add_translation_dirs("thinkhazard:locale") config.set_locale_negotiator("thinkhazard.i18n.custom_locale_negotiator") config.add_route("healthcheck", "/healthcheck") if settings["appname"] == "public": config.include(add_public_routes) config.add_route("sitemap", "/sitemap.xml") if settings["appname"] == "admin": # Celery from thinkhazard.celery import app as celery_app config.add_request_method(lambda x: celery_app, "celery_app", reify=True) config.set_default_permission("admin") config.include(add_public_routes, route_prefix="preview") config.add_route("admin_index", "/") config.add_route("admin_add_task", "/addtask") config.add_route("admin_technical_rec", "/technical_rec") config.add_route("admin_technical_rec_new", "/technical_rec/new") config.add_route("admin_technical_rec_edit", "/technical_rec/{id:\d+}") config.add_route("admin_technical_rec_delete", "/technical_rec/{id:\d+}/delete") config.add_route("admin_admindiv_hazardsets", "/admindiv_hazardsets") config.add_route("admin_admindiv_hazardsets_export", "/admindiv_hazardsets_export") config.add_route( "admin_admindiv_hazardsets_hazardtype", "/admindiv_hazardsets/{hazardtype:([A-Z]{2})}", ) config.add_route("admin_climate_rec", "/climate_rec") config.add_route("admin_climate_rec_hazardtype", "/climate_rec/{hazard_type:([A-Z]{2})}") config.add_route("admin_climate_rec_new", "/climate_rec/{hazard_type:([A-Z]{2})}/new") config.add_route("admin_climate_rec_edit", "/climate_rec/{id:\d+}") config.add_route("admin_climate_rec_delete", "/climate_rec/{id:\d+}/delete") config.add_route("admin_hazardcategories", "/hazardcategories") config.add_route( "admin_hazardcategory", "/hazardcategory/{hazard_type:([A-Z]{2})}" "/{hazard_level:([A-Z]{3})}", ) config.add_route("admin_hazardsets", "/hazardsets") config.add_route("admin_hazardset", "/hazardset/{hazardset}") config.add_route("admin_contacts", "/contacts") config.add_route("admin_contact_new", "/contact/new") config.add_route("admin_contact_edit", "/contact/{id:\d+}") config.add_route("admin_contact_delete", "/contact/{id:\d+}/delete") config.add_route("admin_contact_admindiv_hazardtype_association", "/contact/CAdHt_form") config.add_renderer("geojson", GeoJSON()) config.add_renderer("csv", "thinkhazard.renderers.CSVRenderer") config.add_request_method( lambda r: S3Helper(r.registry.settings), "s3_helper", property=True, reify=True, ) scan_ignore = [] if settings["appname"] != "public": scan_ignore.append("thinkhazard.views.sitemap") if settings["appname"] != "admin": scan_ignore.append("thinkhazard.views.admin") config.scan(ignore=scan_ignore) return config.make_wsgi_app()