py.lib
py.lib/db/ldap.py
+ Работа с LDAP
| awgur@13 | 1 # coding: utf-8 |
| awgur@13 | 2 |
| awgur@13 | 3 from ldap3 import Server, Connection, SIMPLE, SUBTREE |
| awgur@13 | 4 |
| awgur@13 | 5 LDAP_PAGE=1000 |
| awgur@13 | 6 |
| awgur@13 | 7 class LdapError(Exception): pass |
| awgur@13 | 8 |
| awgur@13 | 9 class LdapRes(): |
| awgur@13 | 10 def __init__(self, dn, attrib): |
| awgur@13 | 11 self.dn = dn |
| awgur@13 | 12 self.attr = attrib |
| awgur@13 | 13 |
| awgur@13 | 14 def __getitem__(self, item): |
| awgur@13 | 15 return self.attr[item] |
| awgur@13 | 16 |
| awgur@13 | 17 def __iter__(self): |
| awgur@13 | 18 return iter(self.attr) |
| awgur@13 | 19 |
| awgur@13 | 20 def __repr__(self): |
| awgur@13 | 21 return '<LdapRes: dn: %s>' % self.dn |
| awgur@13 | 22 |
| awgur@13 | 23 @classmethod |
| awgur@13 | 24 def fromLdapQuery(cls, q): |
| awgur@13 | 25 if not isinstance(q, dict): |
| awgur@13 | 26 raise LdapError('LdapRes: Parsing Error, not ldap response item') |
| awgur@13 | 27 if not (('dn' in q) and ('attributes' in q)): |
| awgur@13 | 28 raise LdapError('LdapRes: Parsing Error, format mismatch') |
| awgur@13 | 29 |
| awgur@13 | 30 return cls(q['dn'], q['attributes']) |
| awgur@13 | 31 |
| awgur@13 | 32 class Ldap(): |
| awgur@13 | 33 def __init__(self, host, user, passwd, timeout=60, queryTimeout=300, **kwa): |
| awgur@13 | 34 if 'baseDN' in kwa: |
| awgur@13 | 35 self._baseDN = kwa['baseDN'] |
| awgur@13 | 36 del kwa['baseDN'] |
| awgur@13 | 37 else: |
| awgur@13 | 38 self._baseDN = None |
| awgur@13 | 39 ldapSrv = Server(host, connect_timeout=timeout, **kwa) |
| awgur@13 | 40 self._conn = self._makeConnFabric(ldapSrv, authentication=SIMPLE, |
| awgur@13 | 41 user=user, password=passwd, |
| awgur@13 | 42 check_names=True, lazy=True, |
| awgur@13 | 43 auto_referrals=False, raise_exceptions=True, auto_range=True |
| awgur@13 | 44 ) |
| awgur@13 | 45 self.queryTimeout = queryTimeout |
| awgur@13 | 46 |
| awgur@13 | 47 def __call__(self, filter, attrib, queryTimeout=None, baseDN = None): |
| awgur@13 | 48 if baseDN is None: |
| awgur@13 | 49 if self._baseDN is None: |
| awgur@13 | 50 raise LdapError('No base dn on query execution') |
| awgur@13 | 51 baseDN = self._baseDN |
| awgur@13 | 52 if queryTimeout is None: |
| awgur@13 | 53 queryTimeout = self.queryTimeout |
| awgur@13 | 54 try: |
| awgur@13 | 55 conn = self._conn() |
| awgur@13 | 56 with conn: |
| awgur@13 | 57 conn.open() |
| awgur@13 | 58 conn.bind() |
| awgur@13 | 59 |
| awgur@13 | 60 res = conn.extend.standard.paged_search(baseDN, |
| awgur@13 | 61 filter, attributes=attrib, paged_size=LDAP_PAGE, generator=False, |
| awgur@13 | 62 search_scope=SUBTREE, time_limit=queryTimeout |
| awgur@13 | 63 ) |
| awgur@13 | 64 |
| awgur@13 | 65 for i in res: |
| awgur@13 | 66 if i['type'] == 'searchResEntry': |
| awgur@13 | 67 yield LdapRes.fromLdapQuery(i) |
| awgur@13 | 68 |
| awgur@13 | 69 except Exception as e: |
| awgur@13 | 70 raise LdapError("Error on get data (%s): %s" % (type(e), str(e)), *e.args[1:]) |
| awgur@13 | 71 |
| awgur@13 | 72 def getList(self, *a, **kwa): |
| awgur@13 | 73 return [ i for i in self(*a, **kwa) ] |
| awgur@13 | 74 |
| awgur@13 | 75 @staticmethod |
| awgur@13 | 76 def _makeConnFabric(*a, **kwa): |
| awgur@13 | 77 def _func(): |
| awgur@13 | 78 return Connection(*a, **kwa) |
| awgur@13 | 79 |
| awgur@13 | 80 return _func |
| awgur@13 | 81 |
| awgur@13 | 82 |
| awgur@13 | 83 |
| awgur@13 | 84 |