在完成JupyteHub on k8s的基本部署后,还需要一些用户定制的自定义配置,本文重点介绍JupyterHub的身份验证(Authentication)。
1. JupyteHub自带的Authentication方法
默认条件下,JupyterHub允许用户输入任意的用户名和密码,登录注册自己的Jupyter Notebook。显然这种模式不符合生产要求,必须有一套身份认证机制。
根据官网的描述,JupyterHub自带了一些身份认证方法,比如Dummy、OAuth2、LDAP等,详细信息可以参阅:
https://zero-to-jupyterhub.readthedocs.io/en/latest/authentication.html
但是如果条件不允许,JupyteHub可否支持基于常见数据库(MySQL、SQLite)的Authentication方法了?答案是肯定的,但是需要自己编写,所以接下来分别介绍基于SQLite和MySQL的身份验证方法,详细代码请参考我的https://github.com/tygxy/jupyterhub_localauthenticor
2. JupyteHub Authentication Based on SQLite
2.1 编写sqliteauthenticator包
首先需要完成sqliteauthenticator的基本功能,其包结构如图所示:
1554261481417.jpg
核心的模块就是实现SQLiteAuthenticator类,很简单,只需要从SQLite的DB中查询数据做匹配即可,我这里为了演示,密码用了明文。
# coding:utf-8
from jupyterhub.auth import Authenticator
from tornado import gen
import os
import sqlite3
class SQLiteAuthenticator(Authenticator):
"""JupyterHub Authenticator Based on SQLite"""
def __init__(self, **kwargs):
super(SQLiteAuthenticator, self).__init__(**kwargs)
@staticmethod
def _verify_password(username, password):
try:
# to define sqlite db location in hub images
os.environ["JUPYTERHUB_SQLITEDB_PATH"]="/home/jovyan/user.db"
sql_cnn = sqlite3.connect(os.getenv('JUPYTERHUB_SQLITEDB_PATH'))
cursor = sql_cnn.cursor()
sql = ("SELECT `password` FROM users WHERE `username` = '{}'").format(username)
cursor.execute(sql)
user_passwd = cursor.fetchone()[0]
input_passwd = password
if user_passwd == input_passwd:
cursor.close()
sql_cnn.close()
return True
else:
cursor.close()
sql_cnn.close()
return False
except:
cursor.close()
sql_cnn.close()
return False
@gen.coroutine
def authenticate(self, handler, data):
username = data['username']
passwd = data['password']
if self._verify_password(username, passwd):
return data['username']
else:
return None
2.2 创建SQLite用户表
第二步需要创建users表,基本操作这里就不赘述了。如果对SQLite不熟悉的同学可以网上找找资料,很简单。库名就叫user.db,表名叫users,表的结构如图所示:
1554262124230.jpg插入一条记录,以备后续验证。
insert into users (username,password) values ('kjsx-guoxingyu','123456')
2.3 拷贝内容到镜像
第三步需要把前两步的内容拷贝到jupyter/k8s-hub镜像中,这个镜像是官网自带的hub镜像,我们直接在此镜像上添加内容就可以了,步骤如下,具体的命令我就不写了,自行查找。
- docker 先启一个hub镜像,用到的命令docker run
- 查看该镜像container id,用到的命令docker ps
- 拷贝user.db到镜像中,用到的命令docker cp,注意路径要跟sqliteauthenticator.py里保持一致,我这里是/home/jovyan/
-
拷贝sqliteauthenticator包,注意路径是pip3保持包的路径。在该镜像中,是/home/jovyan/.local/lib/python3.6/site-packages下。这样运行时才能import到该包,如图:
1554270146882.jpg - 保存该镜像,用到的命令是docker commit,可以指定Tag
2.4 修改配置文件
最后需要修改一些配置文件,在values.yaml中,包括:
- auth:type: custom
- auth:custom:className: sqliteauthenticator.SQLiteAuthenticator
- hub.image.tag: 0.1.0 (需要和保存的镜像的tag匹配上,我这里是0.1.0)
2.5 启动服务
到此为止,基于SQLite的身份认证应该就可以用了,重新启动我们的jupyterhub服务,在登录页面验证一下,如图当username是kjsx-guoxingyu1的时候,显示的是Invalid username or password。
1554270759313.jpg3. JupyteHub Authentication Based on MySQL
基本上MySQL的身份认证和SQLite差不多,只有细微的差别,这里就简单叙述一下。
3.1 编写mysqlauthenticator包
包结构:
1554271023757.jpg跟之前的差不多,只不过将MySQL的一些操作封装在了DAO里,此外使用到了sqlalchemy。具体代码就不贴了,需要的话直接去我github上看吧,也很简单。稍微需要注意的就是连接MySQL的格式:
db_url = "mysql+mysqlconnector://root:<password>@<ip>:3306/<talbe_name>"
3.2 创建MySQL用户表
需要在一台服务器上提供MySQL服务,并创建User表,这个我就不多说了,相信大家都会。唯一注意的是要赋予mysql远程登陆的权限,否则镜像访问MySQL会报错。
3.3 拷贝内容到镜像
这个跟之前的一样,把mysqlauthenticator包放在pip3的安装路径下,此外还需要安装一些包,包括
- pip3 install wheel
- pip3 install sqlalchemy
- pip3 install mysql-connector
3.4 修改配置文件
- auth:type: custom
- auth:custom:className: mysqlauthenticator.MysqlAuthenticator
- hub.image.tag: 0.1.0 (需要和保存的镜像的tag匹配上,我这里是0.1.0)
3.5 启动服务
效果一样,这里贴一张认证成功的效果
1554271904139.jpg4. 总结
整体来说,这部分自定义身份认证的参考资料很少,只能自己摸索和试错。所以我也花了一些时间。两种基于SQLite和MySQL的JupyterHub认证方式我都在自己Mac上,和服务器的测试集群上试过,均可用。当然这里也只是一个demo,更成熟可靠的代码,还需要进一步迭代,希望帮助到大家。
网友评论