2018-08-28 12:09:05 +02:00
|
|
|
"""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
|
2018-08-28 12:09:05 +02:00
|
|
|
|
2020-06-18 17:29:50 +03:00
|
|
|
from tljh.config import (
|
|
|
|
|
reload_component,
|
|
|
|
|
set_config_value,
|
|
|
|
|
CONFIG_FILE,
|
|
|
|
|
CONFIG_DIR,
|
|
|
|
|
STATE_DIR,
|
|
|
|
|
)
|
2018-08-28 12:09:05 +02:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
2018-08-28 12:09:05 +02:00
|
|
|
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
|
2018-08-28 12:09:05 +02: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-21 13:55:52 +03:00
|
|
|
def test_extra_traefik_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-21 13:55:52 +03:00
|
|
|
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_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"},
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-21 13:55:52 +03:00
|
|
|
extra_dynamic_config = {
|
|
|
|
|
"frontends": {
|
|
|
|
|
"test": {
|
|
|
|
|
"backend": "test",
|
|
|
|
|
"routes": {
|
|
|
|
|
"rule1": {"rule": "PathPrefixStrip: /the/hub/runs/here/too"}
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"backends": {
|
|
|
|
|
# redirect to hub
|
|
|
|
|
"test": {"servers": {"server1": {"url": "http://127.0.0.1:15001"}}}
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-08 11:42:10 +03:00
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
# 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-21 13:55:52 +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)
|
|
|
|
|
assert resp.code == 200
|
|
|
|
|
|
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-12-23 18:02:45 +02:00
|
|
|
assert "http://127.0.0.1/hub/login" in resp.effective_url
|
2020-06-18 17:29:50 +03:00
|
|
|
|
|
|
|
|
# cleanup
|
2020-06-21 13:55:52 +03:00
|
|
|
os.remove(os.path.join(extra_static_config_dir, "extra.toml"))
|
2020-06-20 02:05:53 +03:00
|
|
|
os.remove(os.path.join(dynamic_config_dir, "extra_rules.toml"))
|
2020-06-21 13:55:52 +03:00
|
|
|
open(os.path.join(STATE_DIR, "traefik.toml"), "w").close()
|