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
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.