1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- """ This is the LDAP component of PyPubSub """
- import ldap
- import asyncio
- class LDAPConnection:
- def __init__(self, yml):
- self.uri = yml.get('uri')
- assert isinstance(self.uri, str), "LDAP URI must be a string."
- self.user = yml.get('user_dn')
- assert isinstance(self.user, str) or self.user is None, "LDAP user DN must be a string or absent."
- self.base = yml.get('base_scope')
- assert isinstance(self.base, str), "LDAP Base scope must be a string"
- self.patterns = yml.get('membership_patterns')
- assert isinstance(self.patterns, list), "LDAP membership patterns must be a list of pattern strings"
- self.acl = yml.get('acl')
- assert isinstance(self.acl, dict), "LDAP ACL must be a dictionary (hash) of ACLs"
- assert ldap.initialize(self.uri)
- print("==== LDAP configuration looks kosher, enabling LDAP authentication as fallback ====")
- async def get_groups(self, user, password):
- """Async fetching of groups an LDAP user belongs to"""
- bind_dn = self.user % user
- try:
- client = ldap.initialize(self.uri)
- client.set_option(ldap.OPT_REFERRALS, 0)
- client.set_option(ldap.OPT_TIMEOUT, 0)
- rv = client.simple_bind(bind_dn, password)
- while True:
- res = client.result(rv, timeout=0)
- if res and res != (None, None):
- break
- await asyncio.sleep(0.25)
- groups = []
- for role in self.patterns:
- rv = client.search(self.base, ldap.SCOPE_SUBTREE, role % user, ['dn'])
- while True:
- res = client.result(rv, all=0, timeout=0)
- if res:
- if res == (None, None):
- await asyncio.sleep(0.25)
- else:
- if not res[1]:
- break
- for tuples in res[1]:
- groups.append(tuples[0])
- else:
- break
- return groups
- except Exception as e:
- print(f"LDAP Exception for user {user}: {e}")
- return []
|