Creating an admin user automatically with NativeAuthenticator

So here’s my situation. I’m provisioning JupyterHub on a Kubernetes cluster using the helm chart (version 1.2.0) which uses the docker image (jupyterhub/k8s-hub:1.2.0). I’m using NativeAuthenticator.

I’ve configured the app such that I’ve made the user with name “root_admin” a valid admin in JupyterHub.

Now my trouble comes from how I can setup this user’s credentials. I want to use secrets provisioned separately so ideally I don’t want to use the UI.

From what I’ve learned, I can use adduser command to add a user. Which is great for the moment, but the docker container starts with the user jovyan so now I don’t have inherent root access to create the new user. I can potentially have the docker container run as root but that can always cause problems down the line. The other thing I’ve thought of is creating a user in the dockerfile who only has permissions to create user accounts, that way we can use this user to create the JuypterHub admin account, only that I don’t know 1 if this is possible or 2 if it poses any security risks.

So I’ve gone back to the original issue where I am unable to automatically create the admin account.

Are there any tips for this? Or advice as to how others provision JupyterHub for their org? Any thoughts or advice will be helpful.

Thanks in advance!

I don’t believe adduser will be relevant. NativeAuthenticator has a bit of a confusing name, because there’s more than one thing it could be native to. It’s not native to the system (system users are ignored), it’s native to jupyterhub (i.e. a totally internal user/password db).

I don’t believe NativeAuthenticator has support for pre-populating the password db. I think this is a reasonable feature request to add a ‘preload passwords’ feature.

But once you have launched NativeAuthenticator, you can add users and passwords with python -m jupyterhub.dbutil shell interactively attached to a running Hub:

kubectl exec -it hub-.... -- bash
# in pod
pip install ipython # needed for dbutil.shell
ipython
# in IPython
from nativeauthenticator import NativeAuthenticator
auth = NativeAuthenticator(db=db) # db variable is pre-populated in the shell
auth.create_user("username", "password")

Or you could create the UserInfo record directly, if you want to only store the bcrypt-hashed password, instead of needing to store the cleartext password at any point:

First, create encrypted fields to be stored at rest

import bcrypt
username = "username"
hashed_password = bcrypt.hashpw("cleartext password".encode(), bcrypt.gensalt())

Then add them to the db (again, following dbutil.shell above, or by running a Python script that connects an sqlalchemy session to db_url, which is `jupyterhub):

# connect to db if not using jupyterhub.dbutil shell
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

from nativeauthenticator.orm import UserInfo

db_url = "sqlite:///jupyterhub.sqlite" # may be different!
db = sessionmaker(bind=create_engine(db_url))()


# create user (or iterate through list of users!)
user = UserInfo(username=username, password=hashed_password)
db.add(user)
db.commit()

A handy way to run Python scripts in a pod, from the host in kubernetes:

cat script.py | kubectl exec -i hub-... - python3
2 Likes