0

I'm using Python ldap3 module to work with an OpenLDAP server. I've been able to query, and add, users to an OU, but can't figure how to add users to groups (both POSIX and memberOf/groupOfNames overlay). I found an Active Directory "way" of doing it here but how do I adapt that example for OpenLDAP? Not even sure from ldap3 import Server, Connection, ALL, NTLM is a thing on Linux.

Trying the code below. User is added to the directory, but adding to the POSIX group ldap-users fails with a cascade of errors but this looks like the culprit. Not sure what I have messed up with the objectClass attributes:

LDAPInvalidAttributeSyntaxResult - 21 - invalidAttributeSyntax - None - objectClass: value #0 invalid per syntax

I thought I'd leave the POSIX groups for later and try the memberOf overlay (adding user to the admins groupOfNames object) but I'm stuck on that one with

ImportError: No module named 'ldap3.modlist'

Not sure why module ldap3.modlist isn't available. Shouldn't that be included with the Ubuntu/python ldap3 package? Tried importing it explicitly.

   import ldap3.modlist as modlist
   import json
   import urllib.request
   from urllib.error import URLError, HTTPError
   import getopt, sys, logging
   from ldap3 import Server, Connection, ALL
   ...
   # retrieve user details from HR database
   ldap_user = PersonFromHRDB(person_id)

   # fill in the template of attributes we need to give to the ldap server
   attributes = {   'givenName': ldap_user.givenName,
                           'sn': ldap_user.sn,
                  'displayName': ldap_user.displayName,
                          'uid': ldap_user.uidNumber,
                'homeDirectory': ldap_user.homeDirectory,
                 ...}

   # add user to DIT via their dn (dn:uid=user101,ou=people,dc=my,dc=dom)
   conn.add(ldap_user.dn, ['posixAccount', 'top', 'inetOrgPerson', 'shadowAccount'], attributes)

   # add user to a the 'ldap-users' POSIX group
   conn.add('cn=ldap-users,ou=groups,dc=my,dc=dom', {'memberUid': ldap_user.cn})

   # add user to 'admins' groupOfNames (memberOf overlay) object
   group_dn = 'cn=admins,ou=groups,dc=my,dc=dom'
   conn.modify_s (group_dn, [ modlist.MOD_ADD, 'member', [ldap_user.dn]])
Server Fault
  • 637
  • 1
  • 6
  • 16
  • 1
    What have you tried so far? I suspect you'll need to make use of the ldap [modify](https://ldap3.readthedocs.io/modify.html) operation. – larsks Aug 19 '19 at 17:57
  • Code added. does `modify` work if the user doesn't currently exist? I suspect that operation is a bit like an LDIF file -- if the user doesn't exist, it's an `add`. If they do exist, it's a `modify` but maybe I'm wrong. – Server Fault Aug 19 '19 at 19:51

1 Answers1

0

For anyone else running across this, I had to add MODIFY_ADD to my ldap3 imports first. Then using conn.modify() as suggested by @larsks (modifed code below) to add the user to the openLDAP group.

Adding a user to a POSIX group vs. memberOf overlay is basically the same function but the attributes and user values are different. POSIX group uses the memberUid attribute and the user CN value whereas the memberOf overlay uses a member attribute along with the full DN: for the user.

Also, conn.modify() will hurl if the user already exists in the group and you try an add it, so, have to check first to see if the user is already there.

   import ldap3.modlist as modlist
   import json
   import urllib.request
   from urllib.error import URLError, HTTPError
   import getopt, sys, logging
   from ldap3 import Server, Connection, ALL, MODIFY_REPLACE, MODIFY_ADD, MODIFY_DELETE

   ...
   # retrieve user details from HR database
   ldap_user = PersonFromHRDB(person_id)

   # fill in the template of attributes we need to give to the ldap server
   attributes = {   'givenName': ldap_user.givenName,
                           'sn': ldap_user.sn,
                  'displayName': ldap_user.displayName,
                          'uid': ldap_user.uidNumber,
                'homeDirectory': ldap_user.homeDirectory,
                 ...}

   # add user to DIT via their dn (dn:uid=user101,ou=people,dc=my,dc=dom)
   conn.add(ldap_user.dn, ['posixAccount', 'top', 'inetOrgPerson', 'shadowAccount'], attributes)

   group_dn = 'cn=ldap-users,ou=groups,dc=my,dc=dom'
   # default to POSIX attributes/values
   attribute = 'memberUid'
   user_value = ldap_user.cn

   if my_userExistsInGroup (ldap_user, group_dn) is False:
      # adjust for memberOf
      if my_isPosixGroup (group_dn) is False:
         attribute = 'member'
         user_value = ldap_user.dn

      conn.modify(group_dn, {attribute: [(MODIFY_ADD, [user_value])]})
Server Fault
  • 637
  • 1
  • 6
  • 16