mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-07 18:14:10 +00:00
Propagate certs to everything that needs them
This commit is contained in:
@@ -1379,6 +1379,7 @@ class JupyterHub(Application):
|
||||
orm_service.admin = spec.get('admin', False)
|
||||
self.db.commit()
|
||||
service = Service(parent=self,
|
||||
app=self,
|
||||
base_url=self.base_url,
|
||||
db=self.db, orm=orm_service,
|
||||
domain=domain, host=host,
|
||||
|
@@ -41,7 +41,7 @@ from jupyterhub.traitlets import Command
|
||||
from traitlets.config import LoggingConfigurable
|
||||
from .objects import Server
|
||||
from . import utils
|
||||
from .utils import url_path_join
|
||||
from .utils import url_path_join, make_ssl_context
|
||||
|
||||
|
||||
def _one_at_a_time(method):
|
||||
@@ -391,6 +391,15 @@ class ConfigurableHTTPProxy(Proxy):
|
||||
c.ConfigurableHTTPProxy.should_start = False
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
ssl_context = make_ssl_context(
|
||||
self.app.internal_ssl_key,
|
||||
self.app.internal_ssl_cert,
|
||||
cafile=self.app.internal_ssl_ca,
|
||||
)
|
||||
AsyncHTTPClient.configure(None, defaults={"ssl_options" : ssl_context})
|
||||
|
||||
proxy_process = Any()
|
||||
client = Instance(AsyncHTTPClient, ())
|
||||
|
||||
@@ -432,9 +441,22 @@ class ConfigurableHTTPProxy(Proxy):
|
||||
token = utils.new_token()
|
||||
return token
|
||||
|
||||
api_url = Unicode('http://127.0.0.1:8001', config=True,
|
||||
api_url = Unicode(config=True,
|
||||
help="""The ip (or hostname) of the proxy's API endpoint"""
|
||||
)
|
||||
|
||||
@default('api_url')
|
||||
def _api_url_default(self):
|
||||
url = '127.0.0.1:8001'
|
||||
proto = 'http'
|
||||
if self.app.internal_ssl:
|
||||
proto = 'https'
|
||||
|
||||
return "{proto}://{url}".format(
|
||||
proto=proto,
|
||||
url=url,
|
||||
)
|
||||
|
||||
command = Command('configurable-http-proxy', config=True,
|
||||
help="""The command to start the proxy"""
|
||||
)
|
||||
@@ -541,6 +563,13 @@ class ConfigurableHTTPProxy(Proxy):
|
||||
cmd.extend(['--ssl-key', self.ssl_key])
|
||||
if self.ssl_cert:
|
||||
cmd.extend(['--ssl-cert', self.ssl_cert])
|
||||
if self.app.internal_ssl:
|
||||
cmd.extend(['--api-ssl-key', self.app.internal_ssl_key])
|
||||
cmd.extend(['--api-ssl-cert', self.app.internal_ssl_cert])
|
||||
cmd.extend(['--api-ssl-ca', self.app.internal_ssl_ca])
|
||||
cmd.extend(['--api-ssl-request-cert'])
|
||||
cmd.extend(['--api-ssl-reject-unauthorized'])
|
||||
cmd.extend(['--forward-ssl'])
|
||||
if self.app.statsd_host:
|
||||
cmd.extend([
|
||||
'--statsd-host', self.app.statsd_host,
|
||||
|
@@ -196,6 +196,27 @@ class HubAuth(SingletonConfigurable):
|
||||
def _default_login_url(self):
|
||||
return self.hub_host + url_path_join(self.hub_prefix, 'login')
|
||||
|
||||
keyfile = Unicode('',
|
||||
help="""The ssl key to use for requests
|
||||
|
||||
Use with certfile
|
||||
"""
|
||||
).tag(config=True)
|
||||
|
||||
certfile = Unicode('',
|
||||
help="""The ssl cert to use for requests
|
||||
|
||||
Use with keyfile
|
||||
"""
|
||||
).tag(config=True)
|
||||
|
||||
client_ca = Unicode('',
|
||||
help="""The ssl certificate authority to use to verify requests
|
||||
|
||||
Use with keyfile and certfile
|
||||
"""
|
||||
).tag(config=True)
|
||||
|
||||
cookie_name = Unicode('jupyterhub-services',
|
||||
help="""The name of the cookie I should be looking for"""
|
||||
).tag(config=True)
|
||||
@@ -277,6 +298,10 @@ class HubAuth(SingletonConfigurable):
|
||||
allow_404 = kwargs.pop('allow_404', False)
|
||||
headers = kwargs.setdefault('headers', {})
|
||||
headers.setdefault('Authorization', 'token %s' % self.api_token)
|
||||
if "cert" not in kwargs and self.certfile and self.keyfile:
|
||||
kwargs["cert"] = (self.certfile, self.keyfile)
|
||||
if self.client_ca:
|
||||
kwargs["verify"] = self.client_ca
|
||||
try:
|
||||
r = requests.request(method, url, **kwargs)
|
||||
except requests.ConnectionError as e:
|
||||
|
@@ -224,6 +224,7 @@ class Service(LoggingConfigurable):
|
||||
domain = Unicode()
|
||||
host = Unicode()
|
||||
hub = Any()
|
||||
app = Any()
|
||||
proc = Any()
|
||||
|
||||
# handles on globals:
|
||||
@@ -331,6 +332,9 @@ class Service(LoggingConfigurable):
|
||||
server=self.orm.server,
|
||||
host=self.host,
|
||||
),
|
||||
internal_ssl=self.app.internal_ssl,
|
||||
internal_certs_location=self.app.internal_certs_location,
|
||||
internal_authority_name=self.app.internal_authority_name,
|
||||
)
|
||||
self.spawner.start()
|
||||
self.proc = self.spawner.proc
|
||||
|
@@ -237,6 +237,27 @@ class SingleUserNotebookApp(NotebookApp):
|
||||
def _default_group(self):
|
||||
return os.environ.get('JUPYTERHUB_GROUP') or ''
|
||||
|
||||
keyfile = Unicode('',
|
||||
help="""The ssl key to use for requests
|
||||
|
||||
Use with certfile
|
||||
"""
|
||||
).tag(config=True)
|
||||
|
||||
certfile = Unicode('',
|
||||
help="""The ssl cert to use for requests
|
||||
|
||||
Use with keyfile
|
||||
"""
|
||||
).tag(config=True)
|
||||
|
||||
client_ca = Unicode('',
|
||||
help="""The ssl certificate authority to use to verify requests
|
||||
|
||||
Use with keyfile and certfile
|
||||
"""
|
||||
).tag(config=True)
|
||||
|
||||
@observe('user')
|
||||
def _user_changed(self, change):
|
||||
self.log.name = change.new
|
||||
@@ -423,6 +444,9 @@ class SingleUserNotebookApp(NotebookApp):
|
||||
api_url=self.hub_api_url,
|
||||
hub_prefix=self.hub_prefix,
|
||||
base_url=self.base_url,
|
||||
keyfile=self.keyfile,
|
||||
certfile=self.certfile,
|
||||
client_ca=self.client_ca,
|
||||
)
|
||||
# smoke check
|
||||
if not self.hub_auth.oauth_client_id:
|
||||
|
@@ -158,6 +158,11 @@ class Spawner(LoggingConfigurable):
|
||||
if self.orm_spawner:
|
||||
return self.orm_spawner.name
|
||||
return ''
|
||||
hub = Any()
|
||||
authenticator = Any()
|
||||
internal_ssl = Bool(False)
|
||||
internal_certs_location = Unicode('')
|
||||
internal_authority_name = Unicode('')
|
||||
admin_access = Bool(False)
|
||||
api_token = Unicode()
|
||||
oauth_client_id = Unicode()
|
||||
|
@@ -11,7 +11,7 @@ from sqlalchemy import inspect
|
||||
from tornado import gen
|
||||
from tornado.log import app_log
|
||||
|
||||
from .utils import maybe_future, url_path_join
|
||||
from .utils import maybe_future, url_path_join, make_ssl_context
|
||||
|
||||
from . import orm
|
||||
from ._version import _check_version, __version__
|
||||
@@ -215,6 +215,9 @@ class User:
|
||||
db=self.db,
|
||||
oauth_client_id=client_id,
|
||||
cookie_options = self.settings.get('cookie_options', {}),
|
||||
internal_ssl=self.settings.get('internal_ssl'),
|
||||
internal_certs_location=self.settings.get('internal_certs_location'),
|
||||
internal_authority_name=self.settings.get('internal_authority_name'),
|
||||
)
|
||||
# update with kwargs. Mainly for testing.
|
||||
spawn_kwargs.update(kwargs)
|
||||
@@ -493,7 +496,11 @@ class User:
|
||||
db.commit()
|
||||
spawner._waiting_for_response = True
|
||||
try:
|
||||
resp = await server.wait_up(http=True, timeout=spawner.http_timeout)
|
||||
key = self.settings['internal_ssl_key']
|
||||
cert = self.settings['internal_ssl_cert']
|
||||
ca = self.settings['internal_ssl_ca']
|
||||
ssl_context = make_ssl_context(key, cert, cafile=ca)
|
||||
resp = await server.wait_up(http=True, timeout=spawner.http_timeout, ssl_context=ssl_context)
|
||||
except Exception as e:
|
||||
if isinstance(e, TimeoutError):
|
||||
self.log.warning(
|
||||
|
Reference in New Issue
Block a user