mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-08 10:34:10 +00:00
Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
aa132cade7 | ||
![]() |
dd35ffbe86 | ||
![]() |
8edcf8be81 | ||
![]() |
29b02b7bcb | ||
![]() |
0383bc27b2 | ||
![]() |
65d5102b49 | ||
![]() |
8a226e6f46 | ||
![]() |
0bd34e0a10 | ||
![]() |
186107d959 | ||
![]() |
91b07b7ea4 | ||
![]() |
f5b30fd2b4 | ||
![]() |
0234396c2c | ||
![]() |
a43d677ae4 | ||
![]() |
dcfe71e7f0 | ||
![]() |
5d41376c2e | ||
![]() |
dd083359ec | ||
![]() |
e6d54960ba | ||
![]() |
a9295bc5c2 | ||
![]() |
2015c701fa | ||
![]() |
3e9c18f50a | ||
![]() |
7cac874afc | ||
![]() |
a7b6bd8d32 | ||
![]() |
1649a98656 | ||
![]() |
ecbe51f60f | ||
![]() |
fed14abed3 |
@@ -9,11 +9,24 @@ command line for details.
|
|||||||
|
|
||||||
## 0.7
|
## 0.7
|
||||||
|
|
||||||
### [0.7.1] - 2016-01-02
|
### [0.7.2] - 2017-01-09
|
||||||
|
|
||||||
#### Added
|
#### Added
|
||||||
|
|
||||||
- `Spawner.will_resume` for signalling that a single-user server is paused instead of stopped.
|
- Support service environment variables and defaults in `jupyterhub-singleuser`
|
||||||
|
for easier deployment of notebook servers as a Service.
|
||||||
|
- Add `--group` parameter for deploying `jupyterhub-singleuser` as a Service with group authentication.
|
||||||
|
- Include URL parameters when redirecting through `/user-redirect/`
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix group authentication for HubAuthenticated services
|
||||||
|
|
||||||
|
### [0.7.1] - 2017-01-02
|
||||||
|
|
||||||
|
#### Added
|
||||||
|
|
||||||
|
- `Spawner.will_resume` for signaling that a single-user server is paused instead of stopped.
|
||||||
This is needed for cases like `DockerSpawner.remove_containers = False`,
|
This is needed for cases like `DockerSpawner.remove_containers = False`,
|
||||||
where the first API token is re-used for subsequent spawns.
|
where the first API token is re-used for subsequent spawns.
|
||||||
- Warning on startup about single-character usernames,
|
- Warning on startup about single-character usernames,
|
||||||
|
@@ -405,6 +405,9 @@ You can restrict which users are allowed to login with `Authenticator.whitelist`
|
|||||||
c.Authenticator.whitelist = {'mal', 'zoe', 'inara', 'kaylee'}
|
c.Authenticator.whitelist = {'mal', 'zoe', 'inara', 'kaylee'}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Users listed in the whitelist are added to the Hub database when the Hub is
|
||||||
|
started.
|
||||||
|
|
||||||
### Managing Hub administrators
|
### Managing Hub administrators
|
||||||
|
|
||||||
Admin users of JupyterHub have the ability to take actions on users' behalf,
|
Admin users of JupyterHub have the ability to take actions on users' behalf,
|
||||||
@@ -427,12 +430,17 @@ Note: additional configuration examples are provided in this guide's
|
|||||||
|
|
||||||
### Add or remove users from the Hub
|
### Add or remove users from the Hub
|
||||||
|
|
||||||
Users can be added and removed to the Hub via the admin panel or REST API. These users will be
|
Users can be added to and removed from the Hub via either the admin panel or
|
||||||
added to the whitelist and database. Restarting the Hub will not require manually updating the
|
REST API.
|
||||||
whitelist in your config file, as the users will be loaded from the database. This means that
|
|
||||||
after starting the Hub once, it is not sufficient to remove users from the whitelist in your
|
If a user is **added**, the user will be automatically added to the whitelist
|
||||||
config file. You must also remove them from the database, either by discarding the database file,
|
and database. Restarting the Hub will not require manually updating the
|
||||||
or via the admin UI.
|
whitelist in your config file, as the users will be loaded from the database.
|
||||||
|
|
||||||
|
After starting the Hub once, it is not sufficient to **remove** a user from
|
||||||
|
the whitelist in your config file. You must also remove the user from the Hub's
|
||||||
|
database, either by deleting the user from the admin page, or you can clear
|
||||||
|
the `jupyterhub.sqlite` database and start fresh.
|
||||||
|
|
||||||
The default `PAMAuthenticator` is one case of a special kind of authenticator, called a
|
The default `PAMAuthenticator` is one case of a special kind of authenticator, called a
|
||||||
`LocalAuthenticator`, indicating that it manages users on the local system. When you add a user to
|
`LocalAuthenticator`, indicating that it manages users on the local system. When you add a user to
|
||||||
|
25
examples/service-notebook/README.md
Normal file
25
examples/service-notebook/README.md
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# Running a shared notebook as a service
|
||||||
|
|
||||||
|
This directory contains two examples of running a shared notebook server as a service,
|
||||||
|
one as a 'managed' service, and one as an external service with supervisor.
|
||||||
|
|
||||||
|
These examples require jupyterhub >= 0.7.2.
|
||||||
|
|
||||||
|
A single-user notebook server is run as a service,
|
||||||
|
and uses groups to authenticate a collection of users with the Hub.
|
||||||
|
|
||||||
|
In these examples, a JupyterHub group `'shared'` is created,
|
||||||
|
and a notebook server is spawned at `/services/shared-notebook`.
|
||||||
|
Any user in the `'shared'` group will be able to access the notebook server at `/services/shared-notebook/`.
|
||||||
|
|
||||||
|
In both examples, you will want to select the name of the group,
|
||||||
|
and the name of the shared-notebook service.
|
||||||
|
|
||||||
|
In the external example, some extra steps are required to set up supervisor:
|
||||||
|
|
||||||
|
1. select a system user to run the service. This is a user on the system, and does not need to be a Hub user. Add this to the user field in `shared-notebook.conf`, replacing `someuser`.
|
||||||
|
2. generate a secret token for authentication, and replace the `super-secret` fields in `shared-notebook-service` and `jupyterhub_config.py`
|
||||||
|
3. install `shared-notebook-service` somewhere on your system, and update `/path/to/shared-notebook-service` to the absolute path of this destination
|
||||||
|
3. copy `shared-notebook.conf` to `/etc/supervisor/conf.d/`
|
||||||
|
4. `supervisorctl reload`
|
||||||
|
|
24
examples/service-notebook/external/jupyterhub_config.py
vendored
Normal file
24
examples/service-notebook/external/jupyterhub_config.py
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# our user list
|
||||||
|
c.Authenticator.whitelist = [
|
||||||
|
'minrk',
|
||||||
|
'ellisonbg',
|
||||||
|
'willingc',
|
||||||
|
]
|
||||||
|
|
||||||
|
# ellisonbg and willingc have access to a shared server:
|
||||||
|
|
||||||
|
c.JupyterHub.load_groups = {
|
||||||
|
'shared': [
|
||||||
|
'ellisonbg',
|
||||||
|
'willingc',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
# start the notebook server as a service
|
||||||
|
c.JupyterHub.services = [
|
||||||
|
{
|
||||||
|
'name': 'shared-notebook',
|
||||||
|
'url': 'http://127.0.0.1:9999',
|
||||||
|
'api_token': 'super-secret',
|
||||||
|
}
|
||||||
|
]
|
9
examples/service-notebook/external/shared-notebook-service
vendored
Executable file
9
examples/service-notebook/external/shared-notebook-service
vendored
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash -l
|
||||||
|
set -e
|
||||||
|
|
||||||
|
export JUPYTERHUB_API_TOKEN=super-secret
|
||||||
|
export JUPYTERHUB_SERVICE_URL=http://127.0.0.1:9999
|
||||||
|
export JUPYTERHUB_SERVICE_NAME=shared-notebook
|
||||||
|
|
||||||
|
jupyterhub-singleuser \
|
||||||
|
--group='shared'
|
14
examples/service-notebook/external/shared-notebook.conf
vendored
Normal file
14
examples/service-notebook/external/shared-notebook.conf
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[program:jupyterhub-shared-notebook]
|
||||||
|
user=someuser
|
||||||
|
command=bash -l /path/to/shared-notebook-service
|
||||||
|
directory=/home/someuser
|
||||||
|
autostart=true
|
||||||
|
autorestart=true
|
||||||
|
startretries=1
|
||||||
|
exitcodes=0,2
|
||||||
|
stopsignal=TERM
|
||||||
|
redirect_stderr=true
|
||||||
|
stdout_logfile=/var/log/jupyterhub-service-shared-notebook.log
|
||||||
|
stdout_logfile_maxbytes=1MB
|
||||||
|
stdout_logfile_backups=10
|
||||||
|
stdout_capture_maxbytes=1MB
|
32
examples/service-notebook/managed/jupyterhub_config.py
Normal file
32
examples/service-notebook/managed/jupyterhub_config.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# our user list
|
||||||
|
c.Authenticator.whitelist = [
|
||||||
|
'minrk',
|
||||||
|
'ellisonbg',
|
||||||
|
'willingc',
|
||||||
|
]
|
||||||
|
|
||||||
|
# ellisonbg and willingc have access to a shared server:
|
||||||
|
|
||||||
|
c.JupyterHub.load_groups = {
|
||||||
|
'shared': [
|
||||||
|
'ellisonbg',
|
||||||
|
'willingc',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
service_name = 'shared-notebook'
|
||||||
|
service_port = 9999
|
||||||
|
group_name = 'shared'
|
||||||
|
|
||||||
|
# start the notebook server as a service
|
||||||
|
c.JupyterHub.services = [
|
||||||
|
{
|
||||||
|
'name': service_name,
|
||||||
|
'url': 'http://127.0.0.1:{}'.format(service_port),
|
||||||
|
'command': [
|
||||||
|
'jupyterhub-singleuser',
|
||||||
|
'--group=shared',
|
||||||
|
'--debug',
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]
|
@@ -571,6 +571,9 @@ class UserRedirectHandler(BaseHandler):
|
|||||||
def get(self, path):
|
def get(self, path):
|
||||||
user = self.get_current_user()
|
user = self.get_current_user()
|
||||||
url = url_path_join(user.url, path)
|
url = url_path_join(user.url, path)
|
||||||
|
if self.request.query:
|
||||||
|
# FIXME: use urlunparse instead?
|
||||||
|
url += '?' + self.request.query
|
||||||
self.redirect(url)
|
self.redirect(url)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -174,6 +174,7 @@ class HubAuth(Configurable):
|
|||||||
raise HTTPError(500, msg)
|
raise HTTPError(500, msg)
|
||||||
|
|
||||||
if r.status_code == 404:
|
if r.status_code == 404:
|
||||||
|
app_log.warning("No Hub user identified for request")
|
||||||
data = None
|
data = None
|
||||||
elif r.status_code == 403:
|
elif r.status_code == 403:
|
||||||
app_log.error("I don't have permission to verify cookies, my auth token may have expired: [%i] %s", r.status_code, r.reason)
|
app_log.error("I don't have permission to verify cookies, my auth token may have expired: [%i] %s", r.status_code, r.reason)
|
||||||
@@ -186,6 +187,7 @@ class HubAuth(Configurable):
|
|||||||
raise HTTPError(500, "Failed to check authorization")
|
raise HTTPError(500, "Failed to check authorization")
|
||||||
else:
|
else:
|
||||||
data = r.json()
|
data = r.json()
|
||||||
|
app_log.debug("Received request from Hub user %s", data)
|
||||||
self.cookie_cache[encrypted_cookie] = data
|
self.cookie_cache[encrypted_cookie] = data
|
||||||
return data
|
return data
|
||||||
|
|
||||||
@@ -274,14 +276,18 @@ class HubAuthenticated(object):
|
|||||||
Returns:
|
Returns:
|
||||||
user_model (dict): The user model if the user should be allowed, None otherwise.
|
user_model (dict): The user model if the user should be allowed, None otherwise.
|
||||||
"""
|
"""
|
||||||
|
name = user_model['name']
|
||||||
if self.hub_users is None and self.hub_groups is None:
|
if self.hub_users is None and self.hub_groups is None:
|
||||||
# no whitelist specified, allow any authenticated Hub user
|
# no whitelist specified, allow any authenticated Hub user
|
||||||
|
app_log.debug("Allowing Hub user %s (all Hub users allowed)", name)
|
||||||
return user_model
|
return user_model
|
||||||
name = user_model['name']
|
|
||||||
if self.hub_users and name in self.hub_users:
|
if self.hub_users and name in self.hub_users:
|
||||||
# user in whitelist
|
# user in whitelist
|
||||||
|
app_log.debug("Allowing whitelisted Hub user %s", name)
|
||||||
return user_model
|
return user_model
|
||||||
elif self.hub_groups and set(user_model['groups']).union(self.hub_groups):
|
elif self.hub_groups and set(user_model['groups']).intersection(self.hub_groups):
|
||||||
|
allowed_groups = set(user_model['groups']).intersection(self.hub_groups)
|
||||||
|
app_log.debug("Allowing Hub user %s in group(s) %s", name, ','.join(sorted(allowed_groups)))
|
||||||
# group in whitelist
|
# group in whitelist
|
||||||
return user_model
|
return user_model
|
||||||
else:
|
else:
|
||||||
@@ -294,8 +300,12 @@ class HubAuthenticated(object):
|
|||||||
Returns:
|
Returns:
|
||||||
user_model (dict): The user model, if a user is identified, None if authentication fails.
|
user_model (dict): The user model, if a user is identified, None if authentication fails.
|
||||||
"""
|
"""
|
||||||
|
if hasattr(self, '_hub_auth_user_cache'):
|
||||||
|
return self._hub_auth_user_cache
|
||||||
user_model = self.hub_auth.get_user(self)
|
user_model = self.hub_auth.get_user(self)
|
||||||
if not user_model:
|
if not user_model:
|
||||||
|
self._hub_auth_user_cache = None
|
||||||
return
|
return
|
||||||
return self.check_hub_user(user_model)
|
self._hub_auth_user_cache = self.check_hub_user(user_model)
|
||||||
|
return self._hub_auth_user_cache
|
||||||
|
|
||||||
|
67
jupyterhub/singleuser.py
Normal file → Executable file
67
jupyterhub/singleuser.py
Normal file → Executable file
@@ -5,6 +5,7 @@
|
|||||||
# Distributed under the terms of the Modified BSD License.
|
# Distributed under the terms of the Modified BSD License.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
from jinja2 import ChoiceLoader, FunctionLoader
|
from jinja2 import ChoiceLoader, FunctionLoader
|
||||||
|
|
||||||
@@ -21,6 +22,7 @@ from traitlets import (
|
|||||||
Unicode,
|
Unicode,
|
||||||
CUnicode,
|
CUnicode,
|
||||||
default,
|
default,
|
||||||
|
observe,
|
||||||
validate,
|
validate,
|
||||||
TraitError,
|
TraitError,
|
||||||
)
|
)
|
||||||
@@ -47,6 +49,11 @@ class HubAuthenticatedHandler(HubAuthenticated):
|
|||||||
@property
|
@property
|
||||||
def hub_users(self):
|
def hub_users(self):
|
||||||
return { self.settings['user'] }
|
return { self.settings['user'] }
|
||||||
|
@property
|
||||||
|
def hub_groups(self):
|
||||||
|
if self.settings['group']:
|
||||||
|
return { self.settings['group'] }
|
||||||
|
return set()
|
||||||
|
|
||||||
|
|
||||||
class JupyterHubLoginHandler(LoginHandler):
|
class JupyterHubLoginHandler(LoginHandler):
|
||||||
@@ -76,6 +83,7 @@ class JupyterHubLogoutHandler(LogoutHandler):
|
|||||||
aliases = dict(notebook_aliases)
|
aliases = dict(notebook_aliases)
|
||||||
aliases.update({
|
aliases.update({
|
||||||
'user' : 'SingleUserNotebookApp.user',
|
'user' : 'SingleUserNotebookApp.user',
|
||||||
|
'group': 'SingleUserNotebookApp.group',
|
||||||
'cookie-name': 'HubAuth.cookie_name',
|
'cookie-name': 'HubAuth.cookie_name',
|
||||||
'hub-prefix': 'SingleUserNotebookApp.hub_prefix',
|
'hub-prefix': 'SingleUserNotebookApp.hub_prefix',
|
||||||
'hub-host': 'SingleUserNotebookApp.hub_host',
|
'hub-host': 'SingleUserNotebookApp.hub_host',
|
||||||
@@ -118,6 +126,7 @@ def _exclude_home(path_list):
|
|||||||
if not p.startswith(home):
|
if not p.startswith(home):
|
||||||
yield p
|
yield p
|
||||||
|
|
||||||
|
|
||||||
class SingleUserNotebookApp(NotebookApp):
|
class SingleUserNotebookApp(NotebookApp):
|
||||||
"""A Subclass of the regular NotebookApp that is aware of the parent multiuser context."""
|
"""A Subclass of the regular NotebookApp that is aware of the parent multiuser context."""
|
||||||
description = dedent("""
|
description = dedent("""
|
||||||
@@ -131,12 +140,48 @@ class SingleUserNotebookApp(NotebookApp):
|
|||||||
version = __version__
|
version = __version__
|
||||||
classes = NotebookApp.classes + [HubAuth]
|
classes = NotebookApp.classes + [HubAuth]
|
||||||
|
|
||||||
user = CUnicode(config=True)
|
user = CUnicode().tag(config=True)
|
||||||
def _user_changed(self, name, old, new):
|
group = CUnicode().tag(config=True)
|
||||||
self.log.name = new
|
@observe('user')
|
||||||
hub_prefix = Unicode().tag(config=True)
|
def _user_changed(self, change):
|
||||||
|
self.log.name = change.new
|
||||||
|
|
||||||
hub_host = Unicode().tag(config=True)
|
hub_host = Unicode().tag(config=True)
|
||||||
|
|
||||||
|
hub_prefix = Unicode('/hub/').tag(config=True)
|
||||||
|
@default('hub_prefix')
|
||||||
|
def _hub_prefix_default(self):
|
||||||
|
base_url = os.environ.get('JUPYTERHUB_BASE_URL') or '/'
|
||||||
|
return base_url + 'hub/'
|
||||||
|
|
||||||
hub_api_url = Unicode().tag(config=True)
|
hub_api_url = Unicode().tag(config=True)
|
||||||
|
@default('hub_api_url')
|
||||||
|
def _hub_api_url_default(self):
|
||||||
|
return os.environ.get('JUPYTERHUB_API_URL') or 'http://127.0.0.1:8081/hub/api'
|
||||||
|
|
||||||
|
# defaults for some configurables that may come from service env variables:
|
||||||
|
@default('base_url')
|
||||||
|
def _base_url_default(self):
|
||||||
|
return os.environ.get('JUPYTERHUB_SERVICE_PREFIX') or '/'
|
||||||
|
|
||||||
|
@default('cookie_name')
|
||||||
|
def _cookie_name_default(self):
|
||||||
|
if os.environ.get('JUPYTERHUB_SERVICE_NAME'):
|
||||||
|
# if I'm a service, use the services cookie name
|
||||||
|
return 'jupyterhub-services'
|
||||||
|
|
||||||
|
@default('port')
|
||||||
|
def _port_default(self):
|
||||||
|
if os.environ.get('JUPYTERHUB_SERVICE_URL'):
|
||||||
|
url = urlparse(os.environ['JUPYTERHUB_SERVICE_URL'])
|
||||||
|
return url.port
|
||||||
|
|
||||||
|
@default('ip')
|
||||||
|
def _ip_default(self):
|
||||||
|
if os.environ.get('JUPYTERHUB_SERVICE_URL'):
|
||||||
|
url = urlparse(os.environ['JUPYTERHUB_SERVICE_URL'])
|
||||||
|
return url.hostname
|
||||||
|
|
||||||
aliases = aliases
|
aliases = aliases
|
||||||
flags = flags
|
flags = flags
|
||||||
|
|
||||||
@@ -221,11 +266,18 @@ class SingleUserNotebookApp(NotebookApp):
|
|||||||
super(SingleUserNotebookApp, self).start()
|
super(SingleUserNotebookApp, self).start()
|
||||||
|
|
||||||
def init_hub_auth(self):
|
def init_hub_auth(self):
|
||||||
if not os.environ.get('JPY_API_TOKEN'):
|
api_token = None
|
||||||
self.exit("JPY_API_TOKEN env is required to run jupyterhub-singleuser. Did you launch it manually?")
|
if os.getenv('JPY_API_TOKEN'):
|
||||||
|
# Deprecated env variable (as of 0.7.2)
|
||||||
|
api_token = os.environ.pop('JPY_API_TOKEN')
|
||||||
|
if os.getenv('JUPYTERHUB_API_TOKEN'):
|
||||||
|
api_token = os.environ.pop('JUPYTERHUB_API_TOKEN')
|
||||||
|
|
||||||
|
if not api_token:
|
||||||
|
self.exit("JUPYTERHUB_API_TOKEN env is required to run jupyterhub-singleuser. Did you launch it manually?")
|
||||||
self.hub_auth = HubAuth(
|
self.hub_auth = HubAuth(
|
||||||
parent=self,
|
parent=self,
|
||||||
api_token=os.environ.pop('JPY_API_TOKEN'),
|
api_token=api_token,
|
||||||
api_url=self.hub_api_url,
|
api_url=self.hub_api_url,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -234,6 +286,7 @@ class SingleUserNotebookApp(NotebookApp):
|
|||||||
self.init_hub_auth()
|
self.init_hub_auth()
|
||||||
s = self.tornado_settings
|
s = self.tornado_settings
|
||||||
s['user'] = self.user
|
s['user'] = self.user
|
||||||
|
s['group'] = self.group
|
||||||
s['hub_prefix'] = self.hub_prefix
|
s['hub_prefix'] = self.hub_prefix
|
||||||
s['hub_host'] = self.hub_host
|
s['hub_host'] = self.hub_host
|
||||||
s['hub_auth'] = self.hub_auth
|
s['hub_auth'] = self.hub_auth
|
||||||
|
@@ -190,7 +190,7 @@ class Spawner(LoggingConfigurable):
|
|||||||
Environment variables that end up in the single-user server's process come from 3 sources:
|
Environment variables that end up in the single-user server's process come from 3 sources:
|
||||||
- This `environment` configurable
|
- This `environment` configurable
|
||||||
- The JupyterHub process' environment variables that are whitelisted in `env_keep`
|
- The JupyterHub process' environment variables that are whitelisted in `env_keep`
|
||||||
- Variables to establish contact between the single-user notebook and the hub (such as JPY_API_TOKEN)
|
- Variables to establish contact between the single-user notebook and the hub (such as JUPYTERHUB_API_TOKEN)
|
||||||
|
|
||||||
The `enviornment` configurable should be set by JupyterHub administrators to add
|
The `enviornment` configurable should be set by JupyterHub administrators to add
|
||||||
installation specific environment variables. It is a dict where the key is the name of the environment
|
installation specific environment variables. It is a dict where the key is the name of the environment
|
||||||
@@ -415,6 +415,8 @@ class Spawner(LoggingConfigurable):
|
|||||||
else:
|
else:
|
||||||
env[key] = value
|
env[key] = value
|
||||||
|
|
||||||
|
env['JUPYTERHUB_API_TOKEN'] = self.api_token
|
||||||
|
# deprecated (as of 0.7.2), for old versions of singleuser
|
||||||
env['JPY_API_TOKEN'] = self.api_token
|
env['JPY_API_TOKEN'] = self.api_token
|
||||||
|
|
||||||
# Put in limit and guarantee info if they exist.
|
# Put in limit and guarantee info if they exist.
|
||||||
|
@@ -101,7 +101,8 @@ def test_hub_auth():
|
|||||||
def test_hub_authenticated(request):
|
def test_hub_authenticated(request):
|
||||||
auth = HubAuth(cookie_name='jubal')
|
auth = HubAuth(cookie_name='jubal')
|
||||||
mock_model = {
|
mock_model = {
|
||||||
'name': 'jubalearly'
|
'name': 'jubalearly',
|
||||||
|
'groups': ['lions'],
|
||||||
}
|
}
|
||||||
cookie_url = url_path_join(auth.api_url, "authorizations/cookie", auth.cookie_name)
|
cookie_url = url_path_join(auth.api_url, "authorizations/cookie", auth.cookie_name)
|
||||||
good_url = url_path_join(cookie_url, "early")
|
good_url = url_path_join(cookie_url, "early")
|
||||||
@@ -194,6 +195,25 @@ def test_hub_authenticated(request):
|
|||||||
assert r.status_code == 302
|
assert r.status_code == 302
|
||||||
assert auth.login_url in r.headers['Location']
|
assert auth.login_url in r.headers['Location']
|
||||||
|
|
||||||
|
# pass group whitelist
|
||||||
|
TestHandler.hub_groups = {'lions'}
|
||||||
|
r = requests.get('http://127.0.0.1:%i' % port,
|
||||||
|
cookies={'jubal': 'early'},
|
||||||
|
allow_redirects=False,
|
||||||
|
)
|
||||||
|
r.raise_for_status()
|
||||||
|
assert r.status_code == 200
|
||||||
|
|
||||||
|
# no pass group whitelist
|
||||||
|
TestHandler.hub_groups = {'tigers'}
|
||||||
|
r = requests.get('http://127.0.0.1:%i' % port,
|
||||||
|
cookies={'jubal': 'early'},
|
||||||
|
allow_redirects=False,
|
||||||
|
)
|
||||||
|
r.raise_for_status()
|
||||||
|
assert r.status_code == 302
|
||||||
|
assert auth.login_url in r.headers['Location']
|
||||||
|
|
||||||
|
|
||||||
def test_service_cookie_auth(app, mockservice_url):
|
def test_service_cookie_auth(app, mockservice_url):
|
||||||
cookies = app.login_user('badger')
|
cookies = app.login_user('badger')
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
version_info = (
|
version_info = (
|
||||||
0,
|
0,
|
||||||
7,
|
7,
|
||||||
1,
|
2,
|
||||||
# 'dev',
|
# 'dev',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user