URI encoding? "." character in the LDAP authentication

Hello, members.

When the user(jupyter.user contains . character) login,

  • Expect behavior: create home jupyter.user
  • Actual behavior: create home jupyter-2euser

%2E means ., in the URI encode.
So, I suspect Z2JH encodes some characters.
Does anyone know how to fix it?

hub:
  config:
    Authenticator:
      enable_auth_state: true
    JupyterHub:
      authenticator_class: ldapauthenticator.LDAPAuthenticator
    LDAPAuthenticator:
      server_address: ldapserver
      lookup_dn: True
      bind_dn_template:
        - uid={username},ou=users,dc=example,dc=com
      user_search_base: "dc=example,dc=com"
      user_attribute: uid
      lookup_dn_user_dn_attribute: uid
      escape_userdn: True
      use_ssl: true
      auth_state_attributes: ["uid", "uidNumber", "gidNumber", "homeDirectory"]
      use_lookup_dn_username: False
  extraConfig:
    SpawnerCustomConfig: |
      from ldapauthenticator import LDAPAuthenticator
      from hashlib import md5

      class LDAPAuthenticatorInfo(LDAPAuthenticator):
          async def pre_spawn_start(self, user, spawner):
              auth_state = await user.get_auth_state()

              if not auth_state:
                  return

              spawner.environment["NB_UID"]  = str(auth_state["uidNumber"][0])
              spawner.environment["NB_GID"]  = str(auth_state["gidNumber"][0])
              spawner.environment["CHOWN_HOME"]  = "yes"

      c.JupyterHub.authenticator_class = LDAPAuthenticatorInfo

    CustomHubConfig: |
      c.JupyterHub.cleanup_servers = True
singleuser:
  storage:
    type: static
    static:
      pvcName: static-pvc
      subPath: "{username}"      

I found the following line in the log. It contains jupyter-2euser.

[I 2023-12-12 13:23:37.440 JupyterHub spawner:2479] Attempting to create pod jupyter-jupyter-2euser, with timeout 3
[D 2023-12-12 13:23:37.557 JupyterHub spawner:2285] progress generator: jupyter-jupyter-2euser
[D 2023-12-12 13:23:42.112 JupyterHub spawner:2782] pod ns-z2jh/jupyter-jupyter-2euser events before launch: 2023-12-12T13:23:37.484529Z [Normal] Successfully assigned ns-z2jh/jupyter-jupyter-2euser to k8node2

pod log

[D 2023-12-12 13:23:37.237 JupyterHub ldapauthenticator:379] Attempting to bind jupyter.user with uid=jupyter.user,ou=users,dc=archsystem,dc=com
[D 2023-12-12 13:23:37.294 JupyterHub ldapauthenticator:392] Status of user bind jupyter.user with uid=jupyter.user,ou=users,dc=archsystem,dc=com : True
[D 2023-12-12 13:23:37.296 JupyterHub ldapauthenticator:462] username:jupyter.user attributes:{'uid': ['jupyter.user'], 'gidNumber': [2002], 'uidNumber': [2002], 'homeDirectory': ['/home/jupyter.user']}
[D 2023-12-12 13:23:37.299 JupyterHub roles:281] Assigning default role to User jupyter.user
[I 2023-12-12 13:23:37.305 JupyterHub roles:238] Adding role user for User: jupyter.user
[D 2023-12-12 13:23:37.317 JupyterHub roles:281] Assigning default role to User jupyter.user
[D 2023-12-12 13:23:37.338 JupyterHub base:591] Setting cookie for jupyter.user: jupyterhub-hub-login
[I 2023-12-12 13:23:37.338 JupyterHub base:837] User logged in: jupyter.user
[I 2023-12-12 13:23:37.338 JupyterHub log:191] 302 POST /hub/login?next=%2Fhub%2F -> /hub/ (jupyter.user@::ffff:10.244.6.0) 627.10ms
[D 2023-12-12 13:23:37.364 JupyterHub base:299] Recording first activity for <User(jupyter.user 0/1 running)>
[D 2023-12-12 13:23:37.373 JupyterHub user:431] Creating <class 'kubespawner.spawner.KubeSpawner'> for jupyter.user:
[I 2023-12-12 13:23:37.374 JupyterHub log:191] 302 GET /hub/ -> /hub/spawn (jupyter.user@::ffff:10.244.6.0) 12.45ms
[D 2023-12-12 13:23:37.394 JupyterHub pages:217] Triggering spawn with default options for jupyter.user
[D 2023-12-12 13:23:37.394 JupyterHub base:961] Initiating spawn for jupyter.user
[I 2023-12-12 13:23:37.413 JupyterHub provider:659] Creating oauth client jupyterhub-user-jupyter.user
[I 2023-12-12 13:23:37.429 JupyterHub log:191] 302 GET /hub/spawn -> /hub/spawn-pending/jupyter.user (jupyter.user@::ffff:10.244.6.0) 37.85ms
[D 2023-12-12 13:23:37.429 JupyterHub <string>:9] pre_spawn_start auth_state: {'uid': ['jupyter.user'], 'gidNumber': [2002], 'uidNumber': [2002], 'homeDirectory': ['/home/jupyter.user']}
[D 2023-12-12 13:23:37.436 JupyterHub user:794] Calling Spawner.start for jupyter.user
[I 2023-12-12 13:23:37.440 JupyterHub spawner:2479] Attempting to create pod jupyter-jupyter-2euser, with timeout 3
[D 2023-12-12 13:23:37.451 JupyterHub scopes:877] Checking access to /hub/spawn-pending/jupyter.user via scope servers
[D 2023-12-12 13:23:37.451 JupyterHub scopes:690] Argument-based access to /hub/spawn-pending/jupyter.user via servers
[I 2023-12-12 13:23:37.452 JupyterHub pages:398] jupyter.user is pending spawn
[I 2023-12-12 13:23:37.453 JupyterHub log:191] 200 GET /hub/spawn-pending/jupyter.user (jupyter.user@::ffff:10.244.6.0) 4.99ms
[D 2023-12-12 13:23:37.555 JupyterHub scopes:877] Checking access to /hub/api/users/jupyter.user/server/progress via scope read:servers
[D 2023-12-12 13:23:37.555 JupyterHub scopes:690] Argument-based access to /hub/api/users/jupyter.user/server/progress via read:servers
[D 2023-12-12 13:23:37.557 JupyterHub spawner:2285] progress generator: jupyter-jupyter-2euser
[D 2023-12-12 13:23:41.202 JupyterHub base:299] Recording first activity for <APIToken('17e4...', user='jupyter.user', client_id='jupyterhub')>
[D 2023-12-12 13:23:41.215 JupyterHub scopes:877] Checking access to /hub/api/users/jupyter.user/activity via scope users:activity
[D 2023-12-12 13:23:41.216 JupyterHub scopes:690] Argument-based access to /hub/api/users/jupyter.user/activity via users:activity
[D 2023-12-12 13:23:41.218 JupyterHub users:874] Activity for user jupyter.user: 2023-12-12T13:23:40.927262Z
[D 2023-12-12 13:23:41.223 JupyterHub users:892] Activity on server jupyter.user/: 2023-12-12T13:23:40.927262Z
[I 2023-12-12 13:23:41.243 JupyterHub log:191] 200 POST /hub/api/users/jupyter.user/activity (jupyter.user@10.244.4.158) 44.58ms
[D 2023-12-12 13:23:42.112 JupyterHub spawner:2782] pod ns-z2jh/jupyter-jupyter-2euser events before launch: 2023-12-12T13:23:37.484529Z [Normal] Successfully assigned ns-z2jh/jupyter-jupyter-2euser to k8node2
[D 2023-12-12 13:23:42.130 JupyterHub utils:278] Server at http://10.244.4.158:8888/user/jupyter.user/ responded with 302
[I 2023-12-12 13:23:42.131 JupyterHub base:990] User jupyter.user took 4.737 seconds to start
[I 2023-12-12 13:23:42.131 JupyterHub proxy:330] Adding user jupyter.user to proxy /user/jupyter.user/ => http://10.244.4.158:8888
[D 2023-12-12 13:23:42.131 JupyterHub proxy:880] Proxy: Fetching POST http://proxy-api:8001/api/routes/user/jupyter.user
[I 2023-12-12 13:23:42.136 JupyterHub users:768] Server jupyter.user is ready
[I 2023-12-12 13:23:42.136 JupyterHub log:191] 200 GET /hub/api/users/jupyter.user/server/progress?_xsrf=[secret] (jupyter.user@::ffff:10.244.6.0) 4583.49ms
[D 2023-12-12 13:23:42.173 JupyterHub scopes:877] Checking access to /hub/spawn-pending/jupyter.user via scope servers
[D 2023-12-12 13:23:42.173 JupyterHub scopes:690] Argument-based access to /hub/spawn-pending/jupyter.user via servers
[I 2023-12-12 13:23:42.173 JupyterHub log:191] 302 GET /hub/spawn-pending/jupyter.user -> /user/jupyter.user/ (jupyter.user@::ffff:10.244.6.0) 2.96ms
[D 2023-12-12 13:23:42.309 JupyterHub provider:420] Validating client id jupyterhub-user-jupyter.user
[D 2023-12-12 13:23:42.310 oauthlib.oauth2.rfc6749.grant_types.authorization_code authorization_code:362] Validating redirection uri /user/jupyter.user/oauth_callback for client jupyterhub-user-jupyter.user.
[D 2023-12-12 13:23:42.310 oauthlib.oauth2.rfc6749.grant_types.base base:231] Using provided redirect_uri /user/jupyter.user/oauth_callback
[D 2023-12-12 13:23:42.310 JupyterHub provider:495] validate_redirect_uri: client_id=jupyterhub-user-jupyter.user, redirect_uri=/user/jupyter.user/oauth_callback
[D 2023-12-12 13:23:42.312 oauthlib.oauth2.rfc6749.grant_types.base base:172] Validating access to scopes ['read:users:groups!user', 'access:servers!server=jupyter.user/', 'read:users:name!user'] for client 'jupyterhub-user-jupyter.user' (<OAuthClient(identifier='jupyterhub-user-jupyter.user')>).
[D 2023-12-12 13:23:42.312 JupyterHub provider:622] Allowing request for scope(s) for jupyterhub-user-jupyter.user:  read:users:name!user,read:users:groups!user,access:servers!server=jupyter.user/
[D 2023-12-12 13:23:42.313 JupyterHub auth:320] Skipping oauth confirmation for <User(jupyter.user 1/1 running)> accessing Server at /user/jupyter.user/
[D 2023-12-12 13:23:42.314 JupyterHub provider:420] Validating client id jupyterhub-user-jupyter.user
[D 2023-12-12 13:23:42.314 oauthlib.oauth2.rfc6749.grant_types.authorization_code authorization_code:362] Validating redirection uri /user/jupyter.user/oauth_callback for client jupyterhub-user-jupyter.user.
[D 2023-12-12 13:23:42.315 oauthlib.oauth2.rfc6749.grant_types.base base:231] Using provided redirect_uri /user/jupyter.user/oauth_callback
[D 2023-12-12 13:23:42.315 JupyterHub provider:495] validate_redirect_uri: client_id=jupyterhub-user-jupyter.user, redirect_uri=/user/jupyter.user/oauth_callback
[D 2023-12-12 13:23:42.316 oauthlib.oauth2.rfc6749.grant_types.base base:172] Validating access to scopes {'read:users:groups!user', 'access:servers!server=jupyter.user/', 'read:users:name!user'} for client 'jupyterhub-user-jupyter.user' (<OAuthClient(identifier='jupyterhub-user-jupyter.user')>).
[D 2023-12-12 13:23:42.316 JupyterHub provider:622] Allowing request for scope(s) for jupyterhub-user-jupyter.user:  read:users:name!user,read:users:groups!user,access:servers!server=jupyter.user/
[D 2023-12-12 13:23:42.317 JupyterHub provider:246] Saving authorization code jupyterhub-user-jupyter.user, 23d..., (), {}
[I 2023-12-12 13:23:42.337 JupyterHub log:191] 302 GET /hub/api/oauth2/authorize?client_id=jupyterhub-user-jupyter.user&redirect_uri=%2Fuser%2Fjupyter.user%2Foauth_callback&response_type=code&state=[secret] -> /user/jupyter.user/oauth_callback?code=[secret]&state=[secret] (jupyter.user@::ffff:10.244.6.0) 32.37ms
[D 2023-12-12 13:23:42.362 oauthlib.oauth2.rfc6749.grant_types.authorization_code authorization_code:533] Using provided redirect_uri /user/jupyter.user/oauth_callback
[D 2023-12-12 13:23:42.363 JupyterHub provider:116] confirm_redirect_uri: client_id=jupyterhub-user-jupyter.user, redirect_uri=/user/jupyter.user/oauth_callback
[D 2023-12-12 13:23:42.363 JupyterHub provider:344] Saving bearer token {'access_token': 'REDACTED', 'expires_in': 1209600, 'token_type': 'Bearer', 'scope': 'read:users:name!user read:users:groups!user access:servers!server=jupyter.user/', 'refresh_token': 'REDACTED'}
[D 2023-12-12 13:23:42.391 JupyterHub provider:204] Deleting oauth code 23d... for jupyterhub-user-jupyter.user
[I 2023-12-12 13:23:42.400 JupyterHub log:191] 200 POST /hub/api/oauth2/token (jupyter.user@10.244.4.158) 45.94ms
[D 2023-12-12 13:23:42.404 JupyterHub base:299] Recording first activity for <APIToken('tSzw...', user='jupyter.user', client_id='jupyterhub-user-jupyter.user')>
[I 2023-12-12 13:23:42.412 JupyterHub log:191] 200 GET /hub/api/user (jupyter.user@10.244.4.158) 9.27ms
[D 2023-12-12 13:29:09.823 JupyterHub base:344] Refreshing auth for jupyter.user
[D 2023-12-12 13:29:09.823 JupyterHub scopes:877] Checking access to /hub/api/users/jupyter.user/activity via scope users:activity
[D 2023-12-12 13:29:09.823 JupyterHub scopes:690] Argument-based access to /hub/api/users/jupyter.user/activity via users:activity
[D 2023-12-12 13:29:09.825 JupyterHub users:879] Not updating activity for <User(jupyter.user 1/1 running)>: 2023-12-12T13:24:44.105534Z < 2023-12-12T13:26:58.251000Z
[D 2023-12-12 13:29:09.825 JupyterHub users:900] Not updating server activity on jupyter.user/: 2023-12-12T13:24:44.105534Z < 2023-12-12T13:26:58.251000Z
[I 2023-12-12 13:29:09.825 JupyterHub log:191] 200 POST /hub/api/users/jupyter.user/activity (jupyter.user@10.244.4.158) 23.89ms
[D 2023-12-12 13:34:09.070 JupyterHub scopes:877] Checking access to /hub/api/users/jupyter.user/activity via scope users:activity
[D 2023-12-12 13:34:09.070 JupyterHub scopes:690] Argument-based access to /hub/api/users/jupyter.user/activity via users:activity
[D 2023-12-12 13:34:09.072 JupyterHub users:879] Not updating activity for <User(jupyter.user 1/1 running)>: 2023-12-12T13:24:44.105534Z < 2023-12-12T13:26:58.251000Z
[D 2023-12-12 13:34:09.072 JupyterHub users:900] Not updating server activity on jupyter.user/: 2023-12-12T13:24:44.105534Z < 2023-12-12T13:26:58.251000Z
[I 2023-12-12 13:34:09.073 JupyterHub log:191] 200 POST /hub/api/users/jupyter.user/activity (jupyter.user@10.244.4.158) 11.81ms
[D 2023-12-12 13:39:16.425 JupyterHub base:344] Refreshing auth for jupyter.user
[D 2023-12-12 13:39:16.426 JupyterHub scopes:877] Checking access to /hub/api/users/jupyter.user/activity via scope users:activity
[D 2023-12-12 13:39:16.426 JupyterHub scopes:690] Argument-based access to /hub/api/users/jupyter.user/activity via users:activity
[D 2023-12-12 13:39:16.428 JupyterHub users:879] Not updating activity for <User(jupyter.user 1/1 running)>: 2023-12-12T13:24:44.105534Z < 2023-12-12T13:26:58.251000Z
[D 2023-12-12 13:39:16.428 JupyterHub users:900] Not updating server activity on jupyter.user/: 2023-12-12T13:24:44.105534Z < 2023-12-12T13:26:58.251000Z
[I 2023-12-12 13:39:16.428 JupyterHub log:191] 200 POST /hub/api/users/jupyter.user/activity (jupyter.user@10.244.4.158) 23.44ms
[D 2023-12-12 13:44:26.691 JupyterHub base:344] Refreshing auth for jupyter.user
[D 2023-12-12 13:44:26.692 JupyterHub scopes:877] Checking access to /hub/api/users/jupyter.user/activity via scope users:activity
[D 2023-12-12 13:44:26.692 JupyterHub scopes:690] Argument-based access to /hub/api/users/jupyter.user/activity via users:activity
[D 2023-12-12 13:44:26.694 JupyterHub users:879] Not updating activity for <User(jupyter.user 1/1 running)>: 2023-12-12T13:24:44.105534Z < 2023-12-12T13:26:58.251000Z
[D 2023-12-12 13:44:26.694 JupyterHub users:900] Not updating server activity on jupyter.user/: 2023-12-12T13:24:44.105534Z < 2023-12-12T13:26:58.251000Z
[I 2023-12-12 13:44:26.695 JupyterHub log:191] 200 POST /hub/api/users/jupyter.user/activity (jupyter.user@10.244.4.158) 13.44ms

Environment.

  • OS: Ubuntu 22.04
  • Helm: v3.12.3
  • Kubernetes: v1.27.4 (Self-Hosted)
  • Z2JH: 3.0.2

The username is used for things like naming Kubernetes pods and volumes, so potentially problematic characters like . have to be escaped:

Hello, @manics. Thank you for your reply.

I got it.
Is it possible to use new variables in the singleuser.storage.static.subPath?
Does it use spawner.environment for setting a new variable?

I want to use a new variable only subPath (unescaped username).

Best regards.

singleuser:
  storage:
    static:
      pvcName: static-pvc
      subPath: "{unescaped_username}"    # <- Reference new variable here.

Use {unescaped_username} instead of {username} in this case.

I would like to know whether I can create a custom variable.

  storage:
    type: static
    static:
      pvcName: static-pvc
      subPath: "{unescaped_username}"

You’d need to subclass KubeSpawner to add your own custom variables.

Hello, @manics. Thank you for your help.

Now, I don’t need to create a custom class yet.

I’ll try to create a subclass KubeSpawner using this configuration example.

1 Like