36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192 | def lookup_ad():
- """Führt den kompletten Prozess zur Anreicherung der Daten mit AD-Informationen aus."""
- try:
- # --- 1. Konfiguration und Daten prüfen und einlesen ---
-
- # Umgebungsvariablen laden und prüfen
- config = {
- 'AD_SERVER': os.environ.get('AD_SERVER'),
- 'AD_USER': os.environ.get('AD_USER'),
- 'AD_PASSWORD': os.environ.get('AD_PASSWORD'),
- 'AD_SEARCH_BASE': os.environ.get('AD_SEARCH_BASE'),
- 'FILE_PATH': os.environ.get('GROUPINFO_JSON_LNK_NAME_WITH_PATH')
- }
- file_path_non_specified_groups = os.environ.get('NON_SPECIFIED_GROUPS')
-
- for key, value in config.items():
- if value is None:
- print(f"ERROR: Environment variable {key} is not set.", file=sys.stderr, flush=True)
- return
-
- # Sicheres Casten zu Strings für den Type-Checker
- ad_server = str(config['AD_SERVER'])
- ad_user = str(config['AD_USER'])
- ad_password = str(config['AD_PASSWORD'])
- ad_search_base = str(config['AD_SEARCH_BASE'])
- file_path = str(config['FILE_PATH'])
-
- # JSON-Datei als Haupt-Datenquelle laden
- if not os.path.exists(file_path):
- print(f"ERROR: File {file_path} not found!", file=sys.stderr, flush=True)
- return
-
- with open(file_path, 'r') as f:
- items = json.load(f)
- print(f"INFO: {len(items)} entries loaded from JSON.", file=sys.stderr, flush=True)
-
- # Optionale CSV-Datei mit manuellen Zuweisungen laden
- manual_departments = {}
- if file_path_non_specified_groups and os.path.exists(file_path_non_specified_groups):
- with open(file_path_non_specified_groups, 'r', newline='') as f:
- reader = csv.DictReader(f)
- for row in reader:
- group = row.get('group', '').strip()
- department = row.get('paymentunit', '').strip()
- info = row.get('info', '').strip()
-
- # Nur Gruppen hinzufügen, die nicht explizit als "nicht im AD" markiert sind
- if group and department and info != 'NOT_IN_AD':
- manual_departments[group] = department
-
- print(f"INFO: Loaded {len(manual_departments)} manual group definitions from CSV.",
- file=sys.stderr, flush=True)
- else:
- print("INFO: No valid manual groups CSV file provided or found.", file=sys.stderr, flush=True)
-
- # --- 2. AD-Verarbeitung ---
-
- # AD-Verbindung via SSL (Port 636) initialisieren
- 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:
- # Cache für die Zuordnung von Beamline zu Department (Performance-Optimierung)
- beamline_department_cache = {}
- count = 0
-
- for item in items:
- count += 1
- group_name = item.get('ownerGroup', '')
-
- # Priorität 1: Manuelle Zuweisung aus CSV
- if group_name in manual_departments:
- item['department'] = manual_departments[group_name]
- continue
-
- # Priorität 2: 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 and 'department' in conn.entries[0]:
- item['department'] = str(conn.entries[0].department)
- else:
- item['department'] = "not_found"
-
- # Priorität 3: Zweistufige p-Gruppen
- elif group_name.startswith('p') and group_name[1:2].isdigit():
- beamline = "not_found"
-
- # Stufe 1: Zugehörige Beamline-Gruppe via 'memberOf' ermitteln
- p_filter = f'(cn={group_name})'
- conn.search(
- search_base=ad_search_base,
- search_filter=p_filter,
- attributes=['memberOf']
- )
-
- if conn.entries and 'memberOf' in conn.entries[0] and conn.entries[0].memberOf:
- dn_generator = (str(dn) for dn in conn.entries[0].memberOf
- if 'OU=Beamlines,OU=Experiment,OU=IT' in str(dn))
- selected_dn = next(dn_generator, None)
-
- if selected_dn is None:
- selected_dn = str(conn.entries[0].memberOf[0])
-
- try:
- beamline = selected_dn.split(',')[0].split('=')[1]
- except IndexError:
- msg = f"WARN: Format von DN '{selected_dn}' unerwartet."
- print(msg, file=sys.stderr, flush=True)
- beamline = "format_error"
-
- item['beamline'] = beamline
-
- # Stufe 2: Department für die Beamline ermitteln (mit Caching)
- if beamline in beamline_department_cache:
- item['department'] = beamline_department_cache[beamline]
- else:
- search_filter = f'(&(objectClass=group)(cn={beamline}))'
- conn.search(
- search_base=ad_search_base,
- search_filter=search_filter,
- attributes=['department']
- )
- if conn.entries and 'department' in conn.entries[0]:
- res = str(conn.entries[0].department)
- else:
- res = "not_found"
- beamline_department_cache[beamline] = res
- item['department'] = res
-
- # Fallback: Unbekannte Gruppenschemata
- else:
- msg = f"WARNING: Unbekanntes Gruppen-Schema: {group_name}"
- print(msg, file=sys.stderr, flush=True)
- item['department'] = "unknown_schema"
-
- if count % 500 == 0:
- print(f"INFO: progress {count}/{len(items)}...", file=sys.stderr, flush=True)
-
- # --- 3. Ausgabe ---
-
- # Finales Ergebnis als JSON auf stdout ausgeben
- print(json.dumps(items))
-
- # Zusätzliche Debug-Ausgabe auf stderr für Gruppen ohne valides Department
- for item in items:
- if item.get('department') in ("[]", "not_found", "no-dept"):
- msg = f"WARNING: Kein Department für {item['ownerGroup']}"
- if 'beamline' in item:
- msg += f" (Beamline: {item['beamline']})"
- msg += " gefunden."
- print(msg, file=sys.stderr, flush=True)
-
- except Exception as e:
- print(f"ERROR: {str(e)}", file=sys.stderr, flush=True)
-
|