I set up JupyterHub for our data science team. Our firm uses Active Directory for authentication and I wanted to leverage that. I was unable to get the Kerberos authentication method that is linked from the JupyterHub github page to work. However, I was able to cobble together something that works for me so I thought I’d share it.
The basic idea is to run kinit user@AD.DOMAIN.COM
and pipe in the password during the authenticate
call of my custom Authenticator
class, saving the resulting credential class file to a volume that is shared between the hub container and the spawned containers.
Two prerequisites are needed. First the hub container needs to install the packages, and possess the krb5.config
necessary to run kinit
. Second, the resulting kerberos credential cache file needs to be stored in a place accessible to the spawned user container, for that I used a shared volume.
With that background, the following code is my custom Authenticator
which I defined inline in the jupyterhub_config.py
file:
class KDBAuthenticator(Authenticator):
@gen.coroutine
def authenticate(self, handler, data):
user = data.get('username', 'None').lower()
self.log.info('Authenticating: ' + user)
pwrd = data['password']
realm = 'OUR.REALM.COM'
kinit = '/usr/bin/kinit'
krbcc = '/srv/jupyterlab/krb5cc_%s' % (user,) # This path is on the shared volume
kuser = '%s@%s' % (user, realm)
kinit_args = [kinit, kuser, '-c', krbcc]
pecho_args = ['echo', '-n', pwrd]
self.log.info('Running: ' + ' '.join(kinit_args))
pecho = Popen(pecho_args, stdout=PIPE)
kinit = Popen(kinit_args, stdin=pecho.stdout, stdout=PIPE, stderr=PIPE)
self.log.info(kinit.communicate())
ans = None
if os.path.isfile(krbcc):
os.chmod(krbcc, 0o666)
ans = user
return ans
There are security implications of deploying this that you may or may not be comfortable with.
I hope this helps someone else trying to do the same. If anyone has questions or comments feel free to reach out.
Matt