github linkedin
Keystone. Synchronize users from AD to OpenLDAP [python script]
With OpenStack i need to sync users from corporate Microsoft Active Directory to OpenLDAP managed by Keystone.

As input i have list of user DNs. Script syncs only particular user parameters, such as

  • objectclass
  • mail
  • cn
  • givenName
  • sn
  • uid
  • userPassword
  • carLicense

These parameters a minimum enough for Keystone.

Usage:
1) Make sure you have “python-ldap” installed
2) Prepare “users” file with list of DNs in source AD

CN=user1,OU=USERS,DC=EXAMPLE,DC=com

CN=user2,OU=OTHER,OU=USERS,DC=EXAMPLE,DC=com

3) Start script below

./sync_users.py –users_file users

                –src_ldap_uri ldap://192.168.0.11:389

                –src_ldap_user ‘DOMAINadministrator’

                –src_ldap_pass ‘xxx’

                –dst_ldap_uri ‘ldap://10.0.0.11’

                –dst_ldap_user ‘cn=admin,dc=domain,dc=tld’

                –dst_ldap_pass xxx

                –dst_ldap_tree ‘ou=Users,dc=domain,dc=tld’

#!/usr/bin/python

import ldap

import ldap.modlist as modlist

import argparse

 

 

parser = argparse.ArgumentParser()

parser.add_argument(‘–users_file’, default=’users’)

parser.add_argument(‘–src_ldap_uri’, required=True)

parser.add_argument(‘–src_ldap_user’, required=True)

parser.add_argument(‘–src_ldap_pass’, required=True)

parser.add_argument(‘–dst_ldap_uri’, required=True)

parser.add_argument(‘–dst_ldap_user’, required=True)

parser.add_argument(‘–dst_ldap_pass’, required=True)

parser.add_argument(‘–dst_ldap_tree’, required=True)

args = parser.parse_args()

 

 

USERS_FILE = args.users_file

SRC_LDAP_URI = args.src_ldap_uri

SRC_LDAP_USER = args.src_ldap_user

SRC_LDAP_PASS = args.src_ldap_pass

DST_LDAP_URI = args.dst_ldap_uri

DST_LDAP_USER = args.dst_ldap_user

DST_LDAP_PASS = args.dst_ldap_pass

DST_LDAP_USER_TREE = args.dst_ldap_tree

 

 

def prepare_attrs(src_attrs):

    attrs = {}

    attrs[‘objectclass’] = [‘top’,’inetOrgPerson’,’organizationalPerson’,’person’]

    attrs[‘mail’] = src_attrs[“mail”]

    attrs[‘cn’] =  src_attrs[“cn”]

    attrs[‘givenName’] = src_attrs[“givenName”]

    attrs[‘sn’] = src_attrs[“sAMAccountName”]

    attrs[‘uid’] = src_attrs[“sAMAccountName”]

    attrs[‘userPassword’] = ‘{SASL}%s’ % src_attrs[“mail”]

    attrs[‘carLicense’] = ‘TRUE’

    return attrs

 

src_ldap = ldap.initialize(SRC_LDAP_URI)

src_ldap.simple_bind_s(SRC_LDAP_USER, SRC_LDAP_PASS)

 

 

dst_ldap = ldap.initialize(DST_LDAP_URI)

dst_ldap.simple_bind_s(DST_LDAP_USER, DST_LDAP_PASS)

 

 

with open(USERS_FILE) as f:

    users_to_sync = f.read().splitlines()

 

 

for user_dn in users_to_sync:

    user_cn = user_dn.split(‘,’)[0]

    user_tree = user_dn.split(‘,’, 1)[1]

    user = src_ldap.search_s(user_tree, ldap.SCOPE_ONELEVEL, user_cn)

    if user:

        dn = “cn=%s,%s” % (user_cn, DST_LDAP_USER_TREE)

        ldif = modlist.addModlist(prepare_attrs(user[0][1]))

        try:

            dst_ldap.add_s(dn,ldif)

            print “Synced user %s” % user[0][0]

        except ldap.ALREADY_EXISTS:

            print “User %s already exists” % user[0][0]

 

 

src_ldap.unbind_s()

dst_ldap.unbind_s()