1. windows + python2.7 安装 python-ldap
    https://www.lfd.uci.edu/~gohlke/pythonlibs/#python-ldap

2.python 同步密码

# encoding: utf-8
"""
  Created by Jeff Liu on 2019/12/2
"""
import ldap
import re

PORTAL_LDAP = {
    'bind_dn': '',
    'bind_pass': '',
    'ldap_server': '',
    'port':"",
    'user_dn': '',
    'group_dn': ''
}
DEVOPS_LDAP = {
    'bind_dn': '',
    'bind_pass': '',
    'ldap_server': '',
    'port':"",
    'user_dn': '',
    'group_dn': ''
}


def connect_ldap(my_ldap):
    """
    建立ldap连接
    :param my_ldap: ldap连接信息
    :return: 返回ldap连接对象
    """
    ip = my_ldap['ldap_server']
    port = my_ldap['port']
    bind_dn = my_ldap['bind_dn']
    bind_pass = my_ldap['bind_pass']
    # 如果是ldaps, 需要指定CA cert file
    # ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, "/path/to/ldaps.cert.file")
    # 如果是self-signed cert, 加上这行
    ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
    # 初始化LDAP连接
    ldap_connect = ldap.initialize('ldap://' + ip + ':' + port)
    ldap_connect.set_option(ldap.OPT_REFERRALS, 0)
    ldap_connect.protocol_version = ldap.VERSION3
    ldap_connect.simple_bind_s(bind_dn, bind_pass)
    print("ldap: {} is connected.".format(ip))
    return ldap_connect


def get_password(ldap_connect, uid, user_dn):
    """
    获取用户密码(加密)
    :param ldap_connect: ldap连接对象
    :param uid: 用户账号
    :param user_dn: 用户base dn
    :return: 用户密码信息
    """
    try:
        result_set = ldap_connect.search_s(user_dn, ldap.SCOPE_SUBTREE, 'uid=' + uid)
        name, attrs = result_set[0]
        if hasattr(attrs, 'has_key') and attrs.has_key('uid'):
            userPassword = attrs['userPassword'][0]
            return userPassword
        else:
            print "get_password error: %s not found." %uid
            return None
    except Exception, e:
        print "get_password error: uid=%s, %s" %(uid, str(e))
        return None


def change_password(ldap_to_connect, uid, user_dn, new_password):
    """
    修改用户密码
    :param ldap_to_connect: ldap连接对象
    :param uid: 用户账号
    :param user_dn: 用户base dn
    :param new_password: 新密码
    :return: 用户密码
    """
    try:
        dn = 'uid=%s, %s' %(uid, user_dn)
        modlist = [(ldap.MOD_REPLACE, 'userPassword', new_password)]
        ldap_to_connect.modify_s(dn, modlist)
        return True
    except Exception,e:
        print "change_password error: %s, %s" %(uid ,str(e))
        return False


def get_group_member(ldap_to_connect, cn, group_dn):
    """
    获取组成员
    :param ldap_to_connect: ldap连接对象
    :param cn: 组名称
    :param group_dn: 组base dn
    :return: 组成员列表
    """
    try:
        result_set = ldap_to_connect.search_s(group_dn, ldap.SCOPE_SUBTREE, 'cn=' + cn)
        name, attrs = result_set[0]
        user_pattern = 'uid=(.*?),.*'
        user_list = []
        if hasattr(attrs, 'has_key') and attrs.has_key('uniqueMember'):
            member_list_dn = attrs['uniqueMember']
            for m in member_list_dn:
                username = re.findall(user_pattern, m)
                if username:
                    user_list.append(username[0])
            return user_list
        else:
            print "get_group_member error: key not found."
            return None
    except Exception, e:
        print "get_group_member error: ", str(e)
        return None


def add_group_member(ldap_to, groupname, group_dn, user_dn, user_list):
    """
    添加组成员信息
    :param ldap_to: ldap连接对象
    :param groupname: ldap组名称
    :param group_dn: ldap group base dn
    :param user_list: 用户列表 ['1111','2222']
    :return: 返回 False/True
    """
    user_dn_list = []
    for user in user_list:
        user_dn_list.append('uid=%s,%s' %(user, user_dn))
    ldap_to_connect = connect_ldap(ldap_to)
    modlist = []
    if len(user_dn_list) == 0:
        modlist.append((ldap.MOD_REPLACE, 'uniqueMember', ""))
    for index in range(len(user_dn_list)):
        if index == 0:
            modlist.append((ldap.MOD_REPLACE, 'uniqueMember', str(user_dn_list[index])))
        else:
            modlist.append((ldap.MOD_ADD, 'uniqueMember', str(user_dn_list[index])))
    try:
        modifyDN = "cn=%s,%s" % (groupname, group_dn)
        print(modifyDN)
        print(modlist)
        ldap_to_connect.modify_s(modifyDN, modlist)
        return True
    except ldap.LDAPError, e:
        print("add_group_member: %s add group memeber failed,reason: %s" % (groupname, str(e)))
    return False


def sync(group_name, ldap_from, ldap_to):
    """
    同步用户组成员密码
    :param group_name: 组名称
    :param ldap_from: ldap 来源server
    :param ldap_to: ldap 目标server
    :return: dict 更新结果
    """
    ldap_to_connect = connect_ldap(ldap_to)
    ldap_from_connect = connect_ldap(ldap_from)
    user_list = get_group_member(ldap_to_connect, group_name, ldap_to['group_dn'])
    count = 0
    for user in user_list:
        user_password = get_password(ldap_from_connect, user, ldap_from['user_dn'])
        if user_password:
            if change_password(ldap_to_connect, user, ldap_to['user_dn'], user_password):
                count += 1
                print "changed: ", user
    ldap_to_connect.unbind_s()
    ldap_from_connect.unbind_s()
    return {'success': count, 'total': len(user_list)}


if __name__ == '__main__':
    # 同步jenkins群组
    result = sync("oa-jenkins", PORTAL_LDAP, DEVOPS_LDAP)
    print(result)
    # 同步gitlab群组
    result = sync("oa-gitlab", PORTAL_LDAP, DEVOPS_LDAP)
    print(result)
    # 同步组成员
    #user_list = []
    #result = add_group_member(DEVOPS_LDAP, 'oa-jenkins', DEVOPS_LDAP['group_dn'], DEVOPS_LDAP['user_dn'], user_list)
    print(result)

12-26 05:19