k8s-manifests/jupyter/base/values/values.yaml

240 lines
8.4 KiB
YAML
Raw Normal View History

2023-05-03 09:19:31 +00:00
hub:
config:
Authenticator:
auto_login: true
enable_auth_state: true
JupyterHub:
tornado_settings:
headers: { 'Content-Security-Policy': "frame-ancestors *;" }
2023-09-28 06:36:09 +00:00
db:
pvc:
storageClassName: csi-sc-cinderplugin
2023-05-03 09:19:31 +00:00
extraConfig:
oauthCode: |
2024-01-13 14:47:22 +00:00
import time
2024-01-15 11:29:56 +00:00
import requests
2024-01-15 09:14:07 +00:00
from datetime import datetime
2024-01-12 09:26:03 +00:00
from oauthenticator.generic import GenericOAuthenticator
2024-01-15 13:28:39 +00:00
token_url = 'https://' + os.environ['NEXTCLOUD_HOST'] + '/index.php/apps/oauth2/api/v1/token'
2024-01-15 11:29:56 +00:00
def get_nextcloud_access_token(refresh_token):
2024-01-15 12:43:55 +00:00
debug = 'NEXTCLOUD_DEBUG_OAUTH' in os.environ
2024-01-15 11:29:56 +00:00
client_id = os.environ['NEXTCLOUD_CLIENT_ID']
client_secret = os.environ['NEXTCLOUD_CLIENT_SECRET']
code = refresh_token
data = {
2024-01-15 13:25:57 +00:00
'grant_type': 'refresh_token',
2024-01-15 11:29:56 +00:00
'code': code,
2024-01-15 11:36:00 +00:00
'refresh_token': refresh_token,
2024-01-15 11:29:56 +00:00
'client_id': client_id,
'client_secret': client_secret
}
2024-01-15 13:28:39 +00:00
response = requests.post(token_url, data=data)
2024-01-15 12:43:55 +00:00
if debug:
print(response.text)
2024-01-15 11:29:56 +00:00
return response.json()
2024-01-12 13:04:13 +00:00
def post_auth_hook(authenticator, handler, authentication):
2024-01-13 14:30:12 +00:00
user = authentication['auth_state']['oauth_user']['ocs']['data']['id']
auth_state = authentication['auth_state']
auth_state['token_expires'] = time.time() + auth_state['token_response']['expires_in']
authentication['auth_state'] = auth_state
2024-01-13 14:30:12 +00:00
return authentication
2024-01-12 13:04:13 +00:00
class NextcloudOAuthenticator(GenericOAuthenticator):
def __init__(self, *args, **kwargs):
2024-01-13 14:30:12 +00:00
super().__init__(*args, **kwargs)
self.user_dict = {}
2024-01-13 15:20:19 +00:00
async def pre_spawn_start(self, user, spawner):
2024-01-13 14:30:12 +00:00
super().pre_spawn_start(user, spawner)
2024-01-13 15:20:19 +00:00
auth_state = await user.get_auth_state()
if not auth_state:
return
access_token = auth_state['access_token']
2024-01-13 14:30:12 +00:00
spawner.environment['NEXTCLOUD_ACCESS_TOKEN'] = access_token
2024-01-13 14:30:57 +00:00
async def refresh_user(self, user, handler=None):
2024-01-15 09:14:07 +00:00
debug = 'NEXTCLOUD_DEBUG_OAUTH' in os.environ
2024-01-13 15:20:19 +00:00
auth_state = await user.get_auth_state()
if not auth_state:
2024-01-15 09:14:07 +00:00
if debug:
print(f'auth_state missing for {user}')
2024-01-13 15:20:19 +00:00
return False
access_token = auth_state['access_token']
refresh_token = auth_state['refresh_token']
2024-01-13 15:24:28 +00:00
token_response = auth_state['token_response']
2024-01-13 15:21:55 +00:00
now = time.time()
2024-01-15 09:14:07 +00:00
now_hr = datetime.fromtimestamp(now)
2024-01-13 15:24:28 +00:00
expires = auth_state['token_expires']
2024-01-15 09:14:07 +00:00
expires_hr = datetime.fromtimestamp(expires)
2024-01-15 13:12:17 +00:00
expires = 0
2024-01-15 11:07:53 +00:00
if debug:
print(f'auth_state for {user}: {auth_state}')
2024-01-13 15:21:55 +00:00
if now >= expires:
2024-01-15 09:14:07 +00:00
if debug:
print(f'Time is: {now_hr}, token expired: {expires_hr}')
2024-01-15 11:29:56 +00:00
print(f'Refreshing token for {user}')
try:
token_response = get_nextcloud_access_token(refresh_token)
auth_state['access_token'] = token_response['access_token']
auth_state['refresh_token'] = token_response['refresh_token']
auth_state['token_expires'] = now + token_response['expires_in']
auth_state['token_response'] = token_response
if debug:
2024-01-15 13:44:33 +00:00
print(f'Successfully refreshed token for {user.name}')
print(f'auth_state for {user.name}: {auth_state}')
return {'name': user.name, 'auth_state': auth_state}
2024-01-15 11:29:56 +00:00
except Exception as e:
if debug:
print(f'Failed to refresh token for {user}')
return False
2024-01-13 14:47:22 +00:00
return False
2024-01-15 09:14:07 +00:00
if debug:
print(f'Time is: {now_hr}, token expires: {expires_hr}')
2024-01-13 15:21:55 +00:00
return True
2024-01-13 14:30:57 +00:00
2024-01-12 13:04:13 +00:00
c.JupyterHub.authenticator_class = NextcloudOAuthenticator
c.NextcloudOAuthenticator.client_id = os.environ['NEXTCLOUD_CLIENT_ID']
c.NextcloudOAuthenticator.client_secret = os.environ['NEXTCLOUD_CLIENT_SECRET']
c.NextcloudOAuthenticator.login_service = 'Sunet Drive'
c.NextcloudOAuthenticator.username_claim = lambda r: r.get('ocs', {}).get('data', {}).get('id')
c.NextcloudOAuthenticator.userdata_url = 'https://' + os.environ['NEXTCLOUD_HOST'] + '/ocs/v2.php/cloud/user?format=json'
c.NextcloudOAuthenticator.authorize_url = 'https://' + os.environ['NEXTCLOUD_HOST'] + '/index.php/apps/oauth2/authorize'
2024-01-15 13:28:39 +00:00
c.NextcloudOAuthenticator.token_url = token_url
2024-01-12 13:04:13 +00:00
c.NextcloudOAuthenticator.oauth_callback_url = 'https://' + os.environ['JUPYTER_HOST'] + '/hub/oauth_callback'
c.NextcloudOAuthenticator.allow_all = True
c.NextcloudOAuthenticator.refresh_pre_spawn = True
c.NextcloudOAuthenticator.enable_auth_state = True
2024-01-15 14:03:35 +00:00
c.NextcloudOAuthenticator.auth_refresh_age = 3600
2024-01-12 13:04:13 +00:00
c.NextcloudOAuthenticator.post_auth_hook = post_auth_hook
2024-01-15 14:03:35 +00:00
serviceCode: |
2024-01-15 15:03:11 +00:00
import sys
c.JupyterHub.load_roles = [
{
"name": "refresh-token",
2024-01-15 16:26:54 +00:00
"services": [
"refresh-token"
2024-01-15 16:28:53 +00:00
],
2024-01-15 15:03:11 +00:00
"scopes": [
"admin:auth_state"
]
2024-01-15 15:42:31 +00:00
},
2024-01-15 15:39:54 +00:00
{
2024-01-15 15:55:11 +00:00
"name": "user",
2024-01-15 15:42:31 +00:00
"scopes": [
2024-01-15 16:26:54 +00:00
"access:services!service=refresh-token",
"read:services!service=refresh-token",
2024-01-15 16:05:37 +00:00
"self",
2024-01-15 15:42:31 +00:00
],
2024-01-16 08:32:21 +00:00
},
{
"name": "server",
"scopes": [
"access:services!service=refresh-token",
"read:services!service=refresh-token",
"inherit",
],
2024-01-15 15:39:54 +00:00
}
2024-01-15 15:03:11 +00:00
]
c.JupyterHub.services = [
{
'name': 'refresh-token',
2024-01-15 15:06:46 +00:00
'command': [sys.executable, '/usr/local/etc/jupyterhub/refresh-token.py']
2024-01-15 15:03:11 +00:00
}
]
2024-01-16 11:33:58 +00:00
extraFiles:
refresh-token.py:
mountPath: /usr/local/etc/jupyterhub/refresh-token.py
stringData: |
"""A token refresh service authenticating with the Hub.
This service serves `/services/refresh-token/`,
authenticated with the Hub,
showing the user their own info.
"""
import json
import os
from urllib.parse import urlparse
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from tornado.web import Application, RequestHandler, authenticated
from jupyterhub.services.auth import HubAuthenticated
class RefreshHandler(HubAuthenticated, RequestHandler):
@authenticated
def get(self):
user_model = self.get_current_user()
2024-01-16 12:39:31 +00:00
user_model = os.environ
2024-01-16 11:33:58 +00:00
self.set_header('content-type', 'application/json')
self.write(json.dumps(user_model, indent=1, sort_keys=True))
def main():
2024-01-16 12:39:31 +00:00
print(os.environ)
2024-01-16 11:33:58 +00:00
prefix = os.environ.get('JUPYTERHUB_SERVICE_PREFIX', '/')
app = Application(
[
(prefix, RefreshHandler),
(r'.*', RefreshHandler),
]
)
http_server = HTTPServer(app)
url = urlparse(os.environ['JUPYTERHUB_SERVICE_URL'])
http_server.listen(url.port, url.hostname)
IOLoop.current().start()
if __name__ == '__main__':
main()
2023-05-03 09:19:31 +00:00
extraEnv:
2024-01-15 09:14:07 +00:00
NEXTCLOUD_DEBUG_OAUTH: "yes"
2023-05-03 09:19:31 +00:00
NEXTCLOUD_HOST: sunet.drive.test.sunet.se
JUPYTER_HOST: jupyter.drive.test.sunet.se
2024-01-13 15:09:47 +00:00
JUPYTERHUB_CRYPT_KEY:
valueFrom:
secretKeyRef:
name: jupyterhub-secrets
key: crypt-key
2023-05-03 09:19:31 +00:00
NEXTCLOUD_CLIENT_ID:
valueFrom:
secretKeyRef:
name: nextcloud-oauth-secrets
key: client-id
NEXTCLOUD_CLIENT_SECRET:
valueFrom:
secretKeyRef:
name: nextcloud-oauth-secrets
key: client-secret
networkPolicy:
enabled: false
2023-05-03 09:19:31 +00:00
singleuser:
image:
name: docker.sunet.se/drive/jupyter-custom
2024-01-12 15:07:42 +00:00
tag: lab-4.0.10
2023-05-03 09:19:31 +00:00
storage:
2024-01-12 15:12:57 +00:00
dynamic:
storageClass: csi-sc-cinderplugin
2023-05-03 09:19:31 +00:00
extraEnv:
JUPYTER_ENABLE_LAB: "yes"
extraFiles:
jupyter_notebook_config:
mountPath: /home/jovyan/.jupyter/jupyter_server_config.py
stringData: |
import os
c = get_config()
c.NotebookApp.allow_origin = '*'
c.NotebookApp.tornado_settings = {
'headers': { 'Content-Security-Policy': "frame-ancestors *;" }
}
os.system('/usr/local/bin/nc-sync')
mode: 0644