import re from ldap3 import BASE from .krbldap import Konnection ATTRIBUTE_MAP = { "cn": "username", "displayName": "display name", "givenName": "first name", # "mail": "email", # "sn": "last name" } ATTRIBUTES = [*ATTRIBUTE_MAP, "memberOf"] COMMON_DN = "OU=users,OU=psi,DC=d,DC=psi,DC=ch" PGROUP_PATTERN = re.compile(r"CN=(p\d{5}),") SERVERS = [f"dc{i:02}.d.psi.ch" for i in range(3)] def get_data(username, password): with Konnection(SERVERS, username, password) as conn: conn.search( make_search_base(username), search_filter="(objectClass=*)", search_scope=BASE, attributes=ATTRIBUTES ) entries = conn.entries n_entries = len(entries) if n_entries != 1: raise RuntimeError(f"received ambiguous result ({n_entries} entries)") entry = entries[0] res = repack(entry) res_username = res["username"] if res_username != username: raise RuntimeError(f"username mismatch: {res_username} != {username}") return res def make_search_base(cn): res = [f"CN={cn}"] if cn.startswith("ext-"): res.append("OU=external") elif cn.startswith("gac-"): res.append("OU=nonpersons") res.append(COMMON_DN) return ",".join(res) def repack(entry): attrs = entry.entry_attributes_as_dict res = {ATTRIBUTE_MAP[old]: item[0] for old, item in attrs.items() if old in ATTRIBUTE_MAP if item} res["pgroups"] = sorted(m.group(1) for i in attrs["memberOf"] if (m := PGROUP_PATTERN.search(i))) return res