Files
ArchiveCostWebapp/logic/scripts/ad_lookup.py
T

129 lines
5.9 KiB
Python

import os
import sys
import json
from ldap3 import Server, Connection, ALL
# --- Konfiguration ---
AD_SERVER = 'd.psi.ch'
AD_USER = os.environ.get('AD_USER')
AD_PASSWORD = os.environ.get('AD_PASSWORD')
AD_SEARCH_BASE = 'DC=d,DC=psi,DC=ch'
#FILE_PATH = "/data/archivegroup_information.json"
FILE_PATH = os.environ.get('GROUPINFO_JSON_LNK_NAME_WITH_PATH')
#FILE_PATH = "/data/" + os.environ.get('GROUPINFO_JSON_LNK_NAME')
#FILE_PATH = "../../" + os.environ.get('GROUPINFO_JSON_LNK_NAME')
def lookup_ad():
try:
# 1. Datenbasis aus lokaler JSON-Datei laden
if not os.path.exists(FILE_PATH):
print(f"ERROR: Datei {FILE_PATH} nicht gefunden!", file=sys.stderr, flush=True)
return
with open(FILE_PATH, 'r') as f:
items = json.load(f)
print(f"INFO: {len(items)} Einträge geladen.", file=sys.stderr, flush=True)
# 2. AD-Verbindung initialisieren (SSL, Port 636)
server = Server(AD_SERVER, port=636, use_ssl=True, get_info=ALL, connect_timeout=10)
with Connection(server, user=AD_USER, password=AD_PASSWORD, auto_bind=True) as conn:
# Interner Cache zur Speicherung der p-Gruppen-Auflösungen
p_group_resolution_cache = {}
count = 0
for item in items:
count += 1
group_name = item.get('ownerGroup', '')
# --- Fall A: Direkte a-Gruppen ---
if group_name.startswith('a-'):
search_filter = f'(&(objectClass=group)(cn={group_name}))'
conn.search(search_base=AD_SEARCH_BASE,
search_filter=search_filter,
attributes=['department'])
if conn.entries:
res = str(conn.entries[0].department) if 'department' in conn.entries[0] else "no-dept"
item['department'] = res
else:
item['department'] = "not_found"
# --- Fall B: Zweistufige p-Gruppen ---
elif group_name.startswith('p') and group_name[1:2].isdigit():
if group_name in p_group_resolution_cache:
target_group = p_group_resolution_cache[group_name]
else:
# Stufe 1: memberOf-Attribut des p-Objekts abfragen
p_filter = f'(cn={group_name})'
conn.search(search_base=AD_SEARCH_BASE,
search_filter=p_filter,
attributes=['memberOf'])
target_group = "not_found"
if conn.entries and 'memberOf' in conn.entries[0] and conn.entries[0].memberOf:
# Iterate over all memberOf entries
selected_dn = None
for dn in conn.entries[0].memberOf:
dn_str = str(dn)
# Look for the specific service folder in the DN
if 'OU=Beamlines,OU=Experiment,OU=IT' in dn_str:
selected_dn = dn_str
break
if selected_dn is None:
# Fallback to the first one if the specific folder wasn't found
selected_dn = str(conn.entries[0].memberOf[0])
# Zielgruppe (CN) aus dem Distinguished Name extrahieren
try:
target_group = selected_dn.split(',')[0].split('=')[1]
p_group_resolution_cache[group_name] = target_group
except IndexError:
print(f"WARN: Format von DN '{selected_dn}' unerwartet.", file=sys.stderr, flush=True)
target_group = "format_error"
item['target_group'] = target_group
# Stufe 2: Department anhand der ermittelten target_group bestimmen
search_filter = f'(&(objectClass=group)(cn={target_group}))'
conn.search(search_base=AD_SEARCH_BASE,
search_filter=search_filter,
attributes=['department'])
if conn.entries:
res = str(conn.entries[0].department) if 'department' in conn.entries[0] else "no-dept"
item['department'] = res
else:
item['department'] = "not_found"
# --- Fall C: Abweichende Schemata ---
else:
print(f"WARN: Unbekanntes Gruppen-Schema: {group_name}", file=sys.stderr)
item['department'] = "unknown_schema"
continue
# Fortschritt alle 500 Einträge im stderr protokollieren
if count % 500 == 0:
print(f"Fortschritt: {count}/{len(items)}...", file=sys.stderr, flush=True)
# 3. Finales Ergebnis als JSON-String an stdout ausgeben
# print(json.dumps(items))
# Print all not known groups
for item in items:
# print(f"group: {item['ownerGroup']} -> {item['department']} -> type: {type(item['department'])}")
if item['department'] == "[]":
if 'target_group' in item.keys():
print(f"LEER -> {item['ownerGroup']} -> {item['target_group']}")
else:
print(f"LEER -> {item['ownerGroup']} has no target_group")
except Exception as e:
print(f"ERROR: {str(e)}", file=sys.stderr, flush=True)
# if 'items' in locals():
# print(json.dumps(items))
if __name__ == "__main__":
lookup_ad()