mirror of
https://github.com/jupyterhub/the-littlest-jupyterhub.git
synced 2025-12-18 21:54:05 +08:00
Merge pull request #395 from GeorgianaElena/admin_pass_on_setup
Set admin password during install
This commit is contained in:
@@ -72,6 +72,12 @@ jobs:
|
||||
command: |
|
||||
.circleci/integration-test.py run-test basic-tests test_hub.py test_install.py test_extensions.py
|
||||
|
||||
- run:
|
||||
name: Run admin tests
|
||||
command: |
|
||||
.circleci/integration-test.py run-test --installer-args "--admin admin:admin" basic-tests test_admin_installer.py
|
||||
|
||||
|
||||
- run:
|
||||
name: Run plugin tests
|
||||
command: |
|
||||
|
||||
@@ -43,6 +43,14 @@ The easiest & safest way to develop & test TLJH is with `Docker <https://www.doc
|
||||
|
||||
python3 /srv/src/bootstrap/bootstrap.py --admin admin
|
||||
|
||||
Or, if you would like to setup the admin's password during install,
|
||||
you can use this command (replace "admin" with the desired admin username
|
||||
and "password" with the desired admin password):
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
python3 /srv/src/bootstrap/bootstrap.py --admin admin:password
|
||||
|
||||
The primary hub environment will also be in your PATH already for convenience.
|
||||
|
||||
#. You should be able to access the JupyterHub from your browser now at
|
||||
|
||||
@@ -19,7 +19,8 @@ so attackers can not easily gain control of the system.
|
||||
.. important::
|
||||
|
||||
You should make sure an admin user is present when you **install** TLJH
|
||||
the very first time. The ``:ref:`--admin <topic/customizing-installer/admin>```
|
||||
the very first time. It is recommended that you also set a password
|
||||
for the admin at this step. The :ref:`--admin <topic/customizing-installer/admin>`
|
||||
flag passed to the installer does this. If you had forgotten to do so, the
|
||||
easiest way to fix this is to run the installer again.
|
||||
|
||||
|
||||
@@ -20,11 +20,24 @@ This page documents the various options you can pass as commandline parameters t
|
||||
Adding admin users
|
||||
===================
|
||||
|
||||
``--admin <username>`` adds user ``<username>`` to JupyterHub as an admin user.
|
||||
This can be repeated multiple times.
|
||||
``--admin <username>:<password>`` adds user ``<username>`` to JupyterHub as an admin user
|
||||
and sets its password to be ``<password>``.
|
||||
Although it is not recommended, it is possible to only set the admin username at this point
|
||||
and set the admin password after the installation.
|
||||
|
||||
For example, to add ``admin-user1`` and ``admin-user2`` as admins when installing, you
|
||||
would do:
|
||||
Also, the ``--admin`` flag can be repeated multiple times. For example, to add ``admin-user1``
|
||||
and ``admin-user2`` as admins when installing, depending if you would like to set their passwords
|
||||
during install you would:
|
||||
|
||||
* set ``admin-user1`` with password ``password-user1`` and ``admin-user2`` with ``password-user2`` using:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
curl https://raw.githubusercontent.com/jupyterhub/the-littlest-jupyterhub/master/bootstrap/bootstrap.py \
|
||||
| sudo python3 - \
|
||||
--admin admin-user1:password-user1 --admin admin-user2:password-user2
|
||||
|
||||
* set ``admin-user1`` and ``admin-user2`` to be admins, without any passwords at this stage, using:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
@@ -32,6 +45,14 @@ would do:
|
||||
| sudo python3 - \
|
||||
--admin admin-user1 --admin admin-user2
|
||||
|
||||
* set ``admin-user1`` with password ``password-user1`` and ``admin-user2`` with no password at this stage using:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
curl https://raw.githubusercontent.com/jupyterhub/the-littlest-jupyterhub/master/bootstrap/bootstrap.py \
|
||||
| sudo python3 - \
|
||||
--admin admin-user1:password-user1 --admin admin-user2
|
||||
|
||||
Installing python packages in the user environment
|
||||
==================================================
|
||||
|
||||
|
||||
45
integration-tests/test_admin_installer.py
Normal file
45
integration-tests/test_admin_installer.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from hubtraf.user import User
|
||||
from hubtraf.auth.dummy import login_dummy
|
||||
import pytest
|
||||
from functools import partial
|
||||
import asyncio
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_admin_login():
|
||||
"""
|
||||
Test if the admin that was added during install can login with
|
||||
the password provided.
|
||||
"""
|
||||
hub_url = 'http://localhost'
|
||||
username = "admin"
|
||||
password = "admin"
|
||||
|
||||
async with User(username, hub_url, partial(login_dummy, password=password)) as u:
|
||||
await u.login()
|
||||
await u.ensure_server()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
"username, password",
|
||||
[
|
||||
("admin", ""),
|
||||
("admin", "wrong_passw"),
|
||||
("user", "password"),
|
||||
],
|
||||
)
|
||||
async def test_unsuccessful_login(username, password):
|
||||
"""
|
||||
Ensure nobody but the admin that was added during install can login
|
||||
"""
|
||||
hub_url = 'http://localhost'
|
||||
|
||||
try:
|
||||
async with User(username, hub_url, partial(login_dummy, password="")) as u:
|
||||
await u.login()
|
||||
except Exception:
|
||||
# This is what we except to happen
|
||||
pass
|
||||
else:
|
||||
raise
|
||||
1
setup.py
1
setup.py
@@ -17,6 +17,7 @@ setup(
|
||||
'passlib',
|
||||
'backoff',
|
||||
'requests',
|
||||
'bcrypt',
|
||||
'jupyterhub-traefik-proxy==0.1.*'
|
||||
],
|
||||
entry_points={
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
Unit test functions in installer.py
|
||||
"""
|
||||
import os
|
||||
import pytest
|
||||
|
||||
from tljh import installer
|
||||
from tljh.yaml import yaml
|
||||
@@ -21,10 +22,17 @@ def test_ensure_config_yaml(tljh_dir):
|
||||
# verify that old config doesn't exist
|
||||
assert not os.path.exists(os.path.join(tljh_dir, 'config.yaml'))
|
||||
|
||||
def test_ensure_admins(tljh_dir):
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"admins, expected_config",
|
||||
[
|
||||
([['a1'], ['a2'], ['a3']], ['a1', 'a2', 'a3']),
|
||||
([['a1:p1'], ['a2']], ['a1', 'a2']),
|
||||
],
|
||||
)
|
||||
def test_ensure_admins(tljh_dir, admins, expected_config):
|
||||
# --admin option called multiple times on the installer
|
||||
# creates a list of argument lists.
|
||||
admins = [['a1'], ['a2'], ['a3']]
|
||||
installer.ensure_admins(admins)
|
||||
|
||||
config_path = installer.CONFIG_FILE
|
||||
@@ -32,4 +40,4 @@ def test_ensure_admins(tljh_dir):
|
||||
config = yaml.load(f)
|
||||
|
||||
# verify the list was flattened
|
||||
assert config['users']['admin'] == ['a1', 'a2', 'a3']
|
||||
assert config['users']['admin'] == expected_config
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""Installation logic for TLJH"""
|
||||
|
||||
import argparse
|
||||
import dbm
|
||||
import itertools
|
||||
import logging
|
||||
import os
|
||||
@@ -10,9 +11,11 @@ import sys
|
||||
import time
|
||||
import warnings
|
||||
|
||||
import bcrypt
|
||||
import pluggy
|
||||
import requests
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
from getpass import getpass
|
||||
|
||||
from tljh import (
|
||||
apt,
|
||||
@@ -126,8 +129,6 @@ def ensure_jupyterhub_service(prefix):
|
||||
Ensure JupyterHub Services are set up properly
|
||||
"""
|
||||
|
||||
os.makedirs(STATE_DIR, mode=0o700, exist_ok=True)
|
||||
|
||||
remove_chp()
|
||||
systemd.reload_daemon()
|
||||
|
||||
@@ -271,11 +272,13 @@ def ensure_user_environment(user_requirements_txt_file):
|
||||
conda.ensure_pip_requirements(USER_ENV_PREFIX, user_requirements_txt_file)
|
||||
|
||||
|
||||
def ensure_admins(admins):
|
||||
def ensure_admins(admin_password_list):
|
||||
"""
|
||||
Setup given list of users as admins.
|
||||
"""
|
||||
if not admins:
|
||||
os.makedirs(STATE_DIR, mode=0o700, exist_ok=True)
|
||||
|
||||
if not admin_password_list:
|
||||
return
|
||||
logger.info("Setting up admin users")
|
||||
config_path = CONFIG_FILE
|
||||
@@ -286,9 +289,22 @@ def ensure_admins(admins):
|
||||
config = {}
|
||||
|
||||
config['users'] = config.get('users', {})
|
||||
# Flatten admin lists
|
||||
config['users']['admin'] = [admin for admin_sublist in admins
|
||||
for admin in admin_sublist]
|
||||
|
||||
db_passw = os.path.join(STATE_DIR, 'passwords.dbm')
|
||||
|
||||
admins = []
|
||||
for admin_password_entry in admin_password_list:
|
||||
for admin_password_pair in admin_password_entry:
|
||||
if ":" in admin_password_pair:
|
||||
admin, password = admin_password_pair.split(':')
|
||||
admins.append(admin)
|
||||
# Add admin:password to the db
|
||||
password = bcrypt.hashpw(password.encode(), bcrypt.gensalt())
|
||||
with dbm.open(db_passw, 'c', 0o600) as db:
|
||||
db[admin] = password
|
||||
else:
|
||||
admins.append(admin_password_pair)
|
||||
config['users']['admin'] = admins
|
||||
|
||||
with open(config_path, 'w+') as f:
|
||||
yaml.dump(config, f)
|
||||
|
||||
Reference in New Issue
Block a user