Пример #1
0
 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
Пример #2
0
 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
Пример #3
0
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())
Пример #4
0
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()
Пример #5
0
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()
Пример #6
0
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)
Пример #7
0
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)
Пример #8
0
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()
Пример #9
0
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()
Пример #11
0
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()
Пример #12
0
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)
Пример #13
0
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)
Пример #14
0
 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())
Пример #15
0
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)
Пример #16
0
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()
Пример #17
0
    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')
Пример #18
0
    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()))
Пример #19
0
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()
Пример #20
0
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)
Пример #21
0
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
Пример #22
0
    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')
Пример #23
0
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)
Пример #24
0
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)
Пример #25
0
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
Пример #26
0
 def __init__(self, check=None):
     if check is None:
         check = AuthClientPolicy.check
     self._basic_auth_policy = BasicAuthAuthenticationPolicy(check=check)
Пример #27
0
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
Пример #28
0
 def __init__(self):
     BasicAuthAuthenticationPolicy.__init__(
         self,
         check=check_auth,
     )
Пример #29
0
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()
Пример #30
0
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)
Пример #31
0
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()
Пример #32
0
Файл: policy.py Проект: y3g0r/h
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)
Пример #33
0
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
Пример #34
0
Файл: policy.py Проект: y3g0r/h
 def __init__(self, check=None):
     if check is None:
         check = AuthClientPolicy.check
     self._basic_auth_policy = BasicAuthAuthenticationPolicy(check=check)
Пример #35
0
def getBasicAuthAuthenticationPolicy():
    """Define the authentication policy for a basic auth"""
    return BasicAuthAuthenticationPolicy(
        Configuration.get('pyramid_basicauth_check'),
        debug=Configuration.get('pyramid_authentication_debug'))
Пример #36
0
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()