Code Monkey home page Code Monkey logo

ldapauthenticator's Introduction

ldapauthenticator

Latest PyPI version Latest conda-forge version GitHub Workflow Status - Test Test coverage of code Issue tracking - GitHub Help forum - Discourse

Simple LDAP Authenticator Plugin for JupyterHub

Installation

You can install it from pip with:

pip install jupyterhub-ldapauthenticator

...or using conda with:

conda install -c conda-forge jupyterhub-ldapauthenticator

Logging people out

If you make any changes to JupyterHub's authentication setup that changes which group of users is allowed to login (such as changing allowed_groups or even just turning on LDAPAuthenticator), you must change the jupyterhub cookie secret, or users who were previously logged in and did not log out would continue to be able to log in!

You can do this by deleting the jupyterhub_cookie_secret file. Note that this will log out all users who are currently logged in.

Usage

You can enable this authenticator with the following lines in your jupyter_config.py:

c.JupyterHub.authenticator_class = 'ldapauthenticator.LDAPAuthenticator'

Required configuration

At minimum, the following two configuration options must be set before the LDAP Authenticator can be used:

LDAPAuthenticator.server_address

Address of the LDAP Server to contact. Just use a bare hostname or IP, without a port name or protocol prefix.

LDAPAuthenticator.lookup_dn or LDAPAuthenticator.bind_dn_template

To authenticate a user we need the corresponding DN to bind against the LDAP server. The DN can be acquired by either:

  1. setting bind_dn_template, which is a list of string template used to generate the full DN for a user from the human readable username, or
  2. setting lookup_dn to True, which does a reverse lookup to obtain the user's DN. This is because ome LDAP servers, such as Active Directory, don't always bind with the true DN.
lookup_dn = False

If lookup_dn = False, then bind_dn_template is required to be a non-empty list of templates the users belong to. For example, if some of the users in your LDAP database have DN of the form uid=Yuvipanda,ou=people,dc=wikimedia,dc=org and some other users have DN like uid=Mike,ou=developers,dc=wikimedia,dc=org where Yuvipanda and Mike are the usernames, you would set this config item to be:

c.LDAPAuthenticator.bind_dn_template = [
    "uid={username},ou=people,dc=wikimedia,dc=org",
    "uid={username},ou=developers,dc=wikimedia,dc=org",
]

Don't forget the preceeding c. for setting configuration parameters! JupyterHub uses traitlets for configuration, and the c represents the config object.

The {username} is expanded into the username the user provides.

lookup_dn = True
c.LDAPAuthenticator.lookup_dn = True

If bind_dn_template isn't explicitly configured, i.e. the empty list, the dynamically acquired value for DN from the username lookup will be used instead. If bind_dn_template is configured it will be used just like in the lookup_dn = False case.

The {username} is expanded to the full path to the LDAP object returned by the LDAP lookup. For example, on an Active Directory system {username} might expand to something like CN=First M. Last,OU=An Example Organizational Unit,DC=EXAMPLE,DC=COM.

Also, when using lookup_dn = True the options user_search_base, user_attribute, lookup_dn_user_dn_attribute and lookup_dn_search_filter are required, although their defaults might be sufficient for your use case.

Optional configuration

LDAPAuthenticator.allowed_groups

LDAP groups whose members are allowed to log in. This must be set to either empty [] (the default, to disable) or to a list of full DNs that have a member attribute that includes the current user attempting to log in.

As an example, to restrict access only to people in groups researcher or operations,

c.LDAPAuthenticator.allowed_groups = [
    "cn=researcher,ou=groups,dc=wikimedia,dc=org",
    "cn=operations,ou=groups,dc=wikimedia,dc=org",
]

LDAPAuthenticator.valid_username_regex

All usernames will be checked against this before being sent to LDAP. This acts as both an easy way to filter out invalid usernames as well as protection against LDAP injection attacks.

By default it looks for the regex ^[a-z][.a-z0-9_-]*$ which is what most shell username validators do.

LDAPAuthenticator.use_ssl

Boolean to specify whether to use SSL encryption when contacting the LDAP server. If it is left to False (the default) LDAPAuthenticator will try to upgrade connection with StartTLS. Set this to be True to start SSL connection.

LDAPAuthenticator.server_port

Port to use to contact the LDAP server. Defaults to 389 if no SSL is being used, and 636 is SSL is being used.

LDAPAuthenticator.user_search_base

Only used with lookup_dn=True. Defines the search base for looking up users in the directory.

c.LDAPAuthenticator.user_search_base = 'ou=People,dc=example,dc=com'

LDAPAuthenticator.user_attribute

Only used with lookup_dn=True. Defines the attribute that stores a user's username in your directory.

# Active Directory
c.LDAPAuthenticator.user_attribute = 'sAMAccountName'

# OpenLDAP
c.LDAPAuthenticator.user_attribute = 'uid'

LDAPAuthenticator.lookup_dn_search_filter

How to query LDAP for user name lookup, if lookup_dn is set to True. Default value '({login_attr}={login})' should be good enough for most use cases.

LDAPAuthenticator.lookup_dn_search_user, LDAPAuthenticator.lookup_dn_search_password

Technical account for user lookup, if lookup_dn is set to True. If both lookup_dn_search_user and lookup_dn_search_password are None, then anonymous LDAP query will be done.

LDAPAuthenticator.lookup_dn_user_dn_attribute

Attribute containing user's name needed for building DN string, if lookup_dn is set to True. See user_search_base for info on how this attribute is used. For most LDAP servers, this is username. For Active Directory, it is cn.

LDAPAuthenticator.escape_userdn

If set to True, escape special chars in userdn when authenticating in LDAP. On some LDAP servers, when userdn contains chars like '(', ')', '' authentication may fail when those chars are not escaped.

LDAPAuthenticator.auth_state_attributes

An optional list of attributes to be fetched for a user after login. If found these will be returned as auth_state.

LDAPAuthenticator.use_lookup_dn_username

If set to True (the default) the username used to build the DN string is returned as the username when lookup_dn is True.

When authenticating on a Linux machine against an AD server this might return something different from the supplied UNIX username. In this case setting this option to False might be a solution.

Compatibility

This has been tested against an OpenLDAP server, with the client running Python 3.4. Verifications of this code working well with other LDAP setups are welcome, as are bug reports and patches to make it work with other LDAP setups!

Active Directory integration

Please use following options for AD integration. This is useful especially in two cases:

  • LDAP Search requires valid user account in order to query user database
  • DN does not contain login but some other field, like CN (actual login is present in sAMAccountName, and we need to lookup CN)
c.LDAPAuthenticator.lookup_dn = True
c.LDAPAuthenticator.lookup_dn_search_filter = '({login_attr}={login})'
c.LDAPAuthenticator.lookup_dn_search_user = 'ldap_search_user_technical_account'
c.LDAPAuthenticator.lookup_dn_search_password = 'secret'
c.LDAPAuthenticator.user_search_base = 'ou=people,dc=wikimedia,dc=org'
c.LDAPAuthenticator.user_attribute = 'sAMAccountName'
c.LDAPAuthenticator.lookup_dn_user_dn_attribute = 'cn'
c.LDAPAuthenticator.escape_userdn = False
c.LDAPAuthenticator.bind_dn_template = '{username}'

In setup above, first LDAP will be searched (with account ldap_search_user_technical_account) for users that have sAMAccountName=login Then DN will be constructed using found CN value.

Configuration note on local user creation

Currently, local user creation by the LDAPAuthenticator is unsupported as this is insecure since there's no cleanup method for these created users. As a result, users who are disabled in LDAP will have access to this for far longer.

Alternatively, there's good support in Linux for integrating LDAP into the system user setup directly, and users can just use PAM (which is supported in not just JupyterHub, but ssh and a lot of other tools) to log in. You can see http://www.tldp.org/HOWTO/archived/LDAP-Implementation-HOWTO/pamnss.html and lots of other documentation on the web on how to set up LDAP to provide user accounts for your system. Those methods are very widely used, much more secure and more widely documented. We recommend you use them rather than have JupyterHub create local accounts using the LDAPAuthenticator.

Issue #19 provides additional discussion on local user creation.

ldapauthenticator's People

Contributors

1kastner avatar behrmann avatar betatim avatar consideratio avatar dhirschfeld avatar dirkcgrunwald avatar fm75 avatar grahamdumpleton avatar jcrubioa avatar kinow avatar kishorchintal avatar m0zes avatar manics avatar marcusianlevine avatar mariusvniekerk avatar mateuszboryn avatar metrofun avatar minrk avatar nklever avatar pre-commit-ci[bot] avatar sauloal avatar sgibson91 avatar skemper avatar toxadx avatar willingc avatar yuvipanda avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ldapauthenticator's Issues

LDAP Authenticator does not allow multiple bind template

c.LDAPAuthenticator.bind_dn_template configuration only takes one value? I have my users spread across multilple OUs

For Eg: 'cn={username},ou=Developers,ou=All Users,dc=abc,dc=ds,dc=xyz,dc=com'
'cn={username},ou=Analysts,ou=All Users,dc=abc,dc=ds,dc=xyz,dc=com'
'cn={username},ou=Bigdata,ou=All Users,dc=abc,dc=ds,dc=xyz,dc=com'

Is there a way I can use multiple bind template in this configuration?

ldap3.search response is not parsed correctly

So, I just started connecting JupyterHub to our LDAP server

I didn't seem to work right away (giving in credentials and JupyterHub would say 'incorrect username/password', so I dove into ldapauthenticator.py code to find the issue

First of all, I cloned from the master branch, as I read there are issues with the 1.1 release concerning the bind user/password.

my Jupyter config in respect to LDAP (in italics to mask our server specifics)

c.JupyterHub.authenticator_class = 'ldapauthenticator.LDAPAuthenticator'
c.LDAPAuthenticator.server_address = 'LDAP SERVER IP'
c.LDAPAuthenticator.bind_dn_template = str('uid={username},dc=OUR.DOMAIN,dc=be')
c.LDAPAuthenticator.lookup_dn = True
c.LDAPAuthenticator.user_search_base = 'dc=OUR.DOMAIN,dc=be'
c.LDAPAuthenticator.user_attribute = 'uid'
c.LDAPAuthenticator.lookup_dn_search_user = str('cn=admin,dc=OUR.DOMAIN,dc=be')
c.LDAPAuthenticator.lookup_dn_search_password = 'admin password'
c.LDAPAuthenticator.lookup_dn_user_dn_attribute = 'uid'

my username I tried to log in with was let's way FRANK
I used self.log.warn to print out the return of the function resolve_username

resolved_username = self.resolve_username(username)
self.log.warn(resolved_username)

[W 2018-05-22 22:53:49.869 JupyterHub ldapauthenticator:327] ['FRANK']

Notice it returns a list.

Taking a step back I checked the entire response of the ldap3 search operation for username FRANK:
[{'raw_dn': b'uid=FRANK,dc=OUR.DOMAIN,dc=be', 'dn': 'uid=FRANK,dc=OUR.DOMAIN,dc=be', 'raw_attributes': {'uid': [b'FRANK']}, 'attributes': {'uid': ['FRANK']}, 'type': 'searchResEntry'}]

So, the value of the attribite uid is a list. At first I thought I missed something in my configuration resulting in this output structure. However, this response is in accordance with ldap3 documentation: http://ldap3.readthedocs.io/searches.html#response

attributes: a dictionary of returned attributes and their values. Values are list.

This results in a weird looking dn

userdn = dn.format(username=resolved_username)
self.log.warn(userdn)

[W 2018-05-22 22:45:21.661 JupyterHub ldapauthenticator:332] ['uid=['FRANK'],dc=OUR.DOMAIN,dc=be']

So, it seemed that would be an issue. To confirm this, I hardcoded the userdn variable right after this assignment and the login was successful.

userdn =['uid=FRANK,dc=_OUR.DOMAIN_,dc=be']

In conclusion: it looks like the uid attribute from the SEARCH operation response isn't properly parsed.
It should be enough to change line 244
return conn.response[0]['attributes'][self.lookup_dn_user_dn_attribute]
into
return conn.response[0]['attributes'][self.lookup_dn_user_dn_attribute][0]

to retrieve the element from the 1-element list

Cheers,
Philip

Error 500 after authentication

Hi,
I configured the LDAP auth and that seems to be ok but after login I've got a crash:

[I 2018-04-04 08:02:58.321 JupyterHub log:122] 200 GET /hub/login (@172.29.0.1) 27.27ms
[I 2018-04-04 08:03:08.584 JupyterHub base:346] User logged in: pafer
[E 2018-04-04 08:03:08.642 JupyterHub user:427] Unhandled error starting pafer's server: 'getpwnam(): name not found: pafer'
[E 2018-04-04 08:03:08.664 JupyterHub web:1621] Uncaught exception POST /hub/login?next= (172.29.0.1)
    HTTPServerRequest(protocol='http', host='172.29.0.2:8000', method='POST', uri='/hub/login?next=', version='HTTP/1.1', remote_ip='172.29.0.1')
    Traceback (most recent call last):
      File "/opt/workdir/.venv/lib64/python3.6/site-packages/tornado/web.py", line 1543, in _execute
        result = yield result
      File "/opt/workdir/.venv/lib64/python3.6/site-packages/jupyterhub/handlers/login.py", line 94, in post
        yield self.spawn_single_user(user)
      File "/opt/workdir/.venv/lib64/python3.6/site-packages/jupyterhub/handlers/base.py", line 475, in spawn_single_user
        yield gen.with_timeout(timedelta(seconds=self.slow_spawn_timeout), finish_spawn_future)
      File "/opt/workdir/.venv/lib64/python3.6/site-packages/jupyterhub/handlers/base.py", line 445, in finish_user_spawn
        yield spawn_future
      File "/opt/workdir/.venv/lib64/python3.6/site-packages/jupyterhub/user.py", line 439, in spawn
        raise e
      File "/opt/workdir/.venv/lib64/python3.6/site-packages/jupyterhub/user.py", line 378, in spawn
        ip_port = yield gen.with_timeout(timedelta(seconds=spawner.start_timeout), f)
      File "/usr/lib64/python3.6/types.py", line 248, in wrapped
        coro = func(*args, **kwargs)
      File "/opt/workdir/.venv/lib64/python3.6/site-packages/jupyterhub/spawner.py", line 968, in start
        env = self.get_env()
      File "/opt/workdir/.venv/lib64/python3.6/site-packages/jupyterhub/spawner.py", line 960, in get_env
        env = self.user_env(env)
      File "/opt/workdir/.venv/lib64/python3.6/site-packages/jupyterhub/spawner.py", line 947, in user_env
        home = pwd.getpwnam(self.user.name).pw_dir
    KeyError: 'getpwnam(): name not found: pafer'

Any explanation to help me to fix this ?

Thanks a lot !

JupyterHub-Livy-Sparkmagic-Kerberos

Here is my use case:
Run spark jobs in JupyterHub notebooks against a Kerborised (YARN/Spark) cluster.
I don't want LDAP users to have Kerberos principals.
I am allowed to create service principals.

What i did so far on a single machine is :

  1. Installed Jupyterhub - Success.
    https://github.com/jupyterhub/jupyterhub

  2. Installed LIvy - Success.
    https://github.com/cloudera/livy

  3. Added this node as a gateway node to the Cloudera cluster - Success.

  4. configured LDAP authenticator -Success.
    https://github.com/jupyterhub/ldapauthenticator

  5. Sparkmagic - Done
    https://github.com/jupyter-incubator/sparkmagic

  6. Kerberos Authentication - KDC authenticator - Done
    https://github.com/bloomberg/jupyterhub-kdcauthenticator

Error message when I'm trying to run :
#KRB5_CONFIG=/etc/krb5.conf
#KRB5_KTNAME=/opt/livy/jhub.keytab
#jupyterhub --ip=public.ip --port=8000 --no-ssl --config=/opt/jupyterhub_config.py

[C 2017-06-27 21:10:31.135 JupyterHub application:90] Bad config encountered during initialization:
[C 2017-06-27 21:10:31.135 JupyterHub application:91] The 'authenticator_class' trait of <jupyterhub.app.JupyterHub object at 0x7f03e8070c88> instance must be a type, but 'kdcauthenticator.kdcauthenticator.KDCAuthenticator' could not be imported

Being a newbie to Jupyter/Spark and Kerberos, I'm not able figure out what I'm missing.

Here I am attaching the overall architecture and the configuration files of livy and jupyterhub.

jupyterhub_config.txt
livy_conf.txt
screen shot 2017-06-26 at 9 20 16 pm

Here I am attaching the overall architecture and the configuration files of livy and jupyterhub.

I cannot authenticate with this plugin. Is there any error of my LDAP config?

JupyterHub and this plugin are both the recent stable version.

c.JupyterHub.authenticator_class = 'ldapauthenticator.LDAPAuthenticator'
c.LDAPAuthenticator.server_address = '***.***.***.***'
c.LDAPAuthenticator.bind_dn_template = ['uid={username},app=100000,cn=apps,dc=***.***.***']
c.LDAPAuthenticator.lookup_dn = True
c.LDAPAuthenticator.lookup_dn_search_user = 'uid=admin, cn=users, dc=***.***.***'
c.LDAPAuthenticator.lookup_dn_search_password = '********'
c.LDAPAuthenticator.user_search_base = 'app=100000,cn=apps,dc=***.***.***'
c.LDAPAuthenticator.user_attribute = 'uid'
c.LDAPAuthenticator.lookup_dn_user_dn_attribute = 'uid'

authenticate() should return groups list

auth_state.groups should be a list of groups the user belongs to (if we can obtain it)

This can then be used to implement conditional logic based on the authenticated user's group membership.

bind_dn_template list not working

for dn in self.bind_dn_template:
userdn = dn.format(username=resolved_username)
conn = getConnection(userdn, username, password)
isBound = conn.bind()
self.log.debug('Status of user bind {username} with {userdn} : {isBound}'.format(
username=username,
userdn=userdn,
isBound=isBound
))
if isBound:
break

Specifically, the line:

conn = getConnection(userdn, username, password)

fails with an invalidCredentials exception if you try to bind with an invalid dn for the given user:

Traceback (most recent call last):
  File "C:\Program Files\JetBrains\PyCharm 2017.2.3\helpers\pydev\_pydevd_bundle\pydevd_exec2.py", line 3, in Exec
    exec(exp, global_vars, local_vars)
  File "<input>", line 1, in <module>
  File "c:\dev\src\ldapauthenticator\ldapauthenticator\ldapauthenticator.py", line 286, in getConnection
    auto_bind=ldap3.AUTO_BIND_TLS_BEFORE_BIND,
  File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\ldap3\core\connection.py", line 337, in __init__
    raise LDAPBindError(self.last_error)
ldap3.core.exceptions.LDAPBindError: automatic bind not successful - invalidCredentials

Since it throws an exception the loop never continues on to try the dn template which would have worked.

This is on Windows connecting to Active Directory.

LDAP Auth doesn't work if an user with the same name doesn't exist on the system

When trying to use LDAP to log user on jupyterhub I get:
File "/usr/local/lib/python3.4/dist-packages/jupyterhub/spawner.py", line 757, in user_env
home = pwd.getpwnam(self.user.name).pw_dir
KeyError: 'getpwnam(): name not found: johny'

The user does exist in the LDAP and the authentication work, when I do:
ldapwhoami -vvv -h localhost -D uid=johny,ou=people,dc=example,dc=com -x -w secret
ldap_initialize( ldap://localhost )
dn:uid=johny,ou=people,dc=example,dc=com
Result: Success (0)

When I create an user on the machine (without the same password but the same username) it does work.
I would like to log user with LDAP information without haign to create myself an account for every user on the machine (they have remote folder that I can mount to store their notebook and files). Is there any way to achieve something like that?

Comma not escaped in username

I'm using Active Directory LDAP with following attributes:
dn: CN=Doe\, John,CN=Users,DC=mycompany,DC=com
cn: Doe, John

My configuration is the following:
c.LDAPAuthenticator.allowed_groups = ['CN={username},CN=Users,DC=mycompany,DC=com'
c.LDAPAuthenticator.lookup_dn_user_dn_attribute = 'cn'

It seems the authentication fails since the comma in the cn is not escaped which is required for AD and therefore doesn't match the dn. I get the following reported in the log:

[D 2018-03-02 20:47:41.249 JupyterHub ldapauthenticator:278] Attempting to bind jdoe with CN=Doe, John,CN=Users,DC=mycompany,DC=com
[D 2018-03-02 20:47:41.272 JupyterHub ldapauthenticator:328] Status of user bind jdoe with CN=Doe, John,CN=Users,DC=mycompany,DC=com : False
    LDAPBindError: automatic bind not successful - invalidCredentials
[

My guess is the escape_userdn_if_needed() function needs to handle this case since the ldap3 escape_filter_chars does not escape the comma.

def escape_userdn_if_needed(self, userdn):
        if self.escape_userdn:
            return escape_filter_chars(userdn)
        else:
            return userdn

If there's a way around this problem by simply changing the configuration please let me know.

pip install not up to date

The pip install does not install the most recent version of the ldapauthenticator, lookup_dn, user_attribute and user_search_base are missing!

c.LDAPAuthenticator.bind_dn_template doesn't work on Active Directory

Just an example:

My AD path is: OU=Laptop_Users,OU=exmple,OU=company,DC=company,DC=com
I have c.LDAPAuthenticator.user_attribute = 'sAMAccountName' insted of 'uid'

my CN it is for example "CN=Jon Smith" and attribute as login= "jons"
how should looks like my base_dn_template ?

none from below works properly:
bind_dn_template = 'uid={username},OU=Laptop_Users,OU=exmple,OU=company,DC=company,DC=com'
bind_dn_template = 'sAMAccountName={username},OU=Laptop_Users,OU=exmple,OU=company,DC=company,DC=com'

if CN == login them below example works properly:
bind_dn_template = 'CN={username},OU=Laptop_Users,OU=exmple,OU=company,DC=company,DC=com'

if CN =! login them I don't know to what bind_dn_template should be

Everything is fine as long as CN ==login
please help.

Support for python version 2.7

Hi,

I have installed python 2.7.15 using conda in a linux server , when i try to utilize ldapauthenticator for multi user authentication I am facing following issue , just want to understand Is there a workaround or support for python 2.7

Python version - Python 2.7.15 :: Anaconda, Inc.

Error log:

pip install jupyterhub-ldapauthenticator
Collecting jupyterhub-ldapauthenticator
Using cached https://files.pythonhosted.org/packages/18/57/eb25276959fd6fee6c48547255cb3f8efb3ced0520474ef5f6eb4ae46b74/jupyterhub-ldapauthenticator-1.2.1.tar.gz
Collecting jupyterhub (from jupyterhub-ldapauthenticator)
Using cached https://files.pythonhosted.org/packages/be/63/b6967b050e304fe50f21b0e4c587660d150877a9861c7e62b3c7fad31f7b/jupyterhub-0.7.2.tar.gz
Complete output from command python setup.py egg_info:
ERROR: JupyterHub requires Python version 3.3 or above.

Thanks

NameError: name 'LDAPAuthenticator' is not defined

        exec(compiler(f.read(), fname, 'exec'), glob, loc)
      File "/home/vagrant/jupyterhub_config.py", line 6, in <module>
        LDAPAuthenticator.server_address = 'https://my.ldap.server'
    NameError: name 'LDAPAuthenticator' is not defined

My config:

c.JupyterHub.authenticator_class = 'ldapauthenticator.LDAPAuthenticator'
LDAPAuthenticator.server_address = 'https://my.ldap.server'
LDAPAuthenticator.bind_dn_template = 'uid={username},ou=people,dc=SOMEDC,dc=COM'

Adding this to my config:

from ldapauthenticator import LDAPAuthenticator

fixes the error. Am I missing something or do the docs just need to be updated?

AD configuration, need help!

Hello guys,

I am trying to setup AD with Jupyterhub but I am stuck on the AD configuration and I am not able to connect. Below is my config and the error message that I get.

Could you please help me the configuration?

Configuration

c.JupyterHub.authenticator_class = 'ldapauthenticator.LDAPAuthenticator'
c.LDAPAuthenticator.server_address = 'IP ADDRESS'
c.LDAPAuthenticator.bind_dn_template = 'cn={USERNAME},ou=BIP,ou=Resources,dc=global,dc=corp,dc=MYCOMPANY'
c.LDAPAuthenticator.lookup_dn = False
c.LDAPAuthenticator.user_search_base = 'dc=global,dc=corp,dc=MYCOMPANY'
c.LDAPAuthenticator.user_attribute = 'sAMAccountName'
c.LDAPAuthenticator.valid_username_regex = '^[a-zA-Z][.a-z0-9_-]*$'
c.LDAPAuthenticator.allowed_groups = []
c.LDAPAuthenticator.server_port = 389

Logs

jupyterhub --no-ssl --log-level=DEBUG
[D 2016-11-23 10:30:02.961 JupyterHub application:555] Looking for jupyterhub_config in /root
[D 2016-11-23 10:30:02.962 JupyterHub application:577] Loaded config file: /root/jupyterhub_config.py
[I 2016-11-23 10:30:03.025 JupyterHub app:724] Loading cookie_secret from /root/jupyterhub_cookie_secret
[D 2016-11-23 10:30:03.026 JupyterHub app:796] Connecting to db: sqlite:///jupyterhub.sqlite
[W 2016-11-23 10:30:03.070 JupyterHub app:365]
Generating CONFIGPROXY_AUTH_TOKEN. Restarting the Hub will require restarting the proxy.
Set CONFIGPROXY_AUTH_TOKEN env or JupyterHub.proxy_auth_token config to avoid this message.

[W 2016-11-23 10:30:03.080 JupyterHub app:864] No admin users, admin interface will be unavailable.
[W 2016-11-23 10:30:03.080 JupyterHub app:865] Add any administrative users to c.Authenticator.admin_users in config.
[I 2016-11-23 10:30:03.081 JupyterHub app:892] Not using whitelist. Any authenticated user will be allowed.
[D 2016-11-23 10:30:03.093 JupyterHub app:1082] Loading state for i329537 from db
[D 2016-11-23 10:30:03.093 JupyterHub app:1094] i329537 not running.
[D 2016-11-23 10:30:03.093 JupyterHub app:1099] Loaded users:
i329537
[I 2016-11-23 10:30:03.102 JupyterHub app:1450] Hub API listening on http://127.0.0.1:8081/hub/
[W 2016-11-23 10:30:03.106 JupyterHub app:1171] Running JupyterHub without SSL. I hope there is SSL termination happening somewhere else...
[I 2016-11-23 10:30:03.106 JupyterHub app:1173] Starting proxy @ http://:8000/
[D 2016-11-23 10:30:03.107 JupyterHub app:1174] Proxy cmd: ['configurable-http-proxy', '--ip', '', '--port', '8000', '--api-ip', '127.0.0.1', '--api-port', '8001', '--default-target', 'http://127.0.0.1:8081', '--error-target', 'http://127.0.0.1:8081/hub/error']
10:30:03.218 - info: [ConfigProxy] Proxying http://
:8000 to http://127.0.0.1:8081
10:30:03.220 - info: [ConfigProxy] Proxy API at http://127.0.0.1:8001/api/routes
[D 2016-11-23 10:30:03.315 JupyterHub app:1202] Proxy started and appears to be up
[I 2016-11-23 10:30:03.316 JupyterHub app:1482] JupyterHub is now running at http://127.0.0.1:8000/
[W 2016-11-23 10:30:13.826 JupyterHub ldapauthenticator:92] Invalid username
[D 2016-11-23 10:30:13.826 JupyterHub login:95] Failed login for USERNAME

Thanks a lot!
Majid

jupyterhub with authentication on Active Directory

Hello,

I want to set up jupyterhub with authentication on Active Directory.

is it possible?

I wonder if someone has already done this use case.

With the default setting defined on https://github.com/jupyterhub/ldapauthenticator
for operation with the LDAP , what are the basic parameters to work with Active Directory in Jupyterhub_config.py ?

What does add or remove to a parameterization with AD ?

it has a specific development python do?

This is some of example of my Active Directory parameters, how can i adapt ?

Thanks for your help !!

nt_domain = org

ldap_url = ldap://127.0.0.1

base_dn = dc=org,dc=com,dc=wikipost

bind_dn = CN=call app,OU=custumer,OU=people and marketing,DC=org,DC=com,DC=wikipost

bind_password = *************

group_filter = (objectCategory=Group)

user_name_attr = sAMAccountName

user_filter = (objectClass=User)

group_member_attr = member

group_name_attr = cn

User able to surpass LDAP group requirement with a cookie

I've just noted that after enabling LDAPAuthenticator.allowed_groups, one user who was not included in the application group was still able to login, probably based on a cookie/browser cache. When the user tried to login from within a private window it didn't succeed, but with a regular browser window login was not required. It seems to be a (minor) security breach.

Without bind_dn_template, any password is authenticated successfully!

When initially configuring ldapauthenticator, I accidentally left bind_dn_template out of my config. When I tested it, I noticed it was authenticating me even with incorrect passwords!

This seems very dangerous. Although this parameter is required, authentication should probably always fail rather than always succeeding (or jupyter hub should simply refuse to start if required values are missing).

This happened when I had the following config vars set: server_address, lookup_dn, user_search_base, user_attribute.

Upload to PyPI

jupyterhub-ldapauthenticator is not available in the PyPI index. It does have a good setup.py script, so fixing this is just a matter of registering and uploading it.

Jupyterhub with Active Directory & Shared Folder

Having read through issues #32 and #36, I set out to try hook the LDAPAuthenticator into realmd and SSSD in order to allow Active Directory users to authenticate on Jupyterhub on a CentOS 7 machine, automatically adding missing users; so far this seems to work! As a bonus, I configured a shared directory between the users, to allow them to share notebooks.

@minrk helped me enormously, most of the ideas here came from him.

Perhaps some of this should be included in the README or elsewhere in the documentation?

Jupyterhub Config

The jupyterhub_config.py should include the following:

import os, sys, subprocess                                            
config_dir = os.path.dirname(os.path.abspath(__file__)) 

# Extend the LDAPAuthenticator with a custom add_user method
# add_user.sh should be in the same directory as jupyterhub_config.py
# (mostly by @minrk)

from ldapauthenticator import LDAPAuthenticator 
class MyAuthenticator(LDAPAuthenticator):      
    def add_user(self, user):             
	super().add_user(user)
        script_path = os.path.join(config_dir, "add_user.sh")      
        subprocess.check_call(['bash', script_path, user.name])
                                  
# Use the custom authenticator; no quotes!
c.JupyterHub.authenticator_class = MyAuthenticator            

# see issue #32
# you can also use c.LDAPAuthenticator for all of these (matter of style)

c.MyAuthenticator.server_address = 'myadserver'                   
c.MyAuthenticator.bind_dn_template = '{username}'         
c.MyAuthenticator.lookup_dn = True          
c.MyAuthenticator.use_ssl = False                
c.MyAuthenticator.lookup_dn_search_filter = '({login_attr}={login})'
c.MyAuthenticator.lookup_dn_search_user = 'ldapsearchuser'          
c.MyAuthenticator.lookup_dn_search_password = 'ldapsearchpassword'  
c.MyAuthenticator.user_attribute = 'sAMAccountName'             
c.MyAuthenticator.user_search_base = 'ou=Org users,dc=domainorg,dc=local' 
c.MyAuthenticator.lookup_dn_user_dn_attribute = 'cn'
c.MyAuthenticator.admin_users = {'adminuser'}          
          
c.Spawner.notebook_dir = '~/notebooks'  

Script

In my case, add_user.sh looks like this:

#!/usr/bin/env bash

user=$1  
userhome="/home/ad-domain/${user}"

# add_user should be idempotent, so we test if the user home directory is there
if [ ! -d "${userhome}" ]; then    

     # Use realmd to add the user
     realm permit ${user}                   

     # Create home directory       
     mkdir "${userhome}"              
     chown "${user}:domain users" "${userhome}"   

     # Add user to the sharedfolder group
     usermod -aG sharedfolder ${user}

     # Create notebook directory and symlink the datalab folder into it
     mkdir ${userhome}/notebooks  
     chown ${user}:domain\ users ${userhome}/notebooks -R  

     # Symlink a shared folder into the user notebook directory
     ln -s /home/sharedfolder ${userhome}/notebooks/sharedfolder
fi     

Realmd and SSSD

For this to work you need to set up realmd, a frontend for SSSD. I follow the Red Hat guide for doing this. The only modification I manually made to /etc/sssd/sssd.conf are to set:

use_fully_qualified_names = False
fallback_homedir = /home/ad-domain/%u

The former due to a problem with SSSD accepting the AD username format and the latter because I preferred putting all my AD users in one folder (if you don't want this edit ${userhome} in the script above accordingly).

Sharedfolder

To make the shared folder work as expected, you need to set permissions correctly, set group ownership of the folder to the sharedfolder group, set the setguid bit of the folder on, and make sure new files will have the right permissions. I did this as follows:

# Set ownership to the administrator and sharedfolder group
sudo chown -R folderadmin:sharedfolder /home/sharedfolder

# Set the setguid bit
sudo chmod g+s /home/sharedfolder

# Apply the correct group permissions to the folder
sudo chmod -R g+rwX /home/sharedfolder

# Make sure all new files added to the folder get the right permissions
sudo setfacl -d -m g:sharedfolder:rwX /home/sharedfolder

(I am a little fuzzy about this last bit, so if there are errors here please correct me!)

pyasn1 Error

After updating to master I'm now seeing the below error when logging in when it used to work previously. We're using Active Directory. Likely a config issue but I thought I'd post so as to not lose the traceback. Even if it does end up being a config issue it should probably not throw an unhandled exception?

[E 2017-09-28 10:23:46.736 JupyterHub web:1590] Uncaught exception POST /hub/login?next= (::1)
    HTTPServerRequest(protocol='http', host='localhost:8000', method='POST', uri='/hub/login?next=', version='HTTP/1.1', remote_ip='::1', headers={'X-Forwarded-Host': 'localhost:8000', 'X-Forwarded-Proto': 'http', 'X-Forwarded-Port': '8000', 'X-Forwarded-For': '::1', 'Accept-Language': 'en-US,en;q=0.8', 'Accept-Encoding': 'gzip, deflate, br', 'Referer': 'http://localhost:8000/hub/login', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36', 'Content-Type': 'application/x-www-form-urlencoded', 'Upgrade-Insecure-Requests': '1', 'Origin': 'http://localhost:8000', 'Cache-Control': 'max-age=0', 'Content-Length': '39', 'Connection': 'close', 'Host': 'localhost:8000'})
    Traceback (most recent call last):
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\web.py", line 1511, in _execute
        result = yield result
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\gen.py", line 1055, in run
        value = future.result()
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\concurrent.py", line 238, in result
        raise_exc_info(self._exc_info)
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\gen.py", line 1063, in run
        yielded = self.gen.throw(*exc_info)
      File "c:\dev\src\jupyterhub\jupyterhub\handlers\login.py", line 82, in post
        user = yield self.login_user(data)
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\gen.py", line 1055, in run
        value = future.result()
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\concurrent.py", line 238, in result
        raise_exc_info(self._exc_info)
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\gen.py", line 1063, in run
        yielded = self.gen.throw(*exc_info)
      File "c:\dev\src\jupyterhub\jupyterhub\handlers\base.py", line 327, in login_user
        authenticated = yield self.authenticate(data)
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\gen.py", line 1055, in run
        value = future.result()
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\concurrent.py", line 238, in result
        raise_exc_info(self._exc_info)
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\gen.py", line 1063, in run
        yielded = self.gen.throw(*exc_info)
      File "c:\dev\src\jupyterhub\jupyterhub\auth.py", line 221, in get_authenticated_user
        authenticated = yield self.authenticate(handler, data)
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\gen.py", line 1055, in run
        value = future.result()
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\concurrent.py", line 238, in result
        raise_exc_info(self._exc_info)
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\gen.py", line 292, in wrapper
        result = func(*args, **kwargs)
      File "C:\Miniconda3\envs\jupyterhub\lib\types.py", line 248, in wrapped
        coro = func(*args, **kwargs)
      File "c:\dev\src\ldapauthenticator\ldapauthenticator\ldapauthenticator.py", line 320, in authenticate
        conn = getConnection(userdn, username, password)
      File "c:\dev\src\ldapauthenticator\ldapauthenticator\ldapauthenticator.py", line 284, in getConnection
        auto_bind=ldap3.AUTO_BIND_TLS_BEFORE_BIND,
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\ldap3\core\connection.py", line 288, in __init__
        self.start_tls(read_server_info=False)
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\ldap3\core\connection.py", line 969, in start_tls
        if self.server.tls.start_tls(self) and self.strategy.sync:  # for async connections _start_tls is run by the strategy
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\ldap3\core\tls.py", line 209, in start_tls
        result = connection.extended('1.3.6.1.4.1.1466.20037')
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\ldap3\core\connection.py", line 935, in extended
        response = self.post_send_single_response(self.send('extendedReq', request, controls))
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\ldap3\strategy\base.py", line 274, in send
        self.connection.request = BaseStrategy.decode_request(ldap_message)
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\ldap3\strategy\base.py", line 559, in decode_request
        result = extended_request_to_dict(component)
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\ldap3\operation\extended.py", line 55, in extended_request_to_dict
        return {'name': str(request['requestName']), 'value': str(request['requestValue']) if request['requestValue'] else None}
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\pyasn1\type\base.py", line 249, in __bool__
        return self._value and True or False
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\pyasn1\type\base.py", line 164, in plug
        raise error.PyAsn1Error('Uninitialized ASN.1 value ("%s" attribute looked up)' % name)
    pyasn1.error.PyAsn1Error: Uninitialized ASN.1 value ("__bool__" attribute looked up)

Release 1.2

It's probably about due and would stop the steady trickle of people confused that the examples in the README don't work because the functionality has never been released.

Plan of attack:

  • Triage issues
  • Tag 1.2
  • Release to PyPI
  • Create conda-forge recipe

500 Error with escape_userdn=True

The below error seems to occur when my username has no special characters:

[E 2017-09-28 10:42:09.532 JupyterHub web:1590] Uncaught exception POST /hub/login?next= (::1)
    HTTPServerRequest(protocol='http', host='localhost:8000', method='POST', uri='/hub/login?next=', version='HTTP/1.1', remote_ip='::1', headers={'X-Forwarded-Host': 'localhost:8000', 'X-Forwarded-Proto': 'http', 'X-Forwarded-Port': '8000', 'X-Forwarded-For': '::1', 'Accept-Language': 'en-US,en;q=0.8', 'Accept-Encoding': 'gzip, deflate, br', 'Referer': 'http://localhost:8000/hub/login?next=', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36', 'Content-Type': 'application/x-www-form-urlencoded', 'Upgrade-Insecure-Requests': '1', 'Origin': 'http://localhost:8000', 'Cache-Control': 'max-age=0', 'Content-Length': '39', 'Connection': 'close', 'Host': 'localhost:8000'})
    Traceback (most recent call last):
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\web.py", line 1511, in _execute
        result = yield result
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\gen.py", line 1055, in run
        value = future.result()
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\concurrent.py", line 238, in result
        raise_exc_info(self._exc_info)
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\gen.py", line 1063, in run
        yielded = self.gen.throw(*exc_info)
      File "c:\dev\src\jupyterhub\jupyterhub\handlers\login.py", line 82, in post
        user = yield self.login_user(data)
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\gen.py", line 1055, in run
        value = future.result()
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\concurrent.py", line 238, in result
        raise_exc_info(self._exc_info)
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\gen.py", line 1063, in run
        yielded = self.gen.throw(*exc_info)
      File "c:\dev\src\jupyterhub\jupyterhub\handlers\base.py", line 327, in login_user
        authenticated = yield self.authenticate(data)
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\gen.py", line 1055, in run
        value = future.result()
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\concurrent.py", line 238, in result
        raise_exc_info(self._exc_info)
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\gen.py", line 1063, in run
        yielded = self.gen.throw(*exc_info)
      File "c:\dev\src\jupyterhub\jupyterhub\auth.py", line 221, in get_authenticated_user
        authenticated = yield self.authenticate(handler, data)
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\gen.py", line 1055, in run
        value = future.result()
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\concurrent.py", line 238, in result
        raise_exc_info(self._exc_info)
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\tornado\gen.py", line 292, in wrapper
        result = func(*args, **kwargs)
      File "C:\Miniconda3\envs\jupyterhub\lib\types.py", line 248, in wrapped
        coro = func(*args, **kwargs)
      File "c:\dev\src\ldapauthenticator\ldapauthenticator\ldapauthenticator.py", line 301, in authenticate
        resolved_username = self.resolve_username(username)
      File "c:\dev\src\ldapauthenticator\ldapauthenticator\ldapauthenticator.py", line 227, in resolve_username
        conn = ldap3.Connection(server, user=self.escape_userdn_if_needed(self.lookup_dn_search_user), password=self.lookup_dn_search_password)
      File "c:\dev\src\ldapauthenticator\ldapauthenticator\ldapauthenticator.py", line 250, in escape_userdn_if_needed
        return escape_filter_chars(userdn)
      File "C:\Miniconda3\envs\jupyterhub\lib\site-packages\ldap3\utils\conv.py", line 36, in escape_filter_chars
        output = text.replace('\\', r'\5c')
    AttributeError: 'NoneType' object has no attribute 'replace'

...if I try to use DOMAIN\USERNAME I Instead see a warning:

[W 2017-09-28 10:46:29.836 JupyterHub ldapauthenticator:290] username:DOMAIN\USERNAME Illegal characters in username, must match regex ^[a-z][.a-z0-9_-]*$

LDAP Auth doesn't work -> 500 : Internal Server Error -> KeyError: 'getpwnam(): name not found: username'

It is my config file:

c.JupyterHub.authenticator_class = 'ldapauthenticator.LDAPAuthenticator'
c.LDAPAuthenticator.server_address = '10.48.1.151'
c.LDAPAuthenticator.use_ssl = False
c.LDAPAuthenticator.bind_dn_template = 'CN={username},OU=Special_Accounts,OU=PL_WAR,OU=mycompany,DC=mycompany,DC=com'
c.LDAPAuthenticator.lookup_dn = True
c.LDAPAuthenticator.user_search_base = 'DC=mycompany,DC=com'
c.LDAPAuthenticator.user_attribute = 'sAMAccountName'

and I receive an error: 500 : Internal Server Error -> KeyError: 'getpwnam(): name not found: datawizards'. I try to login to JupyterHub with LDAP authentication. User and password verification has been passed properly but I don't understand what is going on next. I suppose application is looking my user "datawizards" on OS level. Why ?. I want to login through LDAP to application without user creation inside Linux.

Any idea what is wrong ?

[I 2017-01-25 10:55:33.209 JupyterHub app:1453] Hub API listening on http://127.0.0.1:8081/hub/
[W 2017-01-25 10:55:33.212 JupyterHub app:1174] Running JupyterHub without SSL. I hope there is SSL termination happening somewhere else...
[I 2017-01-25 10:55:33.212 JupyterHub app:1176] Starting proxy @ http://0.0.0.0:8000/
[D 2017-01-25 10:55:33.213 JupyterHub app:1177] Proxy cmd: ['configurable-http-proxy', '--ip', '0.0.0.0', '--port', '8000', '--api-ip', '127.0.0.1', '--api-port', '8001', '--default-target', 'http://127.0.0.1:8081', '--error-target', 'http://127.0.0.1:8081/hub/error', '--log-level', 'debug']
[D 2017-01-25 10:55:33.430 JupyterHub app:1205] Proxy started and appears to be up
[I 2017-01-25 10:55:33.431 JupyterHub app:1485] JupyterHub is now running at http://127.0.0.1:8000/
[I 2017-01-25 10:55:35.750 JupyterHub log:100] 302 GET / (@10.48.2.111) 2.47ms
[I 2017-01-25 10:55:35.825 JupyterHub log:100] 302 GET /hub (@10.48.2.111) 0.42ms
[I 2017-01-25 10:55:35.888 JupyterHub log:100] 302 GET /hub/ (@10.48.2.111) 0.72ms
[I 2017-01-25 10:55:35.958 JupyterHub log:100] 302 GET /login (@10.48.2.111) 0.63ms
[I 2017-01-25 10:55:36.068 JupyterHub log:100] 200 GET /hub/login (@10.48.2.111) 32.31ms
[E 2017-01-25 10:55:41.476 JupyterHub user:251] Unhandled error starting datawizards's server: 'getpwnam(): name not found: datawizards'
[E 2017-01-25 10:55:41.488 JupyterHub web:1548] Uncaught exception POST /hub/login?next= (10.48.2.111)
HTTPServerRequest(protocol='http', host='10.249.1.6:8000', method='POST', uri='/hub/login?next=', version='HTTP/1.1', remote_ip='10.48.2.111', headers={'X-Forwarded-Host': '10.249.1.6:8000', 'Cache-Control': 'no-cache', 'Accept-Encoding': 'gzip, deflate', 'X-Forwarded-Port': '8000', 'Host': '10.249.1.6:8000', 'X-Forwarded-For': '10.48.2.111', 'Accept': 'text/html, application/xhtml+xml, image/jxr, /', 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': '41', 'Connection': 'close', 'Referer': 'http://10.249.1.6:8000/hub/login', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586', 'X-Forwarded-Proto': 'http', 'Accept-Language': 'en-US,en;q=0.5'})
Traceback (most recent call last):
File "/opt/anaconda2/lib/python3.5/site-packages/tornado/web.py", line 1469, in _execute
result = yield result
File "/opt/anaconda2/lib/python3.5/site-packages/jupyterhub/handlers/login.py", line 84, in post
yield self.spawn_single_user(user)
File "/opt/anaconda2/lib/python3.5/site-packages/jupyterhub/handlers/base.py", line 328, in spawn_single_user
yield gen.with_timeout(timedelta(seconds=self.slow_spawn_timeout), f)
File "/opt/anaconda2/lib/python3.5/site-packages/jupyterhub/user.py", line 261, in spawn
raise e
File "/opt/anaconda2/lib/python3.5/site-packages/jupyterhub/user.py", line 229, in spawn
ip_port = yield gen.with_timeout(timedelta(seconds=spawner.start_timeout), f)
File "/opt/anaconda2/lib/python3.5/types.py", line 243, in wrapped
coro = func(*args, **kwargs)
File "/opt/anaconda2/lib/python3.5/site-packages/jupyterhub/spawner.py", line 778, in start
env = self.get_env()
File "/opt/anaconda2/lib/python3.5/site-packages/jupyterhub/spawner.py", line 770, in get_env
env = self.user_env(env)
File "/opt/anaconda2/lib/python3.5/site-packages/jupyterhub/spawner.py", line 757, in user_env
home = pwd.getpwnam(self.user.name).pw_dir
KeyError: 'getpwnam(): name not found: datawizards'

Error in README.md -- bind_dn_template

traitlets.traitlets.TraitError: The 'bind_dn_template' trait of a LDAPAuthenticator instance must be a unicode string, but a value of ['uid={username},ou=People,dc=tu-harburg,dc=de'] <class 'list'> was specified.

Feature Request: support admin_users query

Hi all,

It would be great if this authenticator could support an LDAP query that would designate admin_users and update that list dynamically (not require a restart). Since ldapauthenticator already has all of the machinery to access LDAP, it seems like it might be a good place to optionally populate the admin_users set based on an LDAP query. Thanks for reading.

getpwnam(): name not found: foo when trying to login

Hello folks,

When trying to login using ldapauthenticator I'm running into the following issue:

I attempt to login to Jupyterhub with LDAP user foo, it returns:

500 : Internal Server Error
Failed to start your server. Please contact admin.

Log Output

    Traceback (most recent call last):
      File "/usr/local/anaconda3/lib/python3.5/site-packages/tornado/web.py", line 1469, in _execute
        result = yield result
      File "/usr/local/anaconda3/lib/python3.5/site-packages/jupyterhub/handlers/login.py", line 79, in post
        yield self.spawn_single_user(user)
      File "/usr/local/anaconda3/lib/python3.5/site-packages/jupyterhub/handlers/base.py", line 312, in spawn_single_user
        yield gen.with_timeout(timedelta(seconds=self.slow_spawn_timeout), f)
      File "/usr/local/anaconda3/lib/python3.5/site-packages/jupyterhub/user.py", line 247, in spawn
        raise e
      File "/usr/local/anaconda3/lib/python3.5/site-packages/jupyterhub/user.py", line 228, in spawn
        yield gen.with_timeout(timedelta(seconds=spawner.start_timeout), f)
      File "/usr/local/anaconda3/lib/python3.5/types.py", line 243, in wrapped
        coro = func(*args, **kwargs)
      File "/usr/local/anaconda3/lib/python3.5/site-packages/jupyterhub/spawner.py", line 471, in start
        preexec_fn=self.make_preexec_fn(self.user.name),
      File "/usr/local/anaconda3/lib/python3.5/site-packages/jupyterhub/spawner.py", line 417, in make_preexec_fn
        return set_user_setuid(name)
      File "/usr/local/anaconda3/lib/python3.5/site-packages/jupyterhub/spawner.py", line 374, in set_user_setuid
        user = pwd.getpwnam(username)
    KeyError: 'getpwnam(): name not found: foo'

I'm guessing this is down to getpwnam() looking for the user foo in the /etc/passwd file. However as foo is an LDAP user it does not exist there.

jupyterhub_config.py

c.JupyterHub.authenticator_class = 'ldapauthenticator.LDAPAuthenticator'
c.LDAPAuthenticator.server_address = 'ldap-server'
c.LDAPAuthenticator.bind_dn_template = 'cn={username},ou=Team1,l=Europe,O=thing'

I'm at a loss as to how to resolve this, any help would be greatly appreciated.

Auth ok, but the users are not added

Hello,

Thanks for providing such a module, it is very useful for schools.
As written in the title, I managed to use ldapauthenticator and to log in with ldap credentials, when an unix account already exists on the server who host jupyterhub.
But I get an error 'getpwnam(): name not found: USERNAME' for all new users, and I have to allow all users to login for my school.

I've seen jupyterhub/jupyterhub#466, but I don't want to use the DockerSpawner.

My config :

# pip3 list | grep jup
jupyter (1.0.0)
jupyter-client (4.4.0)
jupyter-console (5.0.0)
jupyter-core (4.2.1)
jupyterhub (0.7.1)
jupyterhub-ldapauthenticator (1.1)
# grep -v '^#' jupyterhub_config.py  | sort -u
c.Authenticator.admin_users = {'admin'}
c.JupyterHub.authenticator_class = 'ldapauthenticator.LDAPAuthenticator'
c.JupyterHub.port = 443
c.JupyterHub.spawner_class = 'jupyterhub.spawner.LocalProcessSpawner'
c.JupyterHub.ssl_cert = 'jupyterhub.crt'
c.JupyterHub.ssl_key = 'jupyterhub.key'
c.LDAPAuthenticator.bind_dn_template = 'uid={username},ou=accounts,dc=domain,dc=com'
c.LDAPAuthenticator.server_address = 'ldap.domain.com'
c.LocalAuthenticator.add_user_cmd = ['useradd', '-m']
c.LocalAuthenticator.create_system_users = True
c.Spawner.notebook_dir = '~'

Did I miss something in the config file ?

Thanks for your help

`username_template` not recognized

The README.md file says:

Template to use to generate the full dn for a user from the human readable username. For example, if users in your LDAP database have DN of the form uid=Yuvipanda,ou=people,dc=wikimedia,dc=org where Yuvipanda is the username, you would set this config item to be:

c.LDAPAuthenticator.username_template = 'uid={username},ou=people,dc=wikimedia,dc=org'

The {username} is expanded into the username the user provides.

However, when I set this option and start JupyterHub, I get:

[W 2016-01-26 10:13:11.050 JupyterHub configurable:162] Config option username_template not recognized by LDAPAuthenticator, do you mean one of : username_pattern ,username_map ,bind_dn_template

Need help in configuring AD accounts

Hello,

I am trying to configure Active Directory in Jupyterhub using ldapauthenticator (latest version pulled from github), below is my configuration for LDAP/AD,

c.JupyterHub.authenticator_class = 'ldapauthenticator.LDAPAuthenticator'
c.LDAPAuthenticator.server_address = 'abc.xyz.com'
c.LDAPAuthenticator.bind_dn_template = 'cn={username},DC=xyz,DC=com'
c.LDAPAuthenticator.lookup_dn = True
c.LDAPAuthenticator.use_ssl = False
c.LDAPAuthenticator.server_port = 3268

c.LDAPAuthenticator.lookup_dn_search_filter = '({login_attr}={login})'
c.LDAPAuthenticator.lookup_dn_search_user = '[email protected]'
c.LDAPAuthenticator.lookup_dn_search_password = 'password'
c.LDAPAuthenticator.lookup_dn_user_dn_attribute = 'cn'

c.LDAPAuthenticator.user_search_base = 'DC=xyz,DC=com'
c.LDAPAuthenticator.user_attribute = 'sAMAccountName'
c.LDAPAuthenticator.allowed_groups = []

But, getting below error in the logs,

[D 2018-01-16 10:08:36.664 JupyterHub ldapauthenticator:299] TYPE= 'False'
[D 2018-01-16 10:08:36.665 JupyterHub ldapauthenticator:223] Looking up user with search_base=DC=xyz,DC=com, search_filter='(sAMAccountName=username)', attributes=sAMAccountName
[D 2018-01-16 10:08:38.719 JupyterHub ldapauthenticator:278] Attempting to bind username with c
[D 2018-01-16 10:08:39.159 JupyterHub ldapauthenticator:328] Status of user bind username with c : False
    LDAPBindError: automatic bind not successful - invalidCredentials
[D 2018-01-16 10:08:39.160 JupyterHub ldapauthenticator:278] Attempting to bind username with n
[D 2018-01-16 10:08:39.603 JupyterHub ldapauthenticator:328] Status of user bind username with n : False
    LDAPBindError: automatic bind not successful - invalidCredentials
[D 2018-01-16 10:08:39.604 JupyterHub ldapauthenticator:278] Attempting to bind username with =
[D 2018-01-16 10:08:40.039 JupyterHub ldapauthenticator:328] Status of user bind username with = : False
    LDAPBindError: automatic bind not successful - invalidCredentials_**
[E 2018-01-16 10:08:40.040 JupyterHub web:1591] Uncaught exception POST /hub/login?next= (<<IPAddress>>)
    HTTPServerRequest(protocol='http', host='<<IPAddress>>:8001', method='POST', uri='/hub/login?next=', version='HTTP/1.1', remote_ip='<<IPAddress>>', headers={'Content-Length': '35', 'X-Forwarded-Port': '8001', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36', 'Connection': 'close', 'Host': '<<IPAddress>>:8001', 'Upgrade-Insecure-Requests': '1', 'Content-Type': 'application/x-www-form-urlencoded', 'Referer': 'http://<<IPAddress>>:8001/hub/login?next=', 'X-Forwarded-For': '<<IPAddress>>', 'X-Forwarded-Host': '<<IPAddress>>:8001', 'Origin': 'http://<<IPAddress>>:8001', 'Accept-Language': 'en-US,en;q=0.9', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate', 'X-Forwarded-Proto': 'http', 'Cache-Control': 'max-age=0'})
    Traceback (most recent call last):
      File "/apps/anaconda3/lib/python3.5/site-packages/tornado/web.py", line 1512, in _execute
        result = yield result
      File "/apps/anaconda3/lib/python3.5/site-packages/jupyterhub/handlers/login.py", line 83, in post
        user = yield self.login_user(data)
      File "/apps/anaconda3/lib/python3.5/site-packages/jupyterhub/handlers/base.py", line 328, in login_user
        authenticated = yield self.authenticate(data)
      File "/apps/anaconda3/lib/python3.5/site-packages/jupyterhub/auth.py", line 227, in get_authenticated_user
        authenticated = yield self.authenticate(handler, data)
      File "/apps/anaconda3/lib/python3.5/types.py", line 243, in wrapped
        coro = func(*args, **kwargs)
      File "/tmp/ldapauthenticator/ldapauthenticator/ldapauthenticator.py", line 311, in authenticate
        userdn = dn.format(username=resolved_username)
    ValueError: Single '{' encountered in format string

[D 2018-01-16 10:08:40.049 JupyterHub base:633] No template for 500
[E 2018-01-16 10:08:40.109 JupyterHub log:114] {
      "Content-Length": "35",
      "X-Forwarded-Port": "8001",
      "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36",
      "Connection": "close",
      "Host": "<<IPAddress>>:8001",
      "Upgrade-Insecure-Requests": "1",
      "Content-Type": "application/x-www-form-urlencoded",
      "Referer": "http://<<IPAddress>>:8001/hub/login?next=",
      "X-Forwarded-For": "<<IPAddress>>",
      "X-Forwarded-Host": "<<IPAddress>>:8001",
      "Origin": "http://<<IPAddress>>:8001",
      "Accept-Language": "en-US,en;q=0.9",
      "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
      "Accept-Encoding": "gzip, deflate",
      "X-Forwarded-Proto": "http",
      "Cache-Control": "max-age=0"
    }
[E 2018-01-16 10:08:40.110 JupyterHub log:122] 500 POST /hub/login?next= (@<<IPAddress>>) 3447.59ms

Any help to resolve this issue will be highly appreciated.

Thanks

Change username_template to bind_dn

Not a big deal, but what you've got as the username_template (6) is typically called the bind_dn (half dozen) in most LDAP configurations.

Thanks for this authenticator btw!

can't specify Tls object or parameters

According to http://ldap3.readthedocs.io/ssltls.html#the-tls-object

IF you don’t use a specific Tls object and set use_ssl=True in the Server definition, a default Tls object will be used, it has no certificate files, uses the ssl.PROTOCOL_SSLv23 (if available in your Python interpreter) and performs no validation of the server certificate.

I need to specify certificate file and other options. Am I missing someway to do this? My python is a not the strongest.

Need help with AD authentication

My LDAP server users below bind template

CN=Full name,OU=Read Only,OU=gCOR,OU=Employees,OU=Accounts,OU=Administrative Root,DC=cdaws,DC=mycompany,DC=com

What configuration variable do I need to set in "jupyterhub_config.py"

I tried with below variables and got error "Invalid username"

c.JupyterHub.authenticator_class = 'ldapauthenticator.LDAPAuthenticator'
c.LDAPAuthenticator.server_address = 'cdaws.mycompany.com'
c.LDAPAuthenticator.bind_dn_template = 'CN={username},OU=Read Only,OU=gCOR,OU=Employees,OU=Accounts,OU=Administrative Root,DC=cdaws,DC=mycompany,DC=com'
c.LDAPAuthenticator.use_ssl = False

I can authenticate from python command prompt using below code

>>> from ldap3 import Server, Connection, ALL, NTLM
>>> server = Server('cdaws.mycompany.com', get_info=ALL)
>>> conn = Connection(server, 'CN=My Full Name,OU=Read Only,OU=gCOR,OU=Employees,OU=Accounts,OU=Administrative Root,DC=cdaws,DC=mycompany,DC=com', 'mypassword', auto_bind=True)
>>> conn.extend.standard.who_am_i()
'u:cdawsmycompany\\First.lastname'

Authentication against Active directory stopped working

Since commit c881a9f the working authentication against Active directory does not work anymore.

from the logs:

after c881a9f

[D 2018-06-12 14:01:04.368 JupyterHub ldapauthenticator:299] TYPE= 'True'
[D 2018-06-12 14:01:04.369 JupyterHub ldapauthenticator:223] Looking up user with search_base=DC=example,dc=com, search_filter='(sAMAccountName=x.matthias)', attributes=sAMAccountName
[D 2018-06-12 14:01:04.587 JupyterHub ldapauthenticator:278] Attempting to bind x.matthias with CN=X Matthias\,OU=Users\,DC=example\,DC=com
[D 2018-06-12 14:01:04.589 JupyterHub ldapauthenticator:330] Status of user bind x.matthias with CN=X Matthias\,OU=Users\,DC=example\,DC=com : False
    LDAPBindError: automatic bind not successful - invalidCredentials

before

[D 2018-06-12 14:09:53.714 JupyterHub ldapauthenticator:299] TYPE= 'True'
[D 2018-06-12 14:09:53.715 JupyterHub ldapauthenticator:223] Looking up user with search_base=DC=example,dc=com, search_filter='(sAMAccountName=x.matthias)', attributes=sAMAccountName
[D 2018-06-12 14:09:53.943 JupyterHub ldapauthenticator:278] Attempting to bind x.matthias with CN=X Matthias,OU=Users,DC=example,DC=com
[D 2018-06-12 14:09:54.709 JupyterHub ldapauthenticator:328] Status of user bind x.matthias with CN=X Matthias,OU=Users,DC=example,DC=com : True
[D 2018-06-12 14:09:54.709 JupyterHub ldapauthenticator:334] username:x.matthias Using dn CN=X Matthias,OU=Users,DC=example,DC=com
[D 2018-06-12 14:09:54.716 JupyterHub base:268] Setting cookie for x.matthias: jupyter-hub-token, {'httponly': True}

The problem seems to be the escaped , - which does not work against Windows AD controllers, and currently cannot be disabled (at least not that i'd have found it).

related config:

c.JupyterHub.authenticator_class = 'ldapauthenticator.LDAPAuthenticator'
c.LDAPAuthenticator.user_attribute = 'sAMAccountName'

c.LDAPAuthenticator.server_address = 'ldap://domaincontroller.example.com'
c.LDAPAuthenticator.server_port = 3268
c.LDAPAuthenticator.lookup_dn = True
c.LDAPAuthenticator.lookup_dn_search_filter = '({login_attr}={login})'
c.LDAPAuthenticator.lookup_dn_search_user = 'CN=HelperUser,OU=Service Accounts,OU=Rights and Policies,OU=GA,DC=example,DC=com'
c.LDAPAuthenticator.lookup_dn_search_password = '<password>'
c.LDAPAuthenticator.base_dn = 'dc=example,dc=com'
c.LDAPAuthenticator.bind_dn_template = [
        '{username}',
]
c.LDAPAuthenticator.user_search_base = 'dc=example,dc=com'
c.LDAPAuthenticator.user_attribute = 'sAMAccountName'
c.LDAPAuthenticator.lookup_dn_user_dn_attribute = 'DistinguishedName'
c.LDAPAuthenticator.escape_userdn = False
c.LDAPAuthenticator.allowed_groups = [
    'CN=JHub-Admin,OU=Groups,OU=Rights and Policies,OU=GA,DC=example,DC=com'
]

unfortunately, changing escape_userdn did not have any effect, as it's in an area where this is not checked.

resolved_username = re.subn(r"([^\\]),", r"\1\,", resolved_username)[0]

All attributes have been changed to "example.com" ...

Allow configuring SSL

Hi,

My OpenLDAP is only accessible through SSL (636). On linux machines I simply add the following to "/etc/ldap/ldap.conf":

TLS_CACERT /etc/ldap/ca_certs.pem

This lets me communicate to my LDAP server over SSL and lets users to SSH to the machine easily.

Now the problem in ldapauthenticator, I have these configs:

c.JupyterHub.authenticator_class = 'ldapauthenticator.LDAPAuthenticator'
c.LDAPAuthenticator.server_address = 'ldaps://myLdapServer'
c.LDAPAuthenticator.user_attribute = 'uid'
c.LDAPAuthenticator.bind_dn_template = 'uid={username},ou=People,dc=domain,dc=com'

Since there is no place to mention TLS file I am assuming it uses the system LDAP config. I can connect to LDAP server (accepted), it shows the right bind_dn but it shows this error:

JupyterHub ldapauthenticator:154] Invalid password for user uid=myUserName,ou=People,dc=domain,dc=com

And on the LDAP server it gives me:

RESULT tag=97 err=49 text=

Is it right to assume there is a SSL problem? How can I solve this issue.

Many thanks.

lookup_dn_search_user not recognized by 'LDAPAuthenticator'

hi, im trying to bind this module but im failed.
How do I resolve this issue?
Please forgive me for not being able to write english very well..

JupyterHub configurable:168] Config option lookup_dn_search_user not recognized by LDAPAuthenticator. Did you mean lookup_dn?
JupyterHub configurable:168] Config option lookup_dn_search_password not recognized by LDAPAuthenticator.

LDAP Config options not recognized by LDAPAuthenticator

Hi All,

I have configured the parameters as per the instructions to authenticate users using LDAPAuthenticator.
But I am getting few errors while starting JupyterHub and unable to authenticate users. Can anyone please help me on this. Please note LDAP users are not present in the local system nor I wish to create them. Hope it is possible to authenticate users against LDAP without need of user creation in local system. Correct me if am wrong.

JupyterHub startup Logs:

[W 2017-11-29 16:40:17.164 JupyterHub configurable:168] Config option lookup_dn_search_filter not recognized by LDAPAuthenticator.
[W 2017-11-29 16:40:17.165 JupyterHub configurable:168] Config option lookup_dn_search_user not recognized by LDAPAuthenticator. Did you mean lookup_dn?
[W 2017-11-29 16:40:17.165 JupyterHub configurable:168] Config option lookup_dn_search_password not recognized by LDAPAuthenticator.
[W 2017-11-29 16:40:17.165 JupyterHub configurable:168] Config option lookup_dn_user_dn_attribute not recognized by LDAPAuthenticator. Did you mean user_attribute?
[W 2017-11-29 16:40:17.166 JupyterHub configurable:168] Config option escape_userdn not recognized by LDAPAuthenticator.
[W 2017-11-29 16:40:17.166 JupyterHub app:966] No admin users, admin interface will be unavailable.
[W 2017-11-29 16:40:17.166 JupyterHub app:967] Add any administrative users to c.Authenticator.admin_users in config.
[I 2017-11-29 16:40:17.166 JupyterHub app:994] Not using whitelist. Any authenticated user will be allowed.
[D 2017-11-29 16:40:17.190 JupyterHub user:184] Creating <class 'jupyterhub.spawner.LocalProcessSpawner'> for idap_user:
[D 2017-11-29 16:40:17.193 JupyterHub app:1222] Loading state for idap_user from db
[W 2017-11-29 16:40:17.193 JupyterHub app:1242] idap_user appears to have stopped while the Hub was down
[D 2017-11-29 16:40:17.202 JupyterHub user:184] Creating <class 'jupyterhub.spawner.LocalProcessSpawner'> for satish_agrawal01:
[D 2017-11-29 16:40:17.204 JupyterHub app:1222] Loading state for satish_agrawal01 from db
[W 2017-11-29 16:40:17.204 JupyterHub app:1242] satish_agrawal01 appears to have stopped while the Hub was down
[D 2017-11-29 16:40:17.208 JupyterHub app:1252] Loaded users:
idap_user
satish_agrawal01
[I 2017-11-29 16:40:17.213 JupyterHub app:1539] Hub API listening on http://127.0.0.1:8081/hub/
[W 2017-11-29 16:40:17.213 JupyterHub proxy:415]
Generating CONFIGPROXY_AUTH_TOKEN. Restarting the Hub will require restarting the proxy.
Set CONFIGPROXY_AUTH_TOKEN env or JupyterHub.proxy_auth_token config to avoid this message.

[W 2017-11-29 16:40:17.214 JupyterHub proxy:456] Running JupyterHub without SSL. I hope there is SSL termination happening somewhere else...
[I 2017-11-29 16:40:17.214 JupyterHub proxy:458] Starting proxy @ http://10.0.0.40:8000/
[D 2017-11-29 16:40:17.214 JupyterHub proxy:459] Proxy cmd: ['configurable-http-proxy', '--ip', '10.0.0.40', '--port', '8000', '--api-ip', '127.0.0.1', '--api-port', '8001', '--error-target', 'http://127.0.0.1:8081/hub/error']
16:40:17.331 - info: [ConfigProxy] Proxying http://10.0.0.40:8000 to (no default)
16:40:17.334 - info: [ConfigProxy] Proxy API at http://127.0.0.1:8001/api/routes
[D 2017-11-29 16:40:17.371 JupyterHub proxy:491] Proxy started and appears to be up
[D 2017-11-29 16:40:17.378 JupyterHub proxy:552] Proxy: Fetching GET http://127.0.0.1:8001/api/routes
[W 2017-11-29 16:40:17.386 JupyterHub proxy:304] Adding missing default route
[I 2017-11-29 16:40:17.387 JupyterHub proxy:370] Adding default route for Hub: / => http://127.0.0.1:8081
[D 2017-11-29 16:40:17.387 JupyterHub proxy:552] Proxy: Fetching POST http://127.0.0.1:8001/api/routes/
16:40:17.387 - info: [ConfigProxy] 200 GET /api/routes
16:40:17.392 - info: [ConfigProxy] Adding route / -> http://127.0.0.1:8081
16:40:17.393 - info: [ConfigProxy] 201 POST /api/routes/
[I 2017-11-29 16:40:17.393 JupyterHub app:1592] JupyterHub is now running at http://10.0.0.40:8000/
[I 2017-11-29 16:40:43.489 JupyterHub log:122] 302 GET / → /hub (@10.110.92.177) 0.63ms
[I 2017-11-29 16:40:43.644 JupyterHub log:122] 302 GET /hub → /hub/login (@10.110.92.177) 0.42ms
[I 2017-11-29 16:40:43.839 JupyterHub log:122] 200 GET /hub/login (@10.110.92.177) 39.15ms
[D 2017-11-29 16:40:44.488 JupyterHub log:122] 200 GET /hub/static/css/style.min.css?v=14dc0b5a8b791d573b687aa626aa2600 (@10.110.92.177) 7.93ms
[D 2017-11-29 16:40:44.492 JupyterHub log:122] 200 GET /hub/static/components/requirejs/require.js?v=e7199843dfd445bb66ec816e98a03214 (@10.110.92.177) 0.57ms
[D 2017-11-29 16:40:44.493 JupyterHub log:122] 200 GET /hub/static/components/jquery/jquery.min.js?v=c9f5aeeca3ad37bf2aa006139b935f0a (@10.110.92.177) 0.57ms
[D 2017-11-29 16:41:11.536 JupyterHub log:122] 200 GET /favicon.ico (@10.110.92.177) 3.98ms
[W 2017-11-29 16:42:39.074 JupyterHub ldapauthenticator:154] Invalid password for user CN=satish_agrawal01,OU=GEN,OU=Users,OU=IVL,OU=BHU,OU=IND,DC=ad,DC=company,DC=com
[W 2017-11-29 16:42:39.074 JupyterHub base:350] Failed login for satish_agrawal01

Here is my jupyterhub_config.py:

c.Spawner.cmd = ['/opt/anaconda3/bin/jupyterhub-singleuser']
c.JupyterHub.authenticator_class = 'ldapauthenticator.LDAPAuthenticator'
c.LDAPAuthenticator.server_address = '10.X.Y.1'
c.LDAPAuthenticator.server_port = 389
#c.LDAPAuthenticator.bind_dn_template = ['CN={username},OU=GEN,OU=Users,OU=IVL,OU=BHU,OU=IND,DC=ad,DC=company,DC=com','CN={username},OU=SPL,OU=Users,OU=KRK,OU=BHU,OU=IND,DC=ad,DC=company,DC=com']
c.LDAPAuthenticator.bind_dn_template = '{username}'
c.LDAPAuthenticator.lookup_dn = True
c.LDAPAuthenticator.use_ssl = False
c.LDAPAuthenticator.lookup_dn_search_filter = '({login_attr}={login})'
c.LDAPAuthenticator.lookup_dn_search_user = 'CN=admin user,OU=SPL,OU=Users,OU=KRK,OU=BHU,OU=IND,DC=ad,DC=company,DC=com'
c.LDAPAuthenticator.lookup_dn_search_password = 'myPassword'
c.LDAPAuthenticator.user_search_base = 'DC=ad,DC=company,DC=com'
c.LDAPAuthenticator.user_attribute = 'sAMAccountName'
c.LDAPAuthenticator.lookup_dn_user_dn_attribute = 'cn'
c.LDAPAuthenticator.escape_userdn = False

Ldapauthenticator on pypi is not updated

Installation via pypi does not result in the same install as from github.

A key missing feature from install via pypi is multiple bind_dn by providing a list.

Allow configuring groupattributes in group search

I'm not the best understanding LDAP standards or syntax but it seems that currently the authenticator is limited in the group attributes it understands:

groupattributes = ['member', 'uniqueMember', 'memberUid']

The LDAP server I'm working with uses memberOf so we have to skip using allowed groups at the moment.

This might be another worthwhile config option for this authenticator.

As an administrator, I would like LDAP authenticated users to automatically have accounts created on my system so that I can automate this process.

Using the LDAP authenticator, I'm able to authenticate users.

For example, the user exists in the LDAP server and also has a linux user account on the hub server. Login and authentication works fine.

If a user exists in the LDAP server though but does not have a corresponding linux system account on the hub, I get the following error:

     File "/usr/lib/python3.4/site-packages/jupyterhub/spawner.py", line 439, in user_env
        home = pwd.getpwnam(self.user.name).pw_dir
    KeyError: 'getpwnam(): name not found: angie'

Can the LDAP authenticator be used with the PAM/LocalAuthenticator capabalities and create this user if they don't exist?

500 Error if "Sign In" Button Clicked Multiple Times

If a user clicks the "Sign In" button multiple times, or attempts to authenticate simultaneously in different tabs, an error is raised and the user gets forwarded to a 500 page.
From the logs:

[D 2017-09-20 15:30:24.295 JupyterHub ldapauthenticator:267] Attempting to bind username with cn=username,OU=Users,DC=wikimedia,DC=org
[I 2017-09-20 15:30:24.590 JupyterHub spawner:766] PVC claim-username already exists, so did not create new pvc.
[D 2017-09-20 15:30:25.826 JupyterHub ldapauthenticator:283] TYPE= 'False'
[D 2017-09-20 15:30:25.826 JupyterHub ldapauthenticator:267] Attempting to bind username with cn=username,OU=Users,DC=wikimedia,DC=org
[E 2017-09-20 15:30:26.141 JupyterHub web:1590] Uncaught exception POST /hub/login?next= (192.168.166.128)
    HTTPServerRequest(protocol='http', host='jupyter.wikimedia.org', method='POST', uri='/hub/login?next=', version='HTTP/1.1', remote_ip='192.168.166.128', headers={'Host': 'jupyter.wikimedia.org', 'Origin': 'https://jupyter.wikimedia.org', 'Cache-Control': 'max-age=0', 'X-Forwarded-Host': 'jupyter.wikimedia.org', 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36', 'Accept-Language': 'en-US,en;q=0.8', 'Upgrade-Insecure-Requests': '1', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'X-Forwarded-Proto': 'http', 'X-Forwarded-Port': '80', 'X-Forwarded-For': '192.168.166.128', 'Content-Length': '42', 'Accept-Encoding': 'gzip, deflate, br', 'Connection': 'close', 'Referer': 'https://jupyter.wikimedia.org/hub/login?next='})
    Traceback (most recent call last):
      File "/usr/local/lib/python3.5/dist-packages/tornado/web.py", line 1511, in _execute
        result = yield result
      File "/usr/local/lib/python3.5/dist-packages/jupyterhub/handlers/login.py", line 84, in post
        yield self.spawn_single_user(user)
      File "/usr/local/lib/python3.5/dist-packages/jupyterhub/handlers/base.py", line 306, in spawn_single_user
        raise RuntimeError("Spawn already pending for: %s" % user.name)
    RuntimeError: Spawn already pending for: username
    
[D 2017-09-20 15:30:26.141 JupyterHub base:462] No template for 500
[E 2017-09-20 15:30:26.145 JupyterHub log:99] {
      "Host": "jupyter.wikimedia.org",
      "Origin": "https://jupyter.wikimedia.org",
      "Cache-Control": "max-age=0",
      "X-Forwarded-Host": "jupyter.wikimedia.org",
      "Content-Type": "application/x-www-form-urlencoded",
      "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36",
      "Accept-Language": "en-US,en;q=0.8",
      "Upgrade-Insecure-Requests": "1",
      "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
      "X-Forwarded-Proto": "http",
      "X-Forwarded-Port": "80",
      "X-Forwarded-For": "192.168.166.128",
      "Content-Length": "42",
      "Accept-Encoding": "gzip, deflate, br",
      "Connection": "close",
      "Referer": "https://jupyter.wikimedia.org/hub/login?next="
    }
[E 2017-09-20 15:30:26.145 JupyterHub log:100] 500 POST /hub/login?next= (@192.168.166.128) 317.60ms

The relevant bit seems to be

RuntimeError: Spawn already pending for: username

LDAPAuthenticator w/zero to jh on K8s

Hi everyone!

Been trying to get this tested working but with little success. Finding depending on a variety of configurations (mostly those I have found that DO work in other JH deployments) end up with the same results - failed container deployment with either of the two outputs:

ModuleNotFoundError: No module named 'ldapauthenticator'

or

The 'authenticator_class' trait of <jupyterhub.app.JupyterHub object at 0x7fd65c760f60> instance must be a type, but 'ldapauthenticator.LDAPAuthenticator' could not be imported

I am deploying with the v6 HELM chart, but have tried with 04, and 050 as well.

When I exec the container I can see that the package is deployed to the container (jupyterhub-ldapauthenticator==1.2.1)

Ive tried to pair the config down to just the instantiation of the adapter, the ldap server, and the template to try and get even the base config to load but with no luck.

I am supplying the config params via the config yaml in the hub extraconfig section. I am wondering if I have an issue in there with not having the right pathing/logic.

Has anyone gotten this to work with the zero-to-jp deployment path?

Thanks!!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.