[LDAP environment construction: 7] Add / search / change / delete users with Python

Reference: http://www.grotan.com/ldap/python-ldap-samples.html

ldap_client.py


#!/usr/bin/python
# -*- encoding=utf8 -*-

import ldap
from   ldap   import modlist

#----------------------------------------------------------
# LdapClient
#----------------------------------------------------------
class LdapClient(object):

    #----------------------------------------------------------
    # INIT
    #----------------------------------------------------------
    def __init__(self, ldap_host, ldap_base_dn, ldap_manager_password):

        self.ldap_base_dn       = ldap_base_dn
        self.ldap_manager_dn    = 'cn=Manager,%s' % ldap_base_dn
        self.ldap               = ldap.initialize(ldap_host)
        self.ldap.simple_bind_s(self.ldap_manager_dn, ldap_manager_password)

    #----------------------------------------------------------
    # SEARCH
    #----------------------------------------------------------
    def search_group(self, ldap_search_name):

        ldap_search_dn = 'ou=Group,%s'  % self.ldap_base_dn
        ldap_search_cn = 'cn=%s'        % ldap_search_name

        return self._search(ldap_search_dn, ldap_search_cn)

    def search_people(self, ldap_search_name):

        ldap_search_dn = 'ou=People,%s' % self.ldap_base_dn
        ldap_search_cn = 'uid=%s'       % ldap_search_name

        return self._search(ldap_search_dn, ldap_search_cn)

    def _search(self, ldap_search_dn, ldap_search_cn):

        row_ldif_list = self.ldap.search_s(ldap_search_dn,
                                           ldap.SCOPE_SUBTREE,
                                           ldap_search_cn,
                                           None)

        now_ldif_dict = {}

        for dn, entry in row_ldif_list:
            for _key, _value in entry.items():
                if _key != 'objectClass' :
                    now_ldif_dict[_key] =  _value[0]

            yield (dn, now_ldif_dict)

    #----------------------------------------------------------
    # ADD
    #----------------------------------------------------------
    def add_group(self, **keywords):

        keywords['objectclass'] = ['posixGroup', 'top']
        ldap_group_dn           = 'cn=%s,ou=Group,%s' % (keywords['cn'], self.ldap_base_dn)
        ldap_group_ldif         = modlist.addModlist(keywords)

        return self._add(ldap_group_dn, ldap_group_ldif)

    def add_people(self, **keywords):

        keywords['objectclass'] = ['account', 'posixAccount', 'top', 'shadowAccount']
        ldap_people_dn          = 'uid=%s,ou=People,%s' % (keywords['cn'], self.ldap_base_dn)
        ldap_people_ldif        = modlist.addModlist(keywords)

        return self._add(ldap_people_dn, ldap_people_ldif)

    def _add(self, dn, ldif):

        try :
            self.ldap.add_s(dn, ldif)
            return (0, dn)

        except ldap.ALREADY_EXISTS:
            return (1, 'already exists %s' % dn)

    #----------------------------------------------------------
    # DELETE
    #----------------------------------------------------------
    def delete_people(self, delete_name):

        ldap_delete_dn  = 'uid=%s,ou=People,%s' % (delete_name, self.ldap_base_dn)

        return self._delete(ldap_delete_dn)

    def delete_group(self, delete_name):

        ldap_delete_dn = 'cn=%s,ou=Group,%s'    % (delete_name, self.ldap_base_dn)

        return self._delete(ldap_delete_dn)

    def _delete(self, delete_dn):
        try :
            self.ldap.delete_s(delete_dn)
            return (0, delete_dn)

        except ldap.NO_SUCH_OBJECT, e:
            return (1, 'no such object %s' % delete_dn)

    #----------------------------------------------------------
    # MODIFY
    #----------------------------------------------------------
    def modify_people(self, name, change_ldif_dict):

        dn, now_ldif_dict = self.search_people(name).next()

        return self._modify(dn, now_ldif_dict, change_ldif_dict)


    def modify_group(self, name, change_ldif_dict):

        dn, now_ldif_dict = self.search_group(name).next()

        return self._modify(dn, now_ldif_dict, change_ldif_dict)


    def _modify(self, dn, now_ldif_dict, change_ldif_dict):

        new_ldif_dict = {}
        old_ldif_dict = {}

        for _key, _value in change_ldif_dict.items():
            if now_ldif_dict.has_key(_key):
                old_ldif_dict[_key] = now_ldif_dict[_key]
                new_ldif_dict[_key] = _value

        try :
            ldif = modlist.modifyModlist(old_ldif_dict, new_ldif_dict)
            self.ldap.modify_s(dn, ldif)
            return (0, dn, '%s > %s'  % (str(old_ldif_dict), str(new_ldif_dict)))

        except Exception, e:
            return (1, dn, e)

#----------------------------------------------------------
# SSHA python seeded salted sha password
# http://www.openldap.org/faq/data/cache/347.html
# > challenge_password = makeSecret('testing123')
# > checkPassword(challenge_password, 'testing123')
#----------------------------------------------------------
import os
import hashlib
from base64 import encodestring as encode
from base64 import decodestring as decode

def makeSecret(password):
    salt = os.urandom(4)
    h = hashlib.sha1(password)
    h.update(salt)
    return "{SSHA}" + encode(h.digest() + salt)

def checkPassword(challenge_password, password):
    challenge_bytes = decode(challenge_password[6:])
    digest = challenge_bytes[:20]
    salt = challenge_bytes[20:]
    hr = hashlib.sha1(password)
    hr.update(salt)
    return digest == hr.digest()

#----------------------------------------------------------
# TEST
#----------------------------------------------------------
def test():


    _LDAP_HOST      = 'ldap://192.168.1.11'
    _MANAGER_PASS   = 'xxxxxxxx'
    _BASE_DN        = 'dc=example,dc=com'

    a = LdapClient(_LDAP_HOST, _BASE_DN, _MANAGER_PASS)

    test_people(a)
    test_group(a)

def test_people(a):

    name      = 'user01'
    user_dict = { 'uid'           : name              ,
                  'cn'            : name              ,
                  'userPassword'  : makeSecret('pass'),
                  'uidNumber'     : '500'             ,
                  'gidNumber'     : '500'             ,
                  'homeDirectory' : '/home/hoge'      ,
                  'loginShell'    : '/bin/sh'         ,
                  'description'   : 'Description'     }

    print '\n#=== PEOPLE' + '=' * 80
    print '\n#------ SEARCH' + '-' * 80
    for i in a.search_people('*'):
        print '  %s' % i[0]

    print '\n#------ ADD' + '-' * 80
    print a.add_people(**user_dict)

    print '\n#------ MODIFY' + '-' * 80
    print a.modify_people(name, {'gidNumber':'1001'})

    print '\n#------ MODIFY' + '-' * 80
    print a.modify_people(name, {'userPassword': makeSecret('abc123')})

    print '\n#------ SEARCH' + '-' * 80
    for i in a.search_people('*'):
        print '  %s' % i[0]

    print '\n#------ DELETE' + '-' * 80
    print a.delete_people(name)

def test_group(a):

    name       = 'group01'
    group_dict = { 'cn'         : name   ,
                   'gidNumber'  : '9999' ,}

    print '\n#=== GROUP' + '=' * 80
    print '\n#------ SEARCH' + '-' * 80
    for i in a.search_group('*'):
        print '  %s' % i[0]

    print '\n#------ ADD' + '-' * 80
    print a.add_group(**group_dict)

    print '\n#------ MODIFY' + '-' * 80
    print a.modify_group(name, {'gidNumber':'1001'})

    print '\n#------ SEARCH' + '-' * 80
    for i in a.search_group('*'):
        print '  %s' % i[0]

    print '\n#------ DELETE' + '-' * 80
    print a.delete_group(name)

if __name__ == '__main__' : test()

Results

#=== PEOPLE================================================================================
>
#------ SEARCH--------------------------------------------------------------------------------
  uid=testuser,ou=People,dc=example,dc=com
>
#------ ADD--------------------------------------------------------------------------------
(0, 'uid=user01,ou=People,dc=example,dc=com')
>
#------ MODIFY--------------------------------------------------------------------------------
(0, 'uid=user01,ou=People,dc=example,dc=com', "{'gidNumber': '500'} > {'gidNumber': '1001'}")
>
#------ MODIFY--------------------------------------------------------------------------------
(0, 'uid=user01,ou=People,dc=example,dc=com', "{'userPassword': '{SSHA}3kXMTM_X5Clv1KZIAQ9vcsUZ6mswW48Q'} > {'userPassword': '{SSHA}YEVxhhsIT3OedWqlrgjQXReAeznLSiHV'}")
>
#------ SEARCH--------------------------------------------------------------------------------
  uid=testuser,ou=People,dc=example,dc=com
  uid=user01,ou=People,dc=example,dc=com
>
#------ DELETE--------------------------------------------------------------------------------
(0, 'uid=user01,ou=People,dc=example,dc=com')
>
#=== GROUP================================================================================
>
#------ SEARCH--------------------------------------------------------------------------------
  cn=testuser,ou=Group,dc=example,dc=com
>
#------ ADD--------------------------------------------------------------------------------
(0, 'cn=group01,ou=Group,dc=example,dc=com')
>
#------ MODIFY--------------------------------------------------------------------------------
(0, 'cn=group01,ou=Group,dc=example,dc=com', "{'gidNumber': '9999'} > {'gidNumber': '1001'}")
>
#------ SEARCH--------------------------------------------------------------------------------
  cn=testuser,ou=Group,dc=example,dc=com
  cn=group01,ou=Group,dc=example,dc=com
>
#------ DELETE--------------------------------------------------------------------------------
(0, 'cn=group01,ou=Group,dc=example,dc=com')

Recommended Posts

[LDAP environment construction: 7] Add / search / change / delete users with Python
Get started with Python! ~ ① Environment construction ~
Python3 environment construction with pyenv-virtualenv (CentOS 7.3)
pytorch @ python3.8 environment construction with pipenv
Move data to LDAP with python Change / Delete (Writer and Reader)
[Ubuntu 18.04] Python environment construction with pyenv + pipenv
Change Python 64bit environment to 32bit environment with Anaconda
Let's get along with Python # 0 (Environment construction)
Python environment construction
Environment construction (python)
python environment construction
Python --Environment construction
Python environment construction
python environment construction
Collecting information from Twitter with Python (Environment construction)
Poetry-virtualenv environment construction with python of centos-sclo-rh ~ Notes
First python ① Environment construction with pythonbrew & Hello World !!
From Python environment construction to virtual environment construction with anaconda
Sequential search with Python
python windows environment construction
homebrew python environment construction
Python development environment construction
Python environment with docker-compose
Binary search with python
Binary search with Python3
python2.7 development environment construction
Mac environment construction Python
Virtual environment with Python 3.6
Python environment construction @ Win7
Virtual environment construction with Docker + Flask (Python) + Jupyter notebook
[Python] OpenCV environment construction with Docker (cv2.imshow () also works)
Data analysis environment construction with Python (IPython notebook + Pandas)
Web application made with Python3.4 + Django (Part.1 Environment construction)
QGIS3 Python plugin development environment construction with VSCode (macOS)
Python + Anaconda + Pycharm environment construction
OpenJTalk on Windows10 (Speak Japanese with Python from environment construction)
Python environment construction (Windows10 + Emacs)
CI environment construction ~ Python edition ~
(For myself) Flask_8 (Add / Edit / Delete in database with python)
Build python3 environment with ubuntu 16.04
ML environment construction with Miniconda
Python environment construction For Mac
Anaconda3 python environment construction procedure
[Python] Change dtype with pandas
Prepare python3 environment with Docker
Build python environment with direnv
Python3 environment construction (for beginners)
Full bit search with Python
Python environment construction and TensorFlow
Python environment construction under Windows7 environment
[MEMO] [Development environment construction] Python
Search engine work with python
Search twitter tweets with python
Environment construction of python2 & 3 (OSX)
Streamline web search with python
Web application created with Python + Flask (using VScode) # 1-Virtual environment construction-
LaTeX and R (a little Python) environment construction with SublimeText3 (Windows)
Environment construction of python and opencv
Python environment construction memo on Windows 10
Build python virtual environment with virtualenv
Setup modern Python environment with Homebrew