def test_authed_user_bypasses_login(app): # A logged in user should go straight to the control panel cookies = app.login_user('river') r = requests.get(public_url(app), cookies=cookies) r.raise_for_status() url = public_url(app) print(url) print(app.hub.server.base_url) assert r.url == ujoin(url, 'hub/home')
def test_authed_user_bypasses_login(app): # A logged in user should go straight to the control panel cookies = app.login_user('river') r = requests.get(public_url(app), cookies=cookies) r.raise_for_status() url = public_url(app) print(url) print(app.hub.server.base_url) assert r.url == ujoin(url, app.hub.server.base_url, 'home')
def test_image_whitelist(app, image): name = "checker" add_user(app.db, app, name=name) user = app.users[name] assert isinstance(user.spawner, DockerSpawner) user.spawner.remove_containers = True user.spawner.image_whitelist = { "0.9": "jupyterhub/singleuser:0.9", "0.8": "jupyterhub/singleuser:0.8", } token = user.new_api_token() # start the server r = yield api_request( app, "users", name, "server", method="post", data=json.dumps({"image": image}) ) if image not in user.spawner.image_whitelist: with pytest.raises(Exception): r.raise_for_status() return while r.status_code == 202: # request again r = yield api_request(app, "users", name, "server", method="post") yield gen.sleep(0.1) assert r.status_code == 201, r.text url = url_path_join(public_url(app, user), "api/status") r = yield async_requests.get(url, headers={"Authorization": "token %s" % token}) r.raise_for_status() assert r.headers['x-jupyterhub-version'].startswith(image) r = yield api_request( app, "users", name, "server", method="delete", ) r.raise_for_status()
async def test_start_stop(dockerspawner_configured_app): app = dockerspawner_configured_app name = "has@" add_user(app.db, app, name=name) user = app.users[name] server_name = 'also-has@' spawner = user.spawners[server_name] assert isinstance(spawner, DockerSpawner) token = user.new_api_token() # start the server r = await api_request(app, "users", name, "servers", server_name, method="post") pending = r.status_code == 202 while pending: # request again r = await api_request(app, "users", name) user_info = r.json() pending = user_info["servers"][server_name]["pending"] assert r.status_code in {201, 200}, r.text url = url_path_join(public_url(app, user), server_name, "api/status") resp = await AsyncHTTPClient().fetch( url, headers={"Authorization": "token %s" % token} ) assert resp.effective_url == url resp.rethrow() assert "kernels" in resp.body.decode("utf-8")
def test_whitelist(app): url = public_url(app) r = requests.post(ujoin(url, 'hub/oauth_callback'), data={ 'username': '******', 'password': '******' }) assert r.status_code == 403 text = ('Your username is not whitelisted on this server. ' 'Please contact the system administrator.') assert text in r.text
def test_github_login_no_auth(app, io_loop): # Test that login page uses GitHub OAuth print(app.hub.server.is_up()) routes = io_loop.run_sync(app.proxy.get_routes) print(routes) print(app.hub.server) url = public_url(app) print(url) r = requests.get(url) r.raise_for_status() assert r.url == ujoin(url, app.hub.server.base_url, 'login') assert "Sign in with GitHub" in r.text
def test_github_login_no_auth(app, io_loop): # Test that login page uses GitHub OAuth print(app.hub.server.is_up()) routes = io_loop.run_sync(app.proxy.get_routes) print(routes) print(app.hub.server) url = public_url(app) print(url) r = requests.get(url) r.raise_for_status() assert r.url == ujoin(url, 'hub/login') assert "Sign in with GitHub" in r.text
def test_whitelist(app): url = public_url(app) r = requests.post( ujoin(url, app.hub.server.base_url, 'oauth_callback'), data={ 'username': '******', 'password': '******' } ) assert r.status_code == 403 text = ('Your username is not whitelisted on this server. ' 'Please contact the system administrator.') assert text in r.text
def setup_class(cls): cls._failure_occurred = False # flag for logging cls.log = get_wrapped_logger(cls.__name__) cls.log.handlers[0].setFormatter( LevelFormatter( fmt=('[%(levelname)1.1s ' '%(asctime)s.%(msecs).03d ' '%(name)s %(module)s:%(lineno)d]' '%(message)s'), datefmt='%H:%M:%S', )) cls._setup_patches() cls.pre_server_setup() cls.log.info('starting webdriver') cls.init_webdriver() cls.log.info('Starting jupyterhub server app thread') cls.app = MockHub.instance( log_datefmt="%H:%M:%S", authenticator_class=MockAuthenticator, spawner_class=TestSpawner, ) # need to start jupyterhub app before calling super, as the super will # wait for the page to load try: cls.app.log = wrap_logger_handlers(cls.app.log) cls.app.start([]) except Exception: cls._server_cleanup(error_msg='failed to start jupyterhub app') try: cls.log.info( 'Logging into hub-spawned single-user notebook server.') login_url = public_url(cls.app) + 'login' cls.driver.get(login_url) cls.uname = name = next(iter(MockAuthenticator._default_whitelist)) cls.wait_for_selector('#username_input').send_keys(name) cls.wait_for_selector('#password_input').send_keys(name) cls.wait_for_selector('#login_submit').click() cls.wait_for_selector('#header') # single-user page loaded user = cls.user = cls.app.users[name] if not user.running: io_loop = IOLoop() io_loop.make_current() io_loop.run_sync(user.spawn) except Exception: cls._server_cleanup( error_msg='failed to start/login to single-user server')
async def test_integration(app, auto_login, logged_in): app.authenticator.auto_login = auto_login # Create a user add_user(app.db, app, name="alice") if auto_login: url = public_url(app, path="/hub/login") resp = await async_requests.get(url) # Sends back 401 requesting authentication assert resp.status_code == 401 # 401 page is formatted nicely assert "Failed to login with Kerberos." in resp.text assert resp.text.count("/hub/login") >= 2 # Before that was a redirect to the auth handler assert resp.history[0].status_code == 302 # Now use the redirected url with auth enabled location = resp.history[0].headers['location'] netloc = urlparse(app.bind_url).netloc url = 'http://%s%s' % (netloc, location) else: url = public_url(app, path="/hub/kerberos_login") # Go through the login procedure resp = await async_requests.get( url, auth=HTTPKerberosAuth(hostname_override="address.example.com")) if logged_in: # Successful resp.raise_for_status() # At user notebook, login successful assert resp.url.startswith(public_url(app, path="/user/alice")) else: # Unsuccessful assert resp.status_code == 401
def login_user(self, name): # Works together with MockGitHubOAuthenticator to allow us to # login users without having to contact the OAuth provider # Need to use POST so we can choose the username which is # normally sent by the OAuth provider base_url = public_url(self) r = requests.post(base_url + 'hub/oauth_callback', data={'username': name, 'password': name, }, allow_redirects=False, ) r.raise_for_status() assert r.cookies return r.cookies
async def test_integration(skein_client, app): with clean_cluster(skein_client): # Create a user add_user(app.db, app, name="alice") alice = app.users["alice"] assert isinstance(alice.spawner, YarnSpawner) token = alice.new_api_token() # Not started, status should be 0 status = await alice.spawner.poll() assert status == 0 # Stop can be called before start, no-op await alice.spawner.stop() # Start the server, and wait for it to start resp = None while resp is None or resp.status_code == 202: await gen.sleep(2.0) resp = await api_request(app, "users", "alice", "server", method="post") # Check that everything is running fine url = url_path_join(public_url(app, alice), "api/status") resp = await async_requests.get( url, headers={'Authorization': 'token %s' % token}) resp.raise_for_status() assert "kernels" in resp.json() # Save the app_id to use later app_id = alice.spawner.app_id # Shutdown the server resp = await api_request(app, "users", "alice", "server", method="delete") resp.raise_for_status() assert_shutdown_in(skein_client, app_id, timeout=10) # Check status status = await alice.spawner.poll() assert status == 0
def login_user(self, name): # Works together with MockGitHubOAuthenticator to allow us to # login users without having to contact the OAuth provider # Need to use POST so we can choose the username which is # normally sent by the OAuth provider base_url = public_url(self) r = requests.post( base_url + 'hub/oauth_callback', data={ 'username': name, 'password': name, }, allow_redirects=False, ) r.raise_for_status() assert r.cookies return r.cookies
async def test_allowed_image(dockerspawner_configured_app, image): app = dockerspawner_configured_app name = "checker" add_user(app.db, app, name=name) user = app.users[name] assert isinstance(user.spawner, DockerSpawner) user.spawner.remove_containers = True user.spawner.allowed_images = { "1.0": "jupyterhub/singleuser:1.0", "1.1": "jupyterhub/singleuser:1.1", } token = user.new_api_token() # start the server r = await api_request(app, "users", name, "server", method="post", data=json.dumps({"image": image})) if image not in user.spawner.allowed_images: with pytest.raises(Exception): r.raise_for_status() return pending = r.status_code == 202 while pending: # request again r = await api_request(app, "users", name) user_info = r.json() pending = user_info["servers"][""]["pending"] url = url_path_join(public_url(app, user), "api/status") resp = await AsyncHTTPClient().fetch( url, headers={"Authorization": "token %s" % token}) assert resp.effective_url == url resp.rethrow() assert resp.headers['x-jupyterhub-version'].startswith(image) r = await api_request( app, "users", name, "server", method="delete", ) r.raise_for_status()
def test_start_stop(app): name = "somebody" add_user(app.db, app, name=name) user = app.users[name] assert isinstance(user.spawner, SwarmSpawner) token = user.new_api_token() # start the server r = yield api_request(app, "users", name, "server", method="post") while r.status_code == 202: # request again r = yield api_request(app, "users", name, "server", method="post") assert r.status_code == 201, r.text url = url_path_join(public_url(app, user), "api/status") r = yield async_requests.get(url, headers={"Authorization": "token %s" % token}) assert r.url == url r.raise_for_status() print(r.text) assert "kernels" in r.json()
def test_start_stop(app): name = getuser() add_user(app.db, app, name=name) user = app.users[name] assert isinstance(user.spawner, SystemUserSpawner) token = user.new_api_token() # start the server r = yield api_request(app, "users", name, "server", method="post") while r.status_code == 202: # request again r = yield api_request(app, "users", name, "server", method="post") assert r.status_code == 201, r.text url = url_path_join(public_url(app, user), "api/status") r = yield async_requests.get(url, headers={"Authorization": "token %s" % token}) assert r.url == url r.raise_for_status() print(r.text) assert "kernels" in r.json()
async def test_start_stop(systemuserspawner_configured_app): app = systemuserspawner_configured_app name = getuser() add_user(app.db, app, name=name) user = app.users[name] assert isinstance(user.spawner, SystemUserSpawner) token = user.new_api_token() # start the server r = await api_request(app, "users", name, "server", method="post") while r.status_code == 202: # request again r = await api_request(app, "users", name, "server", method="post") assert r.status_code == 201, r.text url = url_path_join(public_url(app, user), "api/status") resp = await AsyncHTTPClient().fetch(url, headers={"Authorization": "token %s" % token}) assert resp.effective_url == url resp.rethrow() assert "kernels" in resp.body.decode("utf-8")
def test_image_whitelist(app, image): name = "checker" add_user(app.db, app, name=name) user = app.users[name] assert isinstance(user.spawner, DockerSpawner) user.spawner.remove_containers = True user.spawner.image_whitelist = { "0.9": "jupyterhub/singleuser:0.9", "0.8": "jupyterhub/singleuser:0.8", } token = user.new_api_token() # start the server r = yield api_request(app, "users", name, "server", method="post", data=json.dumps({"image": image})) if image not in user.spawner.image_whitelist: with pytest.raises(Exception): r.raise_for_status() return while r.status_code == 202: # request again r = yield api_request(app, "users", name, "server", method="post") yield gen.sleep(0.1) assert r.status_code == 201, r.text url = url_path_join(public_url(app, user), "api/status") r = yield async_requests.get(url, headers={"Authorization": "token %s" % token}) r.raise_for_status() assert r.headers['x-jupyterhub-version'].startswith(image) r = yield api_request( app, "users", name, "server", method="delete", ) r.raise_for_status()
def test_username_case(app): # A logged in user should go straight to the control panel cookies = app.login_user('River') r = requests.get(public_url(app), cookies=cookies) r.raise_for_status() assert 'Logged in as river' in r.text
def base_url(cls): return public_url(cls.app, cls.user)