Can't get LDAP auth

Issue #59 resolved
IT Expert created an issue

Can not login via MS Active Directory.

in go-d.ini set options:

auth_policy: 'auth'
ldap_host: 'server'
ldap_port: 389
ldap_dn: 'dc=server,dc=local'
ldap_base_dn_filter: 'ou=MyOu'
ldap_base_dn_group_filter: 'My_Group'
ldap_admin_dn: 'user'
ldap_admin_password: 'pass'

try login to god-web (running in docker container)

get logs:

2018-01-22 11:14:01,820 ERROR [root][DummyThread-8] 'NoneType' object has no attribute 'bind_credentials' 2018-01-22 11:14:06,861 DEBUG [gunicorn.error][DummyThread-9] POST /user/bind 2018-01-22 11:14:06,861 DEBUG [gunicorn.error][DummyThread-9] POST /user/bind 2018-01-22 11:22:14,763 ERROR [root][DummyThread-9] 'NoneType' object has no attribute 'bind_credentials'

fake auth works fine :)

Comments (19)

  1. Olivier Sallou repo owner

    in go-d.ini, auth_policy should be "goauth", not "auth", unless you created your own plugin.

  2. Olivier Sallou repo owner

    for ms active directory you may also need to map the homeDirectory field in config , it may use a different field name. Can be customized in ldap / fields / homeDirectory config:

    ldap:
        tls: false
        # LDAP field mapping
        fields:
            homeDirectory: 'homeDirectory'
        ids:
            - 'uid'
            - 'mail'
            - 'sn'
    
  3. IT Expert reporter

    May be you have docs or recommendations, howtos? How to configure it right ?

    Tried different options even add NTLM support in plugin

    from ldap3 import Server, Connection, SUBTREE, NTLM
    
     if 'ldap_admin_dn' in self.cfg and self.cfg['ldap_admin_dn']:
                    con = Connection(
                        s,
                        user=self.cfg['ldap_admin_dn'],
                        password=self.cfg['ldap_admin_password'],
                        authentication=NTLM
                    )
    

    Is it necessary NTLM support for ldap3 module connection to MS AD ? Or it still support simple method ?

    Last logs that I seen was like:

    2018-01-22 16:40:57,907 DEBUG [gunicorn.error][DummyThread-5] POST /user/bind
    2018-01-22 16:40:57,907 DEBUG [gunicorn.error][DummyThread-5] POST /user/bind
    2018-01-22 16:40:58,809 DEBUG [gunicorn.error][DummyThread-5] POST /user/bind
    2018-01-22 16:40:58,809 DEBUG [gunicorn.error][DummyThread-5] POST /user/bind
    2018-01-22 16:41:20,317 DEBUG [gunicorn.error][DummyThread-6] POST /user/bind
    2018-01-22 16:41:20,317 DEBUG [gunicorn.error][DummyThread-6] POST /user/bind
    

    with config like this:

    auth_policy: 'goauth'
    
    # LDAP
    ldap_host: 'server'
    ldap_port: 389
    ldap_dn: 'CN=Users,DC=domain,DC=local'
    # ldap_base_dn_filter without ldap_dn
    ldap_base_dn_filter: 'OU=Ou1,OU=Ou2'
    #ldap_base_dn_group_filter: 'objectClass=group'
    ldap_admin_dn: 'domain\user'
    ldap_admin_password: 'pass'
    
    ldap:
        # Use ldaps (check that ldap_port matches ssl port of the ldap server)
        ssl: false
        # LDAP field mapping
        fields:
            homeDirectory: 'homeDirectory'
        # Fields use to map user login against ldap entries
        ids:
            - 'samAccountName'
            - 'mail'
            - 'sn'
    

    But still no luck, users can't auth.

  4. Olivier Sallou repo owner

    I do not have active directory, so I can't test, but someone already made it work with a Microsoft ldap. I do not know NTLM, but should work without. Should try to log python ldap result.

    Seems no exception is raised, so it is not an error itself. Now, does it fail at connection with ldap_admin_dn or user credentials binding?

    First case should have raise "LDAP simple anon bind failed" error log. At user credentials binding, log "'User binding failed'" should appear.

    If no error log appears, it seems issue occurs at:

    con.search(
                search_base=base_dn,
                search_scope=SUBTREE,
                search_filter=ldap_filter,
                attributes=attrs
            )
    

    So maybe filter do not match for MS Active Directory?

    base filter would be with your config:

    filter = "(&""(|(samAccountName="loginName")(mail="loginName")(sn="loginName")))

    with base_dn = 'OU=Ou1,OU=Ou2,CN=Users,DC=domain,DC=local'

    is it the expected one for your LDAP to find a user? users are located under Users/Ou1/Ou2 ?

  5. Olivier Sallou repo owner

    seems by the way that ntlm is quite old and kerberos mostly used in this case.

    some organization used kerberos on web proxy side to send REMOTE_USER header to go-docker and bypass user credentials. But anyway your pb rather seem to occur on user search than binding.

  6. Olivier Sallou repo owner

    In my conf with openldap i have more something like

    Ldap_dn: 'dc=genouest,dc=org' ldap_base_dn_filter: 'ou=People'

    The base dn is added to dn filter to search user in ldap hierarchy. It searches in dubtree a user with a ldap configured id equal to the user login given in login page. Then found user dn is used for credentials binding.

    But it depends on ldap settings....

  7. MWigger

    Hello, I have it working with an MS AD with this settings:

    auth_policy: 'goauth'
    
    ldap_host: 'MYDC.MYDOMAIN.NET'
    ldap_port: 636
    ssl: true
    
    
    ldap_dn: 'DC=MYDOMAIN,DC=net'
    ldap_admin_dn: 'cn=MYLDAPUSER,dc=MYDOMAIN,dc=net'
    ldap_admin_password: 'MYPASSWORD'
    
    ldap_base_dn_filter: 'ou=MYOU'
    
    
    ldap:
        # Use ldaps (check that ldap_port matches ssl port of the ldap server)
        ssl: true
    
        fields:
            homeDirectory: 'unixHomeDirectory'
        ids:
           - 'uid'
           - 'mail'
           - 'userPrincipalName'
    

    Probably the userPrincipalName is missing at ids I also use the full CN for ldap_admin (not sure if needed, but you might give it a try)

    There are also AD Setups that forbid non-SSL connection

    As Olivier mentioned, this has nothing to do with Kerberos at this point. You need Kerberos when you want SSO (I have that running as well, so give a hint if you need support with that)

  8. IT Expert reporter

    Thank you, guys. Still no luck.

    In goauth.py after results = con.response

    added self.logger.error(results)

    Now I see that user was found, but it uid, uidNumber, gidNumber is empty

    2018-01-23 15:38:20,869 ERROR [godweb][DummyThread-3] [{'attributes': {'uidNumber': [], 'gidNumber': [], 'uid': [], 'mail': 'j.dou@company.com', 'homeDirectory': []}, 'raw_dn': b'CN=John Doe,OU=Ou1,DC=domain,DC=local', 'type': 'searchResEntry', 'dn': 'CN=John Doe,OU=Ou1,DC=domain,DC=local', 'raw_attributes': {'uidNumber': [], 'gidNumber': [], 'uid': [], 'mail': [b'j.doe@comapany.com'], 'homeDirectory': []}}]

  9. Olivier Sallou repo owner

    well, depends on how users are configured in your ldap (schemas). DO you have posix account schema?

    if you look at your ldap directly, where are stored user uid, gid and homeDirectory information? To execute a job, godocker need a uid,gid and homeDir (though last is less important if home dir is not proposed as shared dir in config).

  10. IT Expert reporter

    Looks like we haven't posix account schema. was modified plugin to get all attrs

     con.search(
                    search_base=base_dn,
                    search_scope=SUBTREE,
                    search_filter=ldap_filter,
                    attributes=['*']
                )
    

    So I have only next attrs with ID: objectSid': 'S-1-5-21-555555555-5555555555-5555555-555555 objectGUID': '81fc234f3-fd34-34e1-b37e-sdfa43423' primaryGroupID': 521

  11. Olivier Sallou repo owner

    Is primay group is a unix group? Objectuid is not a unix id.

    On linux compute host, which uid, gid do you have?

    If you want only authentication and don't care of uid/gid because there is none in your ldap, you can modify goauth plugin to hard code the home/uid/gid values, but they must match existing ones on scheduler and compute hosts Impact is all users will share the same ids.

  12. IT Expert reporter

    Thank you. I modified goauth plugin like this:

    attrs = ['mail','sAMAccountName', 'uid', 'uidNumber', 'gidNumber', homeDirectoryField]
                con.search(
                    search_base=base_dn,
                    search_scope=SUBTREE,
                    search_filter=ldap_filter,
                    attributes=attrs
                )
                results = con.response
                self.logger.error(results)
    
                user_dn = None
                if results:
                    sAMAccountName = None
                    ldapMail = None
                    userId = None
                    uidNumber = None
                    gidNumber = None
                    homeDirectory = None
                    # user_dn = None
                    for res in results:
                        dn = res['dn']
                        user_dn = str(dn)
                        entry = res['raw_attributes']
                        if 'sAMAccountName' not in entry:
                            self.logger.error('Uid not set for user ' + user)
                        userId = entry['sAMAccountName'][0]
                        uidNumber = 1001
                        gidNumber = 1001
                        homeDirectory = '/home/' + userId
                        if 'mail' in entry and entry['mail']:
                            ldapMail = entry['mail'][0]
    
                    #sgids = self.__get_ldap_groups(con, userId)
                    sgids = []
    

    Now I have binded user accounts from MS AD. Then I modified godscheduler.py to run all tasks under root instead of binded user. Looks like it works for me. Users can auth in god-web, create jobs and projects, and run it.

  13. Olivier Sallou repo owner

    why modifying godscheduler? this is not needed. Jobs will be executed with user id 1001/1001 in the container, meaning only that jobs are run in non-root env in the container and that files will be created with this id (in job directory or home if available) If root env is needed in container, then in webui (or cli) you can ask to run job as root.

    Running as non-root in container lowers some risks, and avoid to have some files owned by root.

  14. IT Expert reporter

    why modifying godscheduler?

    Had corrected generation of godocker.sh file, because container had failed with following errors:

    I0124 11:37:47.408515  7691 exec.cpp:162] Version: 1.2.0
    I0124 11:37:47.413172  7695 exec.cpp:237] Executor registered on agent 1d2d8f83-e7ff-40ff-bf38-d21248192ca6-S40
    userdel: user root is currently used by process 7709
    groupadd: GID '0' already exists
    useradd: UID 0 is not unique
    usermod: user 'myuser' does not exist
    No passwd entry for user 'myuser'
    chown: invalid user: 'myuser:0'
    

    I tried with different uidNumber, gidNumber, but no luck.

  15. Olivier Sallou repo owner

    this is because you used user id/gid 0, which is root. godocker tried to created the user in container (and of course root already exists and cannot be recreated).

    you must use a non root user (1001 in your updated goauth is fine), and you should get no error.

  16. Log in to comment