Files
the-littlest-jupyterhub/integration-tests/test_proxy.py

180 lines
4.9 KiB
Python
Raw Normal View History

"""tests for the proxy"""
import os
import shutil
import ssl
from subprocess import check_call
import time
2020-06-08 11:42:10 +03:00
import toml
from tornado.httpclient import HTTPClient, HTTPRequest, HTTPClientError
import pytest
2020-06-18 17:29:50 +03:00
from tljh.config import (
reload_component,
set_config_value,
2020-06-20 02:05:53 +03:00
unset_config_value,
2020-06-18 17:29:50 +03:00
CONFIG_FILE,
CONFIG_DIR,
STATE_DIR,
)
2020-06-20 02:05:53 +03:00
def send_request(url, max_sleep, validate_cert=True, username=None, password=None):
resp = None
for i in range(max_sleep):
time.sleep(i)
try:
req = HTTPRequest(
url,
method="GET",
auth_username=username,
auth_password=password,
validate_cert=validate_cert,
follow_redirects=True,
max_redirects=15,
)
resp = HTTPClient().fetch(req)
break
except Exception as e:
print(e)
pass
return resp
def test_manual_https(preserve_config):
ssl_dir = "/etc/tljh-ssl-test"
key = ssl_dir + "/ssl.key"
cert = ssl_dir + "/ssl.cert"
os.makedirs(ssl_dir, exist_ok=True)
os.chmod(ssl_dir, 0o600)
# generate key and cert
check_call(
[
"openssl",
"req",
"-nodes",
"-newkey",
"rsa:2048",
"-keyout",
key,
"-x509",
"-days",
"1",
"-out",
cert,
"-subj",
"/CN=tljh.jupyer.org",
]
)
set_config_value(CONFIG_FILE, "https.enabled", True)
set_config_value(CONFIG_FILE, "https.tls.key", key)
set_config_value(CONFIG_FILE, "https.tls.cert", cert)
reload_component("proxy")
for i in range(10):
time.sleep(i)
try:
server_cert = ssl.get_server_certificate(("127.0.0.1", 443))
except Exception as e:
print(e)
else:
break
with open(cert) as f:
file_cert = f.read()
# verify that our certificate was loaded by traefik
assert server_cert == file_cert
2020-06-20 02:05:53 +03:00
# verify that we can still connect to the hub
resp = send_request(
url="https://127.0.0.1/hub/api", max_sleep=10, validate_cert=False
)
2020-06-08 11:42:10 +03:00
assert resp.code == 200
2020-06-20 02:05:53 +03:00
# cleanup
shutil.rmtree(ssl_dir)
2020-06-20 02:05:53 +03:00
set_config_value(CONFIG_FILE, "https.enabled", False)
reload_component("proxy")
2020-06-08 11:42:10 +03:00
2020-06-18 17:29:50 +03:00
def test_extra_traefik_static_config():
2020-06-20 02:05:53 +03:00
extra_static_config_dir = os.path.join(CONFIG_DIR, "traefik_config.d")
os.makedirs(extra_static_config_dir, exist_ok=True)
2020-06-08 11:42:10 +03:00
2020-06-20 02:05:53 +03:00
extra_static_config = {
2020-06-08 11:42:10 +03:00
"entryPoints": {"no_auth_api": {"address": "127.0.0.1:9999"}},
"api": {"dashboard": True, "entrypoint": "no_auth_api"},
}
success = False
for i in range(5):
time.sleep(i)
try:
with pytest.raises(HTTPClientError, match="HTTP 401: Unauthorized"):
# The default dashboard entrypoint requires authentication, so it should fail
req = HTTPRequest("http://127.0.0.1:8099/dashboard/", method="GET")
HTTPClient().fetch(req)
success = True
break
except Exception as e:
pass
assert success == True
2020-06-20 02:05:53 +03:00
# write the extra static config
with open(
os.path.join(extra_static_config_dir, "extra.toml"), "w+"
) as extra_config_file:
toml.dump(extra_static_config, extra_config_file)
# load the extra config
2020-06-08 11:42:10 +03:00
reload_component("proxy")
2020-06-20 02:05:53 +03:00
# the new dashboard entrypoint shouldn't require authentication anymore
resp = send_request(url="http://127.0.0.1:9999/dashboard/", max_sleep=5)
2020-06-08 11:42:10 +03:00
assert resp.code == 200
# cleanup
2020-06-20 02:05:53 +03:00
os.remove(os.path.join(extra_static_config_dir, "extra.toml"))
open(os.path.join(STATE_DIR, "traefik.toml"), "w").close()
2020-06-08 11:42:10 +03:00
reload_component("proxy")
2020-06-18 17:29:50 +03:00
def test_extra_traefik_dynamic_config():
dynamic_config_dir = os.path.join(STATE_DIR, "rules")
os.makedirs(dynamic_config_dir, exist_ok=True)
2020-06-20 02:05:53 +03:00
extra_dynamic_config = {
2020-06-18 17:29:50 +03:00
"frontends": {
"test": {
"backend": "test",
2020-06-20 02:05:53 +03:00
"routes": {
"rule1": {"rule": "PathPrefixStrip: /the/hub/runs/here/too"}
},
2020-06-18 17:29:50 +03:00
}
},
"backends": {
2020-06-20 02:05:53 +03:00
# redirect to hub
"test": {"servers": {"server1": {"url": "http://127.0.0.1:15001"}}}
2020-06-18 17:29:50 +03:00
},
}
2020-06-20 02:05:53 +03:00
# write the extra dynamic config
2020-06-18 17:29:50 +03:00
with open(
os.path.join(dynamic_config_dir, "extra_rules.toml"), "w+"
) as extra_config_file:
2020-06-20 02:05:53 +03:00
toml.dump(extra_dynamic_config, extra_config_file)
# load the extra config
2020-06-18 17:29:50 +03:00
reload_component("proxy")
2020-06-20 02:05:53 +03:00
# test extra dynamic config
resp = send_request(url="http://127.0.0.1/the/hub/runs/here/too", max_sleep=5)
2020-06-18 17:29:50 +03:00
assert resp.code == 200
2020-06-20 02:05:53 +03:00
assert resp.effective_url == "http://127.0.0.1/hub/login"
2020-06-18 17:29:50 +03:00
# cleanup
2020-06-20 02:05:53 +03:00
os.remove(os.path.join(dynamic_config_dir, "extra_rules.toml"))