示例#1
0
def test_dummy_auth(build_image, container):
    """
    Test that the client is able to.
    - Once authenticated, pass a correctly formatted Mount Header
    """
    test_logger.info("Start of test_dummy_auth")
    assert wait_for_site(JHUB_URL) is True
    with requests.Session() as s:
        # login
        user = "******"
        # next to hub/home, else the login by
        #  default will return 500 because it will
        #  try and start a server right away with the new user
        # Which fails because the default
        #  spawner requires a matching local username
        login_response = s.post(
            JHUB_URL + "/hub/login?next=/hub/home",
            data={
                "username": user,
                "password": "******"
            },
        )
        assert login_response.status_code == 200
        resp = s.get(JHUB_URL + "/hub/home")
        assert resp.status_code == 200
    test_logger.info("End of test_dummy_auth")
示例#2
0
def test_basic_cert_user_header_auth(build_image, container):
    """
    Test that the client is able to.
    Once authenticated, pass a correctly formatted Mount Header
    """
    test_logger.info("Start of test_basic_cert_user_header_auth")
    client = docker.from_env()
    service_name = "jupyterhub"
    if not wait_for_container(client, service_name, minutes=5):
        raise RuntimeError(JUPYTERHUB_START_ERROR)
    assert wait_for_site(JHUB_URL, valid_status_code=401) is True
    with requests.session() as session:
        # Auth requests
        remote_user = (
            "/C=DK/ST=NA/L=NA/O=NBI/OU=NA/CN=Name" "/[email protected]"
        )
        auth_header = {"Remote-User": remote_user}

        auth_response = session.get(
            "".join([JHUB_HUB_URL, "/home"]), headers=auth_header
        )
        assert auth_response.status_code == 200

        auth_response = session.post(
            "".join([JHUB_HUB_URL, "/login"]), headers=auth_header
        )
        assert auth_response.status_code == 200
        # TODO, validate username is actual email regex
    test_logger.info("End of test_basic_cert_user_header_auth")
示例#3
0
def test_default_header_config(build_image, container):
    """
    Test that an authenticated client is able to pass
     a correctly formatted Mount Header
    """
    test_logger.info("Start of test_default_header_config")
    client = docker.from_env()
    service_name = "jupyterhub"
    if not wait_for_container(client, service_name, minutes=5):
        raise RuntimeError(JUPYTERHUB_START_ERROR)
    assert wait_for_site(JHUB_URL, valid_status_code=401) is True
    with requests.session() as session:
        # Auth requests
        remote_user = "******"
        auth_header = {"Remote-User": remote_user}

        auth_response = session.get(
            "".join([JHUB_HUB_URL, "/home"]), headers=auth_header
        )
        assert auth_response.status_code == 200

        auth_response = session.post(
            "".join([JHUB_HUB_URL, "/login"]), headers=auth_header
        )
        assert auth_response.status_code == 200
    test_logger.info("End of test_default_header_config")
示例#4
0
def test_remote_oid_user_header_auth(build_image, container):
    """
    Test that the client is able to.
    Once authenticated, pass a correctly formatted Mount Header
    """
    test_logger.info("Start of test_remote_oid_user_header_auth")
    client = docker.from_env()
    service_name = "jupyterhub"
    if not wait_for_container(client, service_name, minutes=5):
        raise RuntimeError(JUPYTERHUB_START_ERROR)
    assert wait_for_site(JHUB_URL, valid_status_code=401) is True
    with requests.session() as session:
        # Auth requests
        remote_user = "******"
        auth_header = {"Remote-User": remote_user}

        auth_response = session.get(
            "".join([JHUB_HUB_URL, "/home"]), headers=auth_header
        )
        assert auth_response.status_code == 200

        auth_response = session.post(
            "".join([JHUB_HUB_URL, "/login"]), headers=auth_header
        )
        assert auth_response.status_code == 200
    test_logger.info("End of test_remote_oid_user_header_auth")
示例#5
0
def test_custom_data_header_auth(build_image, container):
    """
    Test that the client is able to.
    Once authenticated, pass a correctly formatted Mount Header
    """
    test_logger.info("Start of test_custom_data_header_auth")
    client = docker.from_env()
    service_name = "jupyterhub"
    if not wait_for_container(client, service_name, minutes=5):
        raise RuntimeError(JUPYTERHUB_START_ERROR)
    assert wait_for_site(JHUB_URL, valid_status_code=401) is True
    with requests.session() as session:
        # Auth requests
        remote_user = "******"
        data_dict = {
            "HOST": "hostaddr",
            "USERNAME": "******",
            "PATH": "@host.localhost:",
        }
        auth_data_header = {"Remote-User": remote_user, "Mount": json.dumps(data_dict)}

        auth_response = session.post(
            "".join([JHUB_HUB_URL, "/login"]), headers=auth_data_header
        )
        assert auth_response.status_code == 200
    test_logger.info("End of test_custom_data_header_auth")
def test_auth_hub(build_image, container):
    """
    Test that the client is able to,
    Not access the home path without being authed
    Authenticate with the Remote-User header
    """
    test_logger.info("Start of test_auth_hub")
    client = docker.from_env()
    service_name = "jupyterhub"
    if not wait_for_container(client, service_name, minutes=5):
        raise RuntimeError(JUPYTERHUB_START_ERROR)
    assert wait_for_site(JHUB_URL, valid_status_code=401) is True

    with requests.Session() as session:
        # Auth requests
        user_cert = (
            "/C=DK/ST=NA/L=NA/O=NBI/OU=NA/CN=Name" "/[email protected]"
        )
        other_user = "******"

        cert_auth_header = {"Remote-User": user_cert}

        other_auth_header = {"Remote-User": other_user}

        auth_response = session.post(
            "".join([JHUB_HUB_URL, "/login"]), headers=cert_auth_header
        )
        assert auth_response.status_code == 200

        auth_response = session.get(
            "".join([JHUB_HUB_URL, "/home"]), headers=other_auth_header
        )
        assert auth_response.status_code == 200
    test_logger.info("End of test_auth_hub")
def test_auth_data_header(build_image, container):
    """
    Test that the client is able to.
    Once authenticated, pass a correctly formatted custom Data header
    """
    # not ideal, wait for the jhub container to start, update with proper check
    test_logger.info("Start of test_auth_data_header")
    client = docker.from_env()
    service_name = "jupyterhub"
    if not wait_for_container(client, service_name, minutes=5):
        raise RuntimeError(JUPYTERHUB_START_ERROR)
    assert wait_for_site(JHUB_URL, valid_status_code=401) is True
    with requests.Session() as session:
        no_auth_mount = session.post("".join([JHUB_HUB_URL, "/data"]))
        assert no_auth_mount.status_code == 403

        # Auth requests
        user_cert = (
            "/C=DK/ST=NA/L=NA/O=NBI/OU=NA/CN=Name" "/[email protected]"
        )

        cert_auth_header = {"Remote-User": user_cert}

        auth_response = session.get(
            "".join([JHUB_HUB_URL, "/home"]), headers=cert_auth_header
        )
        assert auth_response.status_code == 200

        auth_response = session.post(
            "".join([JHUB_HUB_URL, "/login"]), headers=cert_auth_header
        )
        assert auth_response.status_code == 200

        wrong_header = {"Mount": "SDfssdfsesdfsfdsdfsxv"}

        # Random key set
        correct_dict = {
            "HOST": "hostaddr",
            "USERNAME": "******",
            "PATH": "@host.localhost:",
        }

        correct_header = {"Mount": str(correct_dict)}

        # Invalid mount header
        auth_mount_response = session.post(
            "".join([JHUB_HUB_URL, "/data"]), headers=wrong_header
        )
        assert auth_mount_response.status_code == 403

        # Valid mount header
        auth_mount_response = session.post(
            "".join([JHUB_HUB_URL, "/data"]), headers=correct_header
        )
        assert auth_mount_response.status_code == 200
    test_logger.info("End of test_auth_data_header")
示例#8
0
def test_json_data_post(build_image, network, container):
    """
    Test that the client is able to submit a json data to the authenticated user.
    """
    test_logger.info("Start of test_json_data_post")
    client = docker.from_env()
    service_name = "jupyterhub"
    if not wait_for_container(client, service_name, minutes=5):
        raise RuntimeError(JUPYTERHUB_START_ERROR)
    assert wait_for_site(JHUB_URL, valid_status_code=401) is True
    with requests.session() as session:
        # Auth requests
        remote_user = "******"
        auth_header = {
            "Remote-User": remote_user,
        }

        auth_response = session.post(
            "".join([JHUB_HUB_URL, "/login"]), headers=auth_header
        )
        assert auth_response.status_code == 200
        # Post json
        data_str = "blablabla"
        data_dict = {
            "HOST": "hostaddr",
            "USERNAME": "******",
            "PATH": "@host.localhost:",
        }
        env_data = {"StringData": data_str, "JsonData": data_dict}

        json_data = {"data": env_data}
        post_response = session.post(
            "".join([JHUB_HUB_URL, "/user-data"]), json=json_data
        )
        assert post_response.status_code == 200
    test_logger.info("End of test_json_data_post")
示例#9
0
def test_auth_state_header_auth(build_image, network, container):
    """
    Test that the client is able to. Test that auth_state recieves
    the specified test data headers.
    """
    test_logger.info("Start of test_auth_state_header_auth")
    client = docker.from_env()
    service_name = "jupyterhub"
    if not wait_for_container(client, service_name, minutes=5):
        raise RuntimeError(JUPYTERHUB_START_ERROR)
    assert wait_for_site(JHUB_URL, valid_status_code=401) is True
    with requests.session() as session:
        # Auth requests
        remote_user = "******"
        data_str = "blablabla"
        data_dict = {
            "HOST": "hostaddr",
            "USERNAME": "******",
            "PATH": "@host.localhost:",
        }
        env_data = {"StringData": data_str, "JsonData": data_dict}
        auth_data_header = {
            "Remote-User": remote_user,
        }

        # Cast to json data types before submission
        auth_data_header.update(
            {env_key: json.dumps(env_val) for env_key, env_val in env_data.items()}
        )
        auth_response = session.post(
            "".join([JHUB_HUB_URL, "/login"]), headers=auth_data_header
        )
        assert auth_response.status_code == 200
        # Spawn with auth_state
        spawn_response = session.post("".join([JHUB_HUB_URL, "/spawn"]))
        assert spawn_response.status_code == 200

        test_logger.info("Spawn POST response message: {}".format(spawn_response.text))
        assert spawn_response.status_code == 200

        target_container_name = "{}-{}".format("jupyter", remote_user)
        wait_min = 5
        if not wait_for_container(client, target_container_name, minutes=wait_min):
            raise RuntimeError(
                "No container with name: {} appeared within: {} minutes".format(
                    service_name, wait_min
                )
            )

        spawned_container = get_container(client, target_container_name)
        # Validate that the container has the passed environment values defined
        # in env_data
        envs = {
            env.split("=")[0]: env.split("=")[1]
            for env in spawned_container.attrs["Config"]["Env"]
        }
        for data_key, data_value in env_data.items():
            assert data_key in envs
            assert envs[data_key] == str(data_value)

        # Shutdown the container
        # Delete the spawned service
        delete_headers = {"Referer": urljoin(JHUB_URL, "/hub/"), "Origin": JHUB_URL}

        jhub_user = get_container_user(spawned_container)
        assert jhub_user is not None
        delete_url = urljoin(JHUB_URL, "/hub/api/users/{}/server".format(jhub_user))

        deleted = delete(session, delete_url, headers=delete_headers)
        assert deleted
        # Remove the stopped container
        spawned_container.stop()
        spawned_container.wait()
        spawned_container.remove()

        deleted_container = get_container(client, target_container_name)
        assert deleted_container is None
    test_logger.info("End of test_auth_state_header_auth")
示例#10
0
def test_remote_auth_hub(image, swarm, network, make_service):
    """Test that logging in as a new user creates a new docker service."""
    test_logger.info("Start of service testing")
    make_service(remote_hub_service)
    client = docker.from_env()
    # jupyterhub service should be running at this point
    services_before_spawn = client.services.list()
    test_logger.info("Pre test services: {}".format(services_before_spawn))

    username = "******"
    # Auth header
    test_logger.info("Authenticating with user: {}".format(username))
    headers = {"Remote-User": username}
    assert wait_for_site(JHUB_URL, valid_status_code=401) is True

    with requests.Session() as s:
        # Login
        login_response = s.post(JHUB_URL + "/hub/login", headers=headers)
        test_logger.info("Login response message: {}".format(
            login_response.text))
        assert login_response.status_code == 200

        # Spawn a notebook
        spawn_form_resp = s.get(JHUB_URL + "/hub/spawn")
        test_logger.info("Spawn page message: {}".format(spawn_form_resp.text))
        assert spawn_form_resp.status_code == 200
        assert "Select a notebook image" in spawn_form_resp.text
        payload = {"dockerimage": "nielsbohr/base-notebook:latest"}
        spawn_resp = s.post(JHUB_URL + "/hub/spawn", data=payload)
        test_logger.info("Spawn POST response message: {}".format(
            spawn_resp.text))
        assert spawn_resp.status_code == 200

        # Get spawned service
        target_service_name = "{}-".format("jupyter")
        spawned_service = get_service(client, target_service_name)
        assert spawned_service is not None

        # Get the service api url
        service_url = get_service_url(spawned_service)
        # If failed the service might not be running
        if not service_url:
            test_logger.info("Properly failed to start the service correctly")
        assert service_url is not None

        # Combine with the base jhub URL
        jhub_service_api = urljoin(JHUB_URL, service_url)

        # Write to user home
        new_file = "write_test.ipynb"
        data = json.dumps({"name": new_file})
        test_logger.info("Looking for xsrf in: {}".format(s.cookies))

        # Refresh csrf token
        assert wait_for_session(s, jhub_service_api, require_xsrf=True)
        assert "_xsrf" in s.cookies
        xsrf_token = s.cookies["_xsrf"]
        service_api_url = get_service_api_url(spawned_service,
                                              postfix_url="contents/")
        jhub_service_content = urljoin(JHUB_URL, service_api_url)

        # Write to home
        xsrf_headers = {"X-XSRFToken": xsrf_token}
        resp = s.put(
            "".join([jhub_service_content, new_file]),
            data=data,
            headers=xsrf_headers,
        )
        assert resp.status_code == 201

        # Remove via the web interface
        refresh_csrf(s, jhub_service_api)
        assert "_xsrf" in s.cookies
        delete_headers = {
            "Referer": urljoin(JHUB_URL, "/hub/home"),
            "Origin": JHUB_URL,
        }

        jhub_user = get_service_user(spawned_service)
        delete_url = urljoin(JHUB_URL,
                             "/hub/api/users/{}/server".format(jhub_user))

        # Wait for the server to finish deleting
        deleted = delete(s, delete_url, headers=delete_headers)
        assert deleted

        deleted_service = get_service(client, target_service_name)
        assert deleted_service is None
示例#11
0
def test_creates_service(image, swarm, network, make_service):
    """Test that logging in as a new user creates a new docker service."""
    test_logger.info("Start of service testing")
    make_service(hub_service)
    client = docker.from_env()
    # jupyterhub service should be running at this point
    services_before_spawn = client.services.list()
    test_logger.info("Pre test services: {}".format(services_before_spawn))

    username = "******"
    password = "******"
    test_logger.info("Authenticating with user: {}".format(username))
    assert wait_for_site(JHUB_URL) is True

    with requests.Session() as s:
        # login
        test_logger.info("Authenticating with user: {}".format(username))
        login_response = s.post(
            JHUB_URL + "/hub/login?next=",
            data={
                "username": username,
                "password": password
            },
        )
        test_logger.info("Login response message: {}".format(
            login_response.text))
        assert login_response.status_code == 200
        # Spawn a notebook
        spawn_form_resp = s.get(JHUB_URL + "/hub/spawn")
        test_logger.info("Spawn page message: {}".format(spawn_form_resp.text))

        assert spawn_form_resp.status_code == 200
        assert "Select a notebook image" in spawn_form_resp.text

        payload = {"dockerimage": "nielsbohr/base-notebook:latest"}
        spawn_resp = s.post(JHUB_URL + "/hub/spawn", data=payload)
        test_logger.info("Spawn POST response message: {}".format(
            spawn_resp.text))
        assert spawn_resp.status_code == 200

        services = client.services.list()
        test_logger.info("Post spawn services: {}".format(services))

        target_service_name = "{}-{}-{}".format("jupyter", username, "1")
        spawned_service = get_service(client, target_service_name)
        assert spawned_service is not None

        # Verify that a task is succesfully running
        running_task = wait_for_service_task(
            client, spawned_service, filters={"desired-state": "running"})
        assert running_task

        # wait for user home
        home_resp = s.get(JHUB_URL + "/user/{}/tree?".format(username))
        assert home_resp.status_code == 200
        # Remove via the web interface
        delete_headers = {
            "Referer": urljoin(JHUB_URL, "/hub/home"),
            "Origin": JHUB_URL
        }

        jhub_user = get_service_user(spawned_service)
        delete_url = urljoin(JHUB_URL,
                             "/hub/api/users/{}/server".format(jhub_user))

        pending = True
        num_wait, max_wait = 0, 15
        while pending or num_wait > max_wait:
            num_wait += 1
            resp = s.delete(delete_url, headers=delete_headers)
            test_logger.info(
                "Response from removing the user server: {}".format(resp.text))
            if resp.status_code == 204:
                pending = False
            time.sleep(1)

        assert resp.status_code == 204

        # double check it is gone
        deleted_service = get_service(client, target_service_name)
        assert deleted_service is None
        test_logger.info("End of test service")
示例#12
0
def test_image_selection(image, swarm, network, make_service):
    """Test that the spawner allows for dynamic image selection"""
    test_logger.info("Start of the image selection test")
    make_service(hub_service)
    client = docker.from_env()
    # jupyterhub service should be running at this point
    services_before_spawn = client.services.list()
    test_logger.info("Pre test services: {}".format(services_before_spawn))

    username = "******"
    password = "******"
    test_logger.info("Authenticating with user: {}".format(username))
    assert wait_for_site(JHUB_URL) is True

    with requests.Session() as s:
        # login
        test_logger.info("Authenticating with user: {}".format(username))
        login_response = s.post(
            urljoin(JHUB_URL, "/hub/login"),
            data={
                "username": username,
                "password": password
            },
        )
        test_logger.info("Login response message: {}".format(
            login_response.text))
        assert login_response.status_code == 200

        # Spawn a notebook
        spawn_form_resp = s.get(JHUB_URL + "/hub/spawn")
        test_logger.info("Spawn page message: {}".format(spawn_form_resp.text))

        assert spawn_form_resp.status_code == 200
        assert "Select a notebook image" in spawn_form_resp.text

        user_image = "nielsbohr/base-notebook:latest"
        user_image_name = "Basic Python Notebook"

        payload = {"name": user_image_name, "image": user_image}
        json_payload = json.dumps(payload)
        spawn_resp = s.post(
            JHUB_URL + "/hub/spawn/{}".format(username),
            files={"select_image": (
                None,
                json_payload,
            )},
        )

        test_logger.info("Spawn POST response message: {}".format(
            spawn_resp.text))
        assert spawn_resp.status_code == 200

        target_service_name = "{}-{}-{}".format("jupyter", username, "1")
        spawned_service = get_service(client, target_service_name)
        assert spawned_service is not None

        # Verify that a task is succesfully running
        running_task = wait_for_service_task(
            client, spawned_service, filters={"desired-state": "running"})
        assert running_task

        # Verify that the image is correct
        service_image = get_task_image(running_task)
        assert service_image == user_image

        service_labels = get_service_labels(spawned_service)
        assert service_labels is not None
        assert service_labels["image_name"] == user_image_name

        # Delete the spawned service
        delete_headers = {
            "Referer": urljoin(JHUB_URL, "/hub/home"),
            "Origin": JHUB_URL
        }

        jhub_user = get_service_user(spawned_service)
        delete_url = urljoin(JHUB_URL,
                             "/hub/api/users/{}/server".format(jhub_user))

        deleted = delete(s, delete_url, headers=delete_headers)
        assert deleted

        deleted_service = get_service(client, target_service_name)
        assert deleted_service is None

        # Spawn a second service with a different name but the same image ##
        # Spawn a notebook
        second_spawn_form_resp = s.get(JHUB_URL + "/hub/spawn")
        test_logger.info("Spawn page message: {}".format(
            second_spawn_form_resp.text))

        assert second_spawn_form_resp.status_code == 200
        assert "Select a notebook image" in second_spawn_form_resp.text

        second_image_name = "Basic Python Notebook 2"
        selection_payload = {"name": second_image_name, "image": user_image}
        json_second_payload = json.dumps(selection_payload)

        spawn_resp = s.post(
            JHUB_URL + "/hub/spawn/{}".format(username),
            files={"select_image": (
                None,
                json_second_payload,
            )},
        )
        test_logger.info("Spawn POST response message: {}".format(
            spawn_resp.text))
        assert spawn_resp.status_code == 200

        second_target_service_name = "{}-{}-{}".format("jupyter", username,
                                                       "1")
        second_spawned_service = get_service(client,
                                             second_target_service_name)
        assert second_spawned_service is not None

        # Verify that a task is succesfully running
        second_running_task = wait_for_service_task(
            client,
            second_spawned_service,
            filters={"desired-state": "running"})
        assert second_running_task

        # Verify that the image is correct
        second_service_image = get_task_image(second_running_task)
        assert second_service_image == user_image

        second_service_labels = get_service_labels(second_spawned_service)
        assert second_service_labels is not None
        assert second_service_labels["image_name"] == second_image_name

        # Delete the second spawned service
        deleted = delete(s, delete_url, headers=delete_headers)
        assert deleted

        deleted_service = get_service(client, second_target_service_name)
        assert deleted_service is None