py.lib
17:10227cc154fa
Go to Latest
py.lib/ldap_utils/ldap_passwd_changer.py
* Исправление ряда тупых ошибок в миграторе
3 Смена пароля на пользователя в AD посредством Python
7 from ldap3 import Server, Connection, SIMPLE, SUBTREE
8 from ldap3.core.exceptions import LDAPException
9 from secrets import token_urlsafe
12 class LdapError(Exception):
15 _buf = ' '.join(str(e).split()) # всё в одну строку с одним пробелом
17 return "%s(%s)" % (type(e).__name__, _buf)
19 class LdapServerError(LdapError): pass
20 class LdapPassGenError(LdapError): pass
21 class LdapNotFound(LdapError): pass
24 class LdapPasswdChanger(object):
25 def __init__(self, ldap_server_uri, ldap_user, ldap_passwd, ldap_baseDN, ldap_timeout=120, ldap_reconnect=5, passwd_len=25):
26 self.ldap_server_uri = ldap_server_uri # URI к серверу: ldaps://server_name:port_number
27 self.ldap_user = ldap_user # Пользователь, имеющий право сброса паролей
28 self.ldap_passwd = ldap_passwd # Пароль к тому пользователю
29 self.ldap_baseDN = ldap_baseDN
30 self.ldap_timeout = ldap_timeout # Таймаут операций с сервером
31 self.passwd_len = passwd_len # Желаемая длинна пароля
32 self.ldap_reconnect = ldap_reconnect # Количество попыток переподключения к серверу
34 # Заготовка под пароли
35 self._set_punct = set(string.punctuation)
36 self._set_uper = set(string.ascii_uppercase)
37 self._set_lower = set(string.ascii_lowercase)
42 res = token_urlsafe(self.passwd_len)
44 if ((_res_set & self._set_punct)
45 and (_res_set & self._set_uper)
46 and (_res_set & self._set_lower)
52 raise LdapPassGenError('Не удалось сгенерировать пароль')
55 def changePass(self, login):
56 _reconnects = self.ldap_reconnect
57 if _reconnects is None or _reconnects < 1:
64 ldapSrv = Server(self.ldap_server_uri, connect_timeout=self.ldap_timeout)
65 ldapConn = Connection(ldapSrv, authentication=SIMPLE,
66 user=self.ldap_user, password=self.ldap_passwd,
68 auto_referrals=False, raise_exceptions=True, auto_range=True,
71 if not ldapConn.bind():
75 except LDAPException as e:
76 if not _reconnects > 0:
77 raise LdapServerError('Ошибка подключения к серверу: %s' % LdapServerError.errFmt(e))
79 filter = '(sAMAccountName=%s)' % login
81 if not ldapConn.search(self.ldap_baseDN, filter):
82 raise LdapServerError('Сервер вернул статус ощибки: %(desc)s(%(code)s) - %(msg)s' % {
83 'desc': ldapConn.result['description'],
84 'code': ldapConn.result['result'],
85 'msg': ldapConn.result['message'],
87 except LDAPException as e:
88 raise LdapServerError('Ошибка при поиска УЗ в ldap: %s' % LdapServerError.errFmt(e))
90 if not len(ldapConn.entries) > 0:
91 raise LdapNotFound('Не найдена учётная запись: %s' % login)
92 elif len(ldapConn.entries) != 1:
93 raise LdapError('Наёдено более одной УЗ по заданному имени %s: %s - %s' %(
95 len(ldapConn.entries),
96 '; '.join([i.entry_dn for i in ldapConn.entries[:10]])
99 login_dn = ldapConn.entries[0].entry_dn
100 new_passwd = self.getPasswd()
102 ldapConn.extend.microsoft.modify_password(login_dn, new_password=new_passwd, old_password=None)
103 except LDAPException as e:
104 raise LdapServerError('Ошибка при смене пароля на УЗ: %s' % LdapServerError.errFmt(e))