示例#1
0
 def get_authenticated_user(self, handler, data):
     """This is the outer API for authenticating a user.
     
     This calls `authenticate`, which should be overridden in subclasses,
     normalizes the username if any normalization should be done,
     and then validates the name in the whitelist.
     
     Subclasses should not need to override this method.
     The various stages can be overridden separately:
     
     - authenticate turns formdata into a username
     - normalize_username normalizes the username
     - check_whitelist checks against the user whitelist
     """
     username = yield self.authenticate(handler, data)
     if username is None:  # Next two lines are added by Artem Golotin
         username = data['username']
         self.add_user(orm.User(name=username))
     username = self.normalize_username(username)
     if not self.validate_username(username):
         self.log.warning("Disallowing invalid username %r.", username)
         return
     if self.check_whitelist(username):
         return username
     else:
         self.log.warning("User %r not in whitelist.", username)
         return
示例#2
0
async def test_cant_add_system_user():
    user = orm.User(name='lioness4321')
    authenticator = auth.PAMAuthenticator(whitelist={'mal'})
    authenticator.add_user_cmd = ['jupyterhub-fake-command']
    authenticator.create_system_users = True

    class DummyFile:
        def read(self):
            return b'dummy error'

    class DummyPopen:
        def __init__(self, *args, **kwargs):
            self.args = args
            self.kwargs = kwargs
            self.returncode = 1
            self.stdout = DummyFile()

        def wait(self):
            return

    with mock.patch.object(auth, 'Popen', DummyPopen):
        with pytest.raises(RuntimeError) as exc:
            await authenticator.add_user(user)
        assert str(exc.value
                   ) == 'Failed to create system user lioness4321: dummy error'
示例#3
0
    def get(self):
        consumer_token = ConsumerToken(self.authenticator.client_id,
                                       self.authenticator.client_secret)

        handshaker = Handshaker(self.authenticator.mw_index_url,
                                consumer_token)
        request_token = dejsonify(
            self.get_secure_cookie(AUTH_REQUEST_COOKIE_NAME))
        self.clear_cookie(AUTH_REQUEST_COOKIE_NAME)
        access_token = yield self.executor.submit(handshaker.complete,
                                                  request_token,
                                                  self.request.query)

        identity = handshaker.identify(access_token)
        if identity and 'username' in identity:
            # FIXME: Figure out total set of chars that can be present
            # in MW's usernames, and set of chars valid in jupyterhub
            # usernames, and do a proper mapping
            username = identity['username'].replace(' ', '_')
            user = self.find_user(username)
            if user is None:
                user = orm.User(name=username, id=identity['sub'])
                self.db.add(user)
                self.db.commit()
            self.set_login_cookie(user)
            self.redirect(url_path_join(self.hub.server.base_url, 'home'))
        else:
            # todo: custom error page?
            raise web.HTTPError(403)
示例#4
0
async def test_delete_user():
    user = orm.User(name='zoe')
    a = MockPAMAuthenticator(allowed_users={'mal'})

    assert 'zoe' not in a.allowed_users
    await a.add_user(user)
    assert 'zoe' in a.allowed_users
    a.delete_user(user)
    assert 'zoe' not in a.allowed_users
示例#5
0
async def test_delete_user():
    user = orm.User(name='zoe')
    a = MockPAMAuthenticator(whitelist={'mal'})

    assert 'zoe' not in a.whitelist
    await a.add_user(user)
    assert 'zoe' in a.whitelist
    a.delete_user(user)
    assert 'zoe' not in a.whitelist
示例#6
0
def test_cant_add_system_user(io_loop):
    user = orm.User(name='lioness4321')
    authenticator = auth.PAMAuthenticator(whitelist={'mal'})
    authenticator.create_system_users = True
    
    def check_output(cmd, *a, **kw):
        raise CalledProcessError(1, cmd)
    
    with mock.patch.object(auth, 'check_output', check_output):
        with pytest.raises(RuntimeError):
            io_loop.run_sync(lambda : authenticator.add_user(user))
示例#7
0
def test_cant_add_system_user(io_loop):
    user = orm.User(name='lioness4321')
    authenticator = auth.PAMAuthenticator(whitelist={'mal'})
    authenticator.add_user_cmd = ['jupyterhub-fake-command']
    authenticator.create_system_users = True
    
    def check_call(cmd, *a, **kw):
        raise CalledProcessError(1, cmd)
    
    with mock.patch.object(auth, 'check_call', check_call):
        with pytest.raises(CalledProcessError):
            io_loop.run_sync(lambda : authenticator.add_user(user))
示例#8
0
def test_add_system_user(io_loop):
    user = orm.User(name='lioness4321')
    authenticator = auth.PAMAuthenticator(whitelist={'mal'})
    authenticator.create_system_users = True
    authenticator.add_user_cmd = ['echo', '/home/USERNAME']
    
    record = {}
    def check_call(cmd, *a, **kw):
        record['cmd'] = cmd
    
    with mock.patch.object(auth, 'check_call', check_call):
        io_loop.run_sync(lambda : authenticator.add_user(user))
    assert record['cmd'] == ['echo', '/home/lioness4321', 'lioness4321']
示例#9
0
def add_user(db, app=None, **kwargs):
    """Add a user to the database."""
    orm_user = find_user(db, name=kwargs.get('name'))
    if orm_user is None:
        orm_user = orm.User(**kwargs)
        db.add(orm_user)
    else:
        for attr, value in kwargs.items():
            setattr(orm_user, attr, value)
    db.commit()
    if app:
        return app.users[orm_user.id]
    else:
        return orm_user
示例#10
0
def get_db():
    """Get a db session"""
    db = orm.new_session_factory('sqlite:///:memory:', echo=True)()
    user = orm.User(
        name=getuser(),
        server=orm.Server(),
    )
    hub = orm.Hub(
        server=orm.Server(),
    )
    db.add(user)
    db.add(hub)
    db.commit()
    return db
示例#11
0
def test_add_system_user(io_loop):
    user = orm.User(name='lioness4321')
    authenticator = auth.PAMAuthenticator(whitelist={'mal'})
    authenticator.create_system_users = True
    
    def check_output(*a, **kw):
        return
    
    record = {}
    def check_call(cmd, *a, **kw):
        record['cmd'] = cmd
    
    with mock.patch.object(auth, 'check_output', check_output), \
             mock.patch.object(auth, 'check_call', check_call):
        io_loop.run_sync(lambda : authenticator.add_user(user))
    
    assert user.name in record['cmd']
示例#12
0
def test_add_system_user(io_loop):
    user = orm.User(name='lioness4321')
    authenticator = auth.PAMAuthenticator(whitelist={'mal'})
    authenticator.create_system_users = True
    authenticator.add_user_cmd = ['echo', '/home/USERNAME']
    
    record = {}
    class DummyPopen:
        def __init__(self, cmd, *args, **kwargs):
            record['cmd'] = cmd
            self.returncode = 0
        
        def wait(self):
            return
    
    with mock.patch.object(auth, 'Popen', DummyPopen):
        io_loop.run_sync(lambda : authenticator.add_user(user))
    assert record['cmd'] == ['echo', '/home/lioness4321', 'lioness4321']
示例#13
0
def add_user(db, app=None, **kwargs):
    """Add a user to the database."""
    orm_user = find_user(db, name=kwargs.get('name'))
    if orm_user is None:
        orm_user = orm.User(**kwargs)
        db.add(orm_user)
        metrics.TOTAL_USERS.inc()
    else:
        for attr, value in kwargs.items():
            setattr(orm_user, attr, value)
    db.commit()
    requested_roles = kwargs.get('roles')
    if requested_roles:
        update_roles(db, entity=orm_user, roles=requested_roles)
    else:
        assign_default_roles(db, entity=orm_user)
    if app:
        return app.users[orm_user.id]
    else:
        return orm_user
示例#14
0
async def test_wont_add_system_user():
    user = orm.User(name='lioness4321')
    authenticator = auth.PAMAuthenticator(whitelist={'mal'})
    authenticator.create_system_users = False
    with pytest.raises(KeyError):
        await authenticator.add_user(user)
示例#15
0
def populate_db(url):
    """Populate a jupyterhub database"""
    connect_args = {}
    if 'mysql' in url:
        connect_args['auth_plugin'] = 'mysql_native_password'
    db = orm.new_session_factory(url, connect_args=connect_args)()
    # create some users
    admin = orm.User(name='admin', admin=True)
    db.add(admin)
    user = orm.User(name='has-server')
    db.add(user)
    db.commit()

    # create a group
    g = orm.Group(name='group')
    db.add(g)
    db.commit()
    g.users.append(user)
    db.commit()

    service = orm.Service(name='service')
    db.add(service)
    db.commit()

    # create some API tokens
    user.new_api_token()
    admin.new_api_token()

    # services got API tokens in 0.7
    if jupyterhub.version_info >= (0, 7):
        # create a group
        service.new_api_token()

    # Create a Spawner for user
    if jupyterhub.version_info >= (0, 8):
        # create spawner for user
        spawner = orm.Spawner(name='', user=user)
        db.add(spawner)
        db.commit()
        spawner.server = orm.Server()
        db.commit()

        # admin's spawner is not running
        spawner = orm.Spawner(name='', user=admin)
        db.add(spawner)
        db.commit()
    else:
        user.server = orm.Server()
        db.commit()

    # create some oauth objects
    client = orm.OAuthClient(identifier='oauth-client')
    db.add(client)
    db.commit()
    code = orm.OAuthCode(client_id=client.identifier)
    db.add(code)
    db.commit()
    if jupyterhub.version_info < (2, 0):
        Token = partial(
            orm.OAuthAccessToken,
            grant_type=orm.GrantType.authorization_code,
        )
    else:
        Token = orm.APIToken
    access_token = Token(
        client_id=client.identifier,
        user_id=user.id,
    )
    db.add(access_token)
    db.commit()

    # set some timestamps added in 0.9
    assert user.created
    assert admin.created
    # set last_activity
    user.last_activity = datetime.utcnow()
    spawner = user.orm_spawners['']
    spawner.started = datetime.utcnow()
    spawner.last_activity = datetime.utcnow()
    db.commit()
示例#16
0
def test_wont_add_system_user(io_loop):
    user = orm.User(name='lioness4321')
    authenticator = auth.PAMAuthenticator(whitelist={'mal'})
    authenticator.create_system_users = False
    with pytest.raises(KeyError):
        io_loop.run_sync(lambda : authenticator.add_user(user))
示例#17
0
def populate_db(url):
    """Populate a jupyterhub database"""
    connect_args = {}
    if 'mysql' in url:
        connect_args['auth_plugin'] = 'mysql_native_password'
    db = orm.new_session_factory(url, connect_args=connect_args)()

    if jupyterhub.version_info >= (2, ):
        if (not db.query(orm.OAuthClient).filter_by(
                identifier="jupyterhub").one_or_none()):
            # create the oauth client for jupyterhub itself
            # this allows us to distinguish between orphaned tokens
            # (failed cascade deletion) and tokens issued by the hub
            # it has no client_secret, which means it cannot be used
            # to make requests
            client = orm.OAuthClient(
                identifier="jupyterhub",
                secret="",
                redirect_uri="",
                description="JupyterHub",
            )
            db.add(client)
            db.commit()

        from jupyterhub import roles

        for role in roles.get_default_roles():
            roles.create_role(db, role)

    # create some users
    admin = orm.User(name='admin', admin=True)
    db.add(admin)
    user = orm.User(name='has-server')
    db.add(user)
    db.commit()

    # create a group
    g = orm.Group(name='group')
    db.add(g)
    db.commit()
    g.users.append(user)
    db.commit()

    service = orm.Service(name='service')
    db.add(service)
    db.commit()

    # create some API tokens
    user.new_api_token()
    admin.new_api_token()

    # services got API tokens in 0.7
    if jupyterhub.version_info >= (0, 7):
        # create a group
        service.new_api_token()

    # Create a Spawner for user
    if jupyterhub.version_info >= (0, 8):
        # create spawner for user
        spawner = orm.Spawner(name='', user=user)
        db.add(spawner)
        db.commit()
        spawner.server = orm.Server()
        db.commit()

        # admin's spawner is not running
        spawner = orm.Spawner(name='', user=admin)
        db.add(spawner)
        db.commit()
    else:
        user.server = orm.Server()
        db.commit()

    # create some oauth objects
    client = orm.OAuthClient(identifier='oauth-client')
    db.add(client)
    db.commit()
    code = orm.OAuthCode(client_id=client.identifier)
    db.add(code)
    db.commit()
    if jupyterhub.version_info < (2, 0):
        Token = partial(
            orm.OAuthAccessToken,
            grant_type=orm.GrantType.authorization_code,
        )
    else:
        Token = orm.APIToken
    access_token = Token(
        client_id=client.identifier,
        user_id=user.id,
    )
    if jupyterhub.version_info >= (2, ):
        if jupyterhub.version_info < (2, 2):
            access_token.roles = [
                db.query(orm.Role).filter_by(name="server").one()
            ]
        else:
            access_token.scopes = [f"read:users!user={user.name}"]
    db.add(access_token)
    db.commit()

    # set some timestamps added in 0.9
    assert user.created
    assert admin.created
    # set last_activity
    user.last_activity = datetime.utcnow()
    spawner = user.orm_spawners['']
    spawner.started = datetime.utcnow()
    spawner.last_activity = datetime.utcnow()
    db.commit()