mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-07 10:04:07 +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)
|
orm_service.admin = spec.get('admin', False)
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
service = Service(parent=self,
|
service = Service(parent=self,
|
||||||
|
app=self,
|
||||||
base_url=self.base_url,
|
base_url=self.base_url,
|
||||||
db=self.db, orm=orm_service,
|
db=self.db, orm=orm_service,
|
||||||
domain=domain, host=host,
|
domain=domain, host=host,
|
||||||
|
@@ -41,7 +41,7 @@ from jupyterhub.traitlets import Command
|
|||||||
from traitlets.config import LoggingConfigurable
|
from traitlets.config import LoggingConfigurable
|
||||||
from .objects import Server
|
from .objects import Server
|
||||||
from . import utils
|
from . import utils
|
||||||
from .utils import url_path_join
|
from .utils import url_path_join, make_ssl_context
|
||||||
|
|
||||||
|
|
||||||
def _one_at_a_time(method):
|
def _one_at_a_time(method):
|
||||||
@@ -391,6 +391,15 @@ class ConfigurableHTTPProxy(Proxy):
|
|||||||
c.ConfigurableHTTPProxy.should_start = False
|
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()
|
proxy_process = Any()
|
||||||
client = Instance(AsyncHTTPClient, ())
|
client = Instance(AsyncHTTPClient, ())
|
||||||
|
|
||||||
@@ -432,9 +441,22 @@ class ConfigurableHTTPProxy(Proxy):
|
|||||||
token = utils.new_token()
|
token = utils.new_token()
|
||||||
return 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"""
|
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,
|
command = Command('configurable-http-proxy', config=True,
|
||||||
help="""The command to start the proxy"""
|
help="""The command to start the proxy"""
|
||||||
)
|
)
|
||||||
@@ -541,6 +563,13 @@ class ConfigurableHTTPProxy(Proxy):
|
|||||||
cmd.extend(['--ssl-key', self.ssl_key])
|
cmd.extend(['--ssl-key', self.ssl_key])
|
||||||
if self.ssl_cert:
|
if self.ssl_cert:
|
||||||
cmd.extend(['--ssl-cert', 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:
|
if self.app.statsd_host:
|
||||||
cmd.extend([
|
cmd.extend([
|
||||||
'--statsd-host', self.app.statsd_host,
|
'--statsd-host', self.app.statsd_host,
|
||||||
|
@@ -196,6 +196,27 @@ class HubAuth(SingletonConfigurable):
|
|||||||
def _default_login_url(self):
|
def _default_login_url(self):
|
||||||
return self.hub_host + url_path_join(self.hub_prefix, 'login')
|
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',
|
cookie_name = Unicode('jupyterhub-services',
|
||||||
help="""The name of the cookie I should be looking for"""
|
help="""The name of the cookie I should be looking for"""
|
||||||
).tag(config=True)
|
).tag(config=True)
|
||||||
@@ -277,6 +298,10 @@ class HubAuth(SingletonConfigurable):
|
|||||||
allow_404 = kwargs.pop('allow_404', False)
|
allow_404 = kwargs.pop('allow_404', False)
|
||||||
headers = kwargs.setdefault('headers', {})
|
headers = kwargs.setdefault('headers', {})
|
||||||
headers.setdefault('Authorization', 'token %s' % self.api_token)
|
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:
|
try:
|
||||||
r = requests.request(method, url, **kwargs)
|
r = requests.request(method, url, **kwargs)
|
||||||
except requests.ConnectionError as e:
|
except requests.ConnectionError as e:
|
||||||
|
@@ -224,6 +224,7 @@ class Service(LoggingConfigurable):
|
|||||||
domain = Unicode()
|
domain = Unicode()
|
||||||
host = Unicode()
|
host = Unicode()
|
||||||
hub = Any()
|
hub = Any()
|
||||||
|
app = Any()
|
||||||
proc = Any()
|
proc = Any()
|
||||||
|
|
||||||
# handles on globals:
|
# handles on globals:
|
||||||
@@ -331,6 +332,9 @@ class Service(LoggingConfigurable):
|
|||||||
server=self.orm.server,
|
server=self.orm.server,
|
||||||
host=self.host,
|
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.spawner.start()
|
||||||
self.proc = self.spawner.proc
|
self.proc = self.spawner.proc
|
||||||
|
@@ -237,6 +237,27 @@ class SingleUserNotebookApp(NotebookApp):
|
|||||||
def _default_group(self):
|
def _default_group(self):
|
||||||
return os.environ.get('JUPYTERHUB_GROUP') or ''
|
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')
|
@observe('user')
|
||||||
def _user_changed(self, change):
|
def _user_changed(self, change):
|
||||||
self.log.name = change.new
|
self.log.name = change.new
|
||||||
@@ -423,6 +444,9 @@ class SingleUserNotebookApp(NotebookApp):
|
|||||||
api_url=self.hub_api_url,
|
api_url=self.hub_api_url,
|
||||||
hub_prefix=self.hub_prefix,
|
hub_prefix=self.hub_prefix,
|
||||||
base_url=self.base_url,
|
base_url=self.base_url,
|
||||||
|
keyfile=self.keyfile,
|
||||||
|
certfile=self.certfile,
|
||||||
|
client_ca=self.client_ca,
|
||||||
)
|
)
|
||||||
# smoke check
|
# smoke check
|
||||||
if not self.hub_auth.oauth_client_id:
|
if not self.hub_auth.oauth_client_id:
|
||||||
|
@@ -158,6 +158,11 @@ class Spawner(LoggingConfigurable):
|
|||||||
if self.orm_spawner:
|
if self.orm_spawner:
|
||||||
return self.orm_spawner.name
|
return self.orm_spawner.name
|
||||||
return ''
|
return ''
|
||||||
|
hub = Any()
|
||||||
|
authenticator = Any()
|
||||||
|
internal_ssl = Bool(False)
|
||||||
|
internal_certs_location = Unicode('')
|
||||||
|
internal_authority_name = Unicode('')
|
||||||
admin_access = Bool(False)
|
admin_access = Bool(False)
|
||||||
api_token = Unicode()
|
api_token = Unicode()
|
||||||
oauth_client_id = Unicode()
|
oauth_client_id = Unicode()
|
||||||
|
@@ -11,7 +11,7 @@ from sqlalchemy import inspect
|
|||||||
from tornado import gen
|
from tornado import gen
|
||||||
from tornado.log import app_log
|
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 . import orm
|
||||||
from ._version import _check_version, __version__
|
from ._version import _check_version, __version__
|
||||||
@@ -215,6 +215,9 @@ class User:
|
|||||||
db=self.db,
|
db=self.db,
|
||||||
oauth_client_id=client_id,
|
oauth_client_id=client_id,
|
||||||
cookie_options = self.settings.get('cookie_options', {}),
|
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.
|
# update with kwargs. Mainly for testing.
|
||||||
spawn_kwargs.update(kwargs)
|
spawn_kwargs.update(kwargs)
|
||||||
@@ -493,7 +496,11 @@ class User:
|
|||||||
db.commit()
|
db.commit()
|
||||||
spawner._waiting_for_response = True
|
spawner._waiting_for_response = True
|
||||||
try:
|
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:
|
except Exception as e:
|
||||||
if isinstance(e, TimeoutError):
|
if isinstance(e, TimeoutError):
|
||||||
self.log.warning(
|
self.log.warning(
|
||||||
|
Reference in New Issue
Block a user