65 lines
1.5 KiB
Python
65 lines
1.5 KiB
Python
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
|
|
|
|
|
|
|