servers/roles/proxmox/templates/sync-ldap.py.j2
Timotej Lazar 25bcddede1 Factor frr role from debian, ceph and proxmox
Consolidate base system and networking setup into debian role and BGP
configuration into frr role. Add facts role to collect data from NetBox
once to avoid many slow lookups. Also many other tweaks and cleanups.
2024-05-19 14:21:25 +02:00

58 lines
2.1 KiB
Django/Jinja

#!/usr/bin/python3
import collections
import os
import re
import ldap3
{% set password = lookup('passwordstore', "cluster/"+cluster.name, returnall=true) | from_yaml %}
realm = '{{ hostvars[inventory_hostname]["sync-ldap"] }}'
ldap_host = '{{ domain }}'
ldap_user = '{{ password.ldap_user }}'
ldap_pass = '{{ password.ldap_pass }}'
ldap_base = '{{ domain | split(".") | map("regex_replace", "^", "dc=") | join(",") }}'
# build LDAP query for users
filters = [
'(objectClass=user)', # only users
'(objectCategory=person)', # that are people
'(schacHomeOrganization=*)', # presumably
'(!(userAccountControl:1.2.840.113556.1.4.803:=2))' # with enabled accounts
]
# run query
server = ldap3.Server(ldap_host, use_ssl=True)
ldap = ldap3.Connection(server, ldap_user, ldap_pass, auto_bind=True)
ldap.search(ldap_base,
f'(&{"".join(filters)})', # conjuction (&(…)(…)(…)) of queries
attributes=['userPrincipalName', 'givenName', 'sn', 'mail', 'memberOf'])
# build user and group dicts
all_users = {}
all_groups = collections.defaultdict(set)
for e in ldap.entries:
user = f'{e.userPrincipalName.value}@{realm}'
all_users[user] = { k: e[k].value for k in e.entry_attributes }
for group in e.memberOf:
if m := re.match(r'^CN=([^,]*)', group.replace('\\,', '-')):
group = re.sub(r'[^A-Za-z0-9_.-]', '-', m[1])
all_groups[group].add(user)
with open('/etc/pve/user.cfg.new', 'w') as f:
# user:{username}@{realm}:1:0:{name}:{surname}:{mail}:AD sync::
for user, info in sorted(all_users.items()):
print(f'user:{user}:1:0:{info["givenName"]}:{info["sn"]}:{info["mail"]}:AD sync::', file=f)
# group:{name}:{users}:AD sync:
print(f'group:ALL:{",".join(sorted(all_users))}:AD sync:', file=f)
for group, users in all_groups.items():
print(f'group:{group}:{",".join(sorted(users))}:AD sync:', file=f)
# keep everything not added by us
for line in open('/etc/pve/user.cfg'):
if not re.match('^(user|group):.*:AD sync:', line):
print(line, end='', file=f)
os.rename('/etc/pve/user.cfg.new', '/etc/pve/user.cfg')