From 00f0dc0d6b9f54571898e95d29b08a8d520c8e6a Mon Sep 17 00:00:00 2001 From: Masaki Yatsu Date: Sat, 6 Sep 2025 20:56:15 +0900 Subject: [PATCH] fix(jupyterhub): setting token ttl --- jupyterhub/jupyterhub-values.gomplate.yaml | 36 +++++++++++++++++++--- jupyterhub/justfile | 14 +++++---- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/jupyterhub/jupyterhub-values.gomplate.yaml b/jupyterhub/jupyterhub-values.gomplate.yaml index 2003471..30098e8 100644 --- a/jupyterhub/jupyterhub-values.gomplate.yaml +++ b/jupyterhub/jupyterhub-values.gomplate.yaml @@ -1,6 +1,10 @@ hub: extraEnv: JUPYTERHUB_CRYPT_KEY: {{ .Env.JUPYTERHUB_CRYPT_KEY | quote }} + JUPYTERHUB_VAULT_TOKEN: {{ .Env.JUPYTERHUB_VAULT_TOKEN | quote }} + VAULT_ADDR: {{ .Env.VAULT_ADDR | quote }} + NOTEBOOK_VAULT_TOKEN_TTL: {{ .Env.NOTEBOOK_VAULT_TOKEN_TTL | quote }} + NOTEBOOK_VAULT_TOKEN_MAX_TTL: {{ .Env.NOTEBOOK_VAULT_TOKEN_MAX_TTL | quote }} # Install packages at container startup extraFiles: @@ -70,8 +74,16 @@ hub: username = spawner.user.name # Step 1: Initialize admin Vault client - vault_client = hvac.Client(url="{{ .Env.VAULT_ADDR }}", verify=False) - vault_client.token = "{{ .Env.JUPYTERHUB_VAULT_TOKEN }}" + import os + vault_addr = os.environ.get("VAULT_ADDR", "{{ .Env.VAULT_ADDR }}") + vault_token = os.environ.get("JUPYTERHUB_VAULT_TOKEN", "{{ .Env.JUPYTERHUB_VAULT_TOKEN }}") + + spawner.log.info(f"pre_spawn_hook starting for {username}") + spawner.log.info(f"Vault address: {vault_addr}") + spawner.log.info(f"Vault token present: {bool(vault_token)}, length: {len(vault_token) if vault_token else 0}") + + vault_client = hvac.Client(url=vault_addr, verify=False) + vault_client.token = vault_token if not vault_client.is_authenticated(): raise Exception("Admin token is not authenticated") @@ -96,11 +108,16 @@ hub: spawner.log.warning("Policy creation failed (may already exist): {}".format(policy_e)) # Step 3: Create user-specific token + # Get TTL settings from environment variables + user_token_ttl = os.environ.get("NOTEBOOK_VAULT_TOKEN_TTL", "24h") + user_token_max_ttl = os.environ.get("NOTEBOOK_VAULT_TOKEN_MAX_TTL", "168h") + token_response = vault_client.auth.token.create( policies=[user_policy_name], - ttl="1h", + ttl=user_token_ttl, renewable=True, - display_name="notebook-{}".format(username) + display_name="notebook-{}".format(username), + explicit_max_ttl=user_token_max_ttl ) user_vault_token = token_response["auth"]["client_token"] @@ -109,7 +126,7 @@ hub: # Set user-specific Vault token as environment variable spawner.environment["NOTEBOOK_VAULT_TOKEN"] = user_vault_token - spawner.log.info("✅ User-specific Vault token created for {} (expires in {}s, renewable)".format(username, lease_duration)) + spawner.log.info("✅ User-specific Vault token created for {} (TTL: {}s, renewable, max TTL: {})".format(username, lease_duration, user_token_max_ttl)) except Exception as e: spawner.log.error("Failed to create user-specific Vault token for {}: {}".format(spawner.user.name, e)) @@ -266,8 +283,17 @@ singleuser: cull: enabled: true + + # for production timeout: 7200 # 2 hours idle timeout every: 600 # Check every 10 minutes + + # for testing + # timeout: 300 # 5 minutes idle timeout (for testing) │ │ + # every: 60 # Check every 1 minute (for testing) │ │ + + # maxAge: 86400 # Maximum age of a server pod (1 day) + adminUsers: true # Also cull admin users' server pods users: false # Don't delete user accounts, only stop server pods diff --git a/jupyterhub/justfile b/jupyterhub/justfile index f5e58ea..7218707 100644 --- a/jupyterhub/justfile +++ b/jupyterhub/justfile @@ -8,7 +8,7 @@ export JUPYTERHUB_OIDC_CLIENT_SESSION_MAX := env("JUPYTERHUB_OIDC_CLIENT_SESSION export JUPYTERHUB_NFS_PV_ENABLED := env("JUPYTERHUB_NFS_PV_ENABLED", "") export JUPYTERHUB_STORAGE_CLASS := env("JUPYTERHUB_STORAGE_CLASS", "") export JUPYTERHUB_VAULT_INTEGRATION_ENABLED := env("JUPYTERHUB_VAULT_INTEGRATION_ENABLED", "") -export JUPYTER_PYTHON_KERNEL_TAG := env("JUPYTER_PYTHON_KERNEL_TAG", "python-3.12-24") +export JUPYTER_PYTHON_KERNEL_TAG := env("JUPYTER_PYTHON_KERNEL_TAG", "python-3.12-28") export KERNEL_IMAGE_BUUN_STACK_REPOSITORY := env("KERNEL_IMAGE_BUUN_STACK_REPOSITORY", "buun-stack-notebook") export KERNEL_IMAGE_BUUN_STACK_CUDA_REPOSITORY := env("KERNEL_IMAGE_BUUN_STACK_CUDA_REPOSITORY", "buun-stack-cuda-notebook") export JUPYTER_PROFILE_MINIMAL_ENABLED := env("JUPYTER_PROFILE_MINIMAL_ENABLED", "false") @@ -20,8 +20,10 @@ export JUPYTER_PROFILE_TENSORFLOW_ENABLED := env("JUPYTER_PROFILE_TENSORFLOW_ENA export JUPYTER_PROFILE_BUUN_STACK_ENABLED := env("JUPYTER_PROFILE_BUUN_STACK_ENABLED", "false") export JUPYTER_PROFILE_BUUN_STACK_CUDA_ENABLED := env("JUPYTER_PROFILE_BUUN_STACK_CUDA_ENABLED", "false") export IMAGE_REGISTRY := env("IMAGE_REGISTRY", "localhost:30500") -export NOTEBOOK_VAULT_TOKEN_TTL := env("NOTEBOOK_VAULT_TOKEN_TTL", "1h") -export NOTEBOOK_VAULT_TOKEN_MAX_TTL := env("NOTEBOOK_VAULT_TOKEN_MAX_TTL", "720h") +export JUPYTERHUB_VAULT_TOKEN_TTL := env("JUPYTERHUB_VAULT_TOKEN_TTL", "720h") # 30 days +export JUPYTERHUB_VAULT_TOKEN_MAX_TTL := env("JUPYTERHUB_VAULT_TOKEN_MAX_TTL", "8760h") # 1 year +export NOTEBOOK_VAULT_TOKEN_TTL := env("NOTEBOOK_VAULT_TOKEN_TTL", "24h") # 1 day +export NOTEBOOK_VAULT_TOKEN_MAX_TTL := env("NOTEBOOK_VAULT_TOKEN_MAX_TTL", "168h") # 7 days export KEYCLOAK_REALM := env("KEYCLOAK_REALM", "buunstack") export LONGHORN_NAMESPACE := env("LONGHORN_NAMESPACE", "longhorn") export VAULT_ADDR := env("VAULT_ADDR", "http://vault.vault.svc:8200") @@ -221,12 +223,12 @@ create-jupyterhub-vault-token: #!/bin/bash set -euo pipefail echo "Creating JupyterHub Vault token with admin policy..." - echo " TTL: ${NOTEBOOK_VAULT_TOKEN_TTL}" - echo " Max TTL: ${NOTEBOOK_VAULT_TOKEN_MAX_TTL}" + echo " TTL: ${JUPYTERHUB_VAULT_TOKEN_TTL}" + echo " Max TTL: ${JUPYTERHUB_VAULT_TOKEN_MAX_TTL}" # JupyterHub needs admin privileges to read Keycloak credentials from Vault # Create token and store in Vault - just vault::create-token-and-store admin jupyterhub/vault-token ${NOTEBOOK_VAULT_TOKEN_TTL} ${NOTEBOOK_VAULT_TOKEN_MAX_TTL} + just vault::create-token-and-store admin jupyterhub/vault-token ${JUPYTERHUB_VAULT_TOKEN_TTL} ${JUPYTERHUB_VAULT_TOKEN_MAX_TTL} echo "✓ JupyterHub Vault token created and stored" echo ""