py.lib
2022-08-19
Parent:1668cc57225b
py.lib/ldap_utils/ldap_util.py
. Исправление ошибок и рефакторинг
| awgur@3 | 1 # coding: utf-8 |
| awgur@3 | 2 import ldap |
| awgur@3 | 3 |
| awgur@3 | 4 # =========================================================== |
| awgur@23 | 5 # Статус завершения операций |
| awgur@3 | 6 STATUS_OK = 0 # Всё ОК. |
| awgur@3 | 7 STATUS_BADAUTH = 1 # Не верные пользователь или пароль. |
| awgur@3 | 8 STATUS_SERVERDOWN = 2 # Сервер не доступен. |
| awgur@3 | 9 STATUS_SERVERERROR = 3 # Ошибка при взаимодействии с сервером. |
| awgur@3 | 10 |
| awgur@23 | 11 |
| awgur@23 | 12 class LdapError(Exception): |
| awgur@23 | 13 pass |
| awgur@23 | 14 |
| awgur@3 | 15 |
| awgur@3 | 16 class LdapAuth(object): |
| awgur@23 | 17 def __init__(self, server, user_prefix='CORP\\', base_dn='DC=example,DC=net', attr=None): |
| awgur@23 | 18 self.server = server |
| awgur@23 | 19 self.prefix = user_prefix |
| awgur@23 | 20 self.status = '' |
| awgur@23 | 21 self.baseDN = base_dn |
| awgur@23 | 22 self.status_code = 0 |
| awgur@23 | 23 self.groups = None |
| awgur@23 | 24 self.attr = None |
| awgur@23 | 25 self._needAttr = [i for i in map(str, attr)] if attr is not None else [] |
| awgur@23 | 26 |
| awgur@23 | 27 def __call__(self, user, passwd): |
| awgur@23 | 28 conn = None |
| awgur@23 | 29 try: |
| awgur@23 | 30 conn = ldap.initialize(self.server) |
| awgur@23 | 31 conn.set_option(ldap.OPT_REFERRALS, 0) |
| awgur@23 | 32 conn.simple_bind_s(self.prefix + user, passwd) |
| awgur@23 | 33 |
| awgur@23 | 34 except ldap.INVALID_CREDENTIALS: |
| awgur@23 | 35 if conn is not None: |
| awgur@23 | 36 conn.unbind() |
| awgur@23 | 37 |
| awgur@23 | 38 self.status = 'Invalid credentials' |
| awgur@23 | 39 self.status_code = STATUS_BADAUTH |
| awgur@23 | 40 return False |
| awgur@23 | 41 |
| awgur@23 | 42 except ldap.SERVER_DOWN: |
| awgur@23 | 43 self.status = 'Server is down' |
| awgur@23 | 44 self.status_code = STATUS_SERVERDOWN |
| awgur@23 | 45 return False |
| awgur@23 | 46 |
| awgur@23 | 47 self.groups = [] |
| awgur@23 | 48 try: |
| awgur@23 | 49 ldap_data = conn.search_s(self.baseDN, ldap.SCOPE_SUBTREE, f'(cn={user})', |
| awgur@23 | 50 ['memberOf'] + self._needAttr)[0][1] |
| awgur@23 | 51 |
| awgur@23 | 52 for i in ldap_data['memberOf']: |
| awgur@23 | 53 self.groups.append(i.split(',')[0].split('=')[1].decode('utf-8')) |
| awgur@23 | 54 |
| awgur@23 | 55 del ldap_data['memberOf'] |
| awgur@23 | 56 self.attr = ldap_data |
| awgur@3 | 57 |
| awgur@23 | 58 except KeyError: |
| awgur@23 | 59 self.status = 'User object from LDAP is wrong, it can be anonymous logon' |
| awgur@23 | 60 self.status_code = STATUS_SERVERERROR |
| awgur@23 | 61 return False |
| awgur@23 | 62 |
| awgur@23 | 63 finally: |
| awgur@23 | 64 conn.unbind() |
| awgur@23 | 65 |
| awgur@23 | 66 return True |
| awgur@23 | 67 |
| awgur@23 | 68 def __getitem__(self, key): |
| awgur@23 | 69 return self.attr[key] |
| awgur@23 | 70 |
| awgur@23 | 71 def member_of(self, group): |
| awgur@23 | 72 """Проверка на присутствие у пользователя некоторой группы |
| awgur@23 | 73 """ |
| awgur@23 | 74 if self.groups is None: |
| awgur@23 | 75 raise LdapError('Request membership before auth call') |
| awgur@23 | 76 |
| awgur@23 | 77 if not isinstance(group, unicode): |
| awgur@23 | 78 if isinstance(group, str): |
| awgur@23 | 79 group = group.decode('utf-8') |
| awgur@23 | 80 else: |
| awgur@23 | 81 group = str(group).decode('utf-8') |
| awgur@23 | 82 |
| awgur@23 | 83 if group in self.groups: |
| awgur@23 | 84 return True |
| awgur@23 | 85 else: |
| awgur@23 | 86 return False |
| awgur@23 | 87 |
| awgur@23 | 88 def __contains__(self, group): |
| awgur@23 | 89 return self.member_of(group) |
| awgur@23 | 90 |
| awgur@23 | 91 def member_of_groups(self, groups): |
| awgur@23 | 92 if not len(groups) > 0: |
| awgur@23 | 93 return False |
| awgur@23 | 94 |
| awgur@23 | 95 for group in groups: |
| awgur@23 | 96 if group not in self: |
| awgur@23 | 97 return False |
| awgur@23 | 98 |
| awgur@23 | 99 return True |