No description
  • C# 96.6%
  • PowerShell 3.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Lars Oste 87ba30c2e9
All checks were successful
CI / build-test (push) Successful in 1m29s
Die Forge heisst git.flexfamily.de
Lars am 28.10.2026: "ab jetzt git.flexfamily.de gehoeren die repos".
Grund, und das ist der eigentliche Punkt: **git.flexfamily.cloud ist in
Lars' Firmennetz gesperrt**, .de nicht. Beide Namen zeigen auf dieselbe
Instanz und haben ein Zertifikat -- vom Arbeitsplatz aus waere die Forge
unter dem alten Namen aber nicht erreichbar.

Umgestellt sind damit: ROOT_URL, DOMAIN und SSH_DOMAIN der Instanz, alle
Git-Remotes, die Workflows und jedes Programm, das dort etwas abholt.

Ohne den Grund wirkt das wie Geschmack, und der naechste, der eine
Adresse schreibt, nimmt wieder die falsche. Er steht im allgemeinen Skill
und in RUNNER.md.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-28 14:30:37 +01:00
.forgejo/workflows Die Forge heisst git.flexfamily.de 2026-10-28 14:30:37 +01:00
.github feat: Zugangsgruppe ins Binary kompilieren statt in eine Datei daneben 2026-09-01 11:26:04 +02:00
.vscode feat: LDAPeek — AD-Konten und Gruppenmitgliedschaften nachschlagen 2026-08-25 15:55:48 +02:00
docs feat: Gruppenliste als Baum, nach Verzeichnis oder flach 2026-09-03 17:32:49 +02:00
LDAPeek feat: Gruppenliste als Baum, nach Verzeichnis oder flach 2026-09-03 17:32:49 +02:00
LDAPeek.Tests test: vier Windows-Tests ueberspringen statt scheitern lassen 2026-10-28 06:54:12 +01:00
scripts feat: LDAPeek — AD-Konten und Gruppenmitgliedschaften nachschlagen 2026-08-25 15:55:48 +02:00
.editorconfig feat: LDAPeek — AD-Konten und Gruppenmitgliedschaften nachschlagen 2026-08-25 15:55:48 +02:00
.gitignore feat: LDAPeek — AD-Konten und Gruppenmitgliedschaften nachschlagen 2026-08-25 15:55:48 +02:00
CLAUDE.md feat: Gruppenliste als Baum, nach Verzeichnis oder flach 2026-09-03 17:32:49 +02:00
Directory.Build.props feat: LDAPeek — AD-Konten und Gruppenmitgliedschaften nachschlagen 2026-08-25 15:55:48 +02:00
Directory.Packages.props build: Pakete auf den aktuellen Stand 2026-08-26 00:15:40 +02:00
global.json feat: LDAPeek — AD-Konten und Gruppenmitgliedschaften nachschlagen 2026-08-25 15:55:48 +02:00
ldapeek.policy.example.json feat: Zugangsgruppe ins Binary kompilieren statt in eine Datei daneben 2026-09-01 11:26:04 +02:00
LDAPeek.slnx feat: LDAPeek — AD-Konten und Gruppenmitgliedschaften nachschlagen 2026-08-25 15:55:48 +02:00
LICENSE chore: Copyright auf Lars Oste 2026-10-05 10:41:49 +02:00
README.md docs: Bildschirmfotos in die README, reproduzierbar aus dem Programm erzeugt 2026-09-01 12:10:32 +02:00

LDAPeek

CI Release

Active-Directory-Konten nachschlagen: Stammdaten, Kontozustand und vor allem die Gruppenmitgliedschaften — inklusive der über Verschachtelung geerbten.

LDAPeek ist ein rein lesendes Werkzeug. Es schreibt nichts ins Verzeichnis, und es gibt keinen Codepfad, der das könnte.

LDAPeek

Alle Bilder in dieser Datei zeigen erfundene Daten aus einer Beispieldomäne. Sie entstehen reproduzierbar aus dem Programm selbst — siehe Bilder neu erzeugen.

Wofür

Die Frage „warum hat die Kollegin Zugriff auf X?" lässt sich mit der flachen Gruppenliste aus Active Directory-Benutzer und -Computer nicht beantworten: dort steht nur, was dem Konto direkt zugewiesen wurde. In einer gewachsenen Domäne ist das die Minderheit. Ein Beispiel aus dem Alltag: 33 direkte Mitgliedschaften, aber 132 effektive — 99 davon geerbt.

LDAPeek zeigt beides nebeneinander und markiert bei jeder Gruppe, wie das Konto hineingekommen ist:

Kennzeichnung Bedeutung
Primärgruppe Aus primaryGroupID — typisch „Domänen-Benutzer". Steht in keinem memberOf und fehlt deshalb in vielen selbstgebauten Auswertungen.
direkt Steht im memberOf des Kontos.
verschachtelt Geerbt über eine andere Gruppe. Der Domain Controller löst das serverseitig auf.

Features

  • Suche über mehrere Attribute — Anmeldename, Anzeigename, Vor- und Nachname, E-Mail, Benutzerprinzipalname; Personalnummern werden exakt gesucht. Genau ein Treffer wird direkt geöffnet.
  • Vollständige Stammdaten — Organisation, Erreichbarkeit, Anschrift, Verzeichnisangaben (DN, SID, Objekt-GUID), Profilpfade und das im Verzeichnis hinterlegte Foto.
  • Kontozustand im Klartext — aktiv/deaktiviert/gesperrt/abgelaufen, dazu die Merkmale aus userAccountControl („Passwort läuft nie ab", „Smartcard erforderlich", …). Zeitangaben immer mit Abstand zu heute: 14.03.2026 08:12 (vor 12 Tagen).
  • Gruppen filtern — Volltextfilter über Name, Anmeldename und Beschreibung, optional nur Sicherheitsgruppen (Verteilergruppen tragen keine Berechtigungen).
  • Weitergeben — Gruppenliste als CSV in die Zwischenablage oder als Datei, oder eine vollständige Textzusammenfassung des Kontos für ein Ticket.
  • Update über den Netzwerkordner — kein Internetzugang nötig.
  • Optionale Gruppenbeschränkung — der Start lässt sich an eine AD-Gruppenmitgliedschaft koppeln.

Installation

Es gibt keine Installation. Das ZIP von der Releases-Seite oder aus \\samba01\542$\5424_IT-Basis-Dienste\LDAPeek entpacken und LDAPeek.exe starten. Das Paket ist self-contained — .NET muss nicht installiert sein.

Voraussetzungen: Windows, Rechner an der Domäne angemeldet (oder VPN). Es genügen die normalen Leserechte, die jedes Domänenkonto im Verzeichnis hat.

Bedienung

  1. Links einen Suchbegriff eintippen und Suchen (oder Eingabetaste). Ab zwei Zeichen; zuletzt gesuchte Begriffe schlägt das Feld selbst vor.
  2. Einen Treffer anklicken. Rechts oben stehen die Stammdaten, darunter die Gruppen.
  3. Die Fuge zwischen Stammdaten und Gruppen lässt sich ziehen — wer vor allem Gruppen prüft, zieht sie nach oben.
Taste Wirkung
Strg+F Cursor ins Suchfeld
F5 Konto und Gruppen neu abfragen
Esc Suchfeld leeren

Minimieren legt LDAPeek in den Infobereich (Tray), Schließen beendet es. Ein zweiter Start holt das laufende Fenster nach vorn, statt ein zweites zu öffnen.

Die Gruppenliste lesen

Jede Zeile trägt zwei Abzeichen: woher die Mitgliedschaft kommt und was die Gruppe ist.

Abzeichen Bedeutung
Primärgruppe (gold) Aus primaryGroupID, typisch „Domänen-Benutzer". Steht in keinem memberOf.
direkt (blau) Dem Konto unmittelbar zugewiesen.
verschachtelt (grau) Über eine andere Gruppe geerbt.
Sicherheit / Verteiler Nur Sicherheitsgruppen tragen Berechtigungen.
Global / Lokal in Domäne / Universell Gültigkeitsbereich.

Verschachtelte Gruppen

Der Schalter Verschachtelte auflösen steuert, ob geerbte Mitgliedschaften mitgeholt werden. Er ist standardmäßig an, weil das die interessante Auskunft ist. Die Abfrage läuft serverseitig (LDAP_MATCHING_RULE_IN_CHAIN) und dauert je nach Verschachtelungstiefe ein paar Sekunden — bei einem Konto mit 132 effektiven Gruppen etwa vier. Wer nur schnell die direkten Zuweisungen sehen will, schaltet ihn aus.

Start auf eine Gruppe beschränken (optional)

LDAPeek kann beim Start prüfen, ob der angemeldete Benutzer in einer bestimmten AD-Gruppe ist. Wer nicht drin ist, bekommt einen Hinweis statt des Fensters.

Die Gruppe wird beim Bauen ins Binary geschrieben — es gibt keine Datei, die man löschen könnte:

dotnet publish LDAPeek/LDAPeek.csproj -c Release -p:RequiredGroup="RG-LDAPeek-Benutzer"

Im Release-Workflow kommt der Wert aus der Repo-Variable LDAPEEK_REQUIRED_GROUP (Settings → Secrets and variables → Actions → Variables). So steht der Gruppenname nicht im Quellcode und lässt sich ohne Commit ändern; ein Gruppenwechsel kostet ein neues Release.

  • Ohne gesetzte Gruppe gibt es keine Einschränkung — der Normalfall für Entwicklung.
  • RequiredGroup nimmt einen Namen (Gruppe, DOMÄNE\Gruppe) oder eine SID. Eine SID ist robuster: sie überlebt eine Umbenennung der Gruppe.
  • Verschachtelte Mitgliedschaften zählen mit.

Eine optionale ldapeek.policy.json neben der EXE kann den Hinweistext anpassen (rein kosmetisch, dafür soll niemand neu bauen müssen) — die Gruppe kann sie nicht ändern. Nur wenn keine Gruppe einkompiliert ist, darf sie auch eine setzen. Vorlage: ldapeek.policy.example.json.

Was die Prüfung leistet — und was nicht

Sie ist kein Sicherheitsmechanismus, und die Daten sind nicht geheim: LDAPeek liest ausschließlich, was jedes Domänenkonto ohnehin lesen darf — die tatsächliche Zugriffskontrolle sind die Leserechte im Verzeichnis.

Der Zweck ist ein anderer und durchaus wirksam: LDAPeek senkt die Einstiegshürde erheblich. Dieselbe Auskunft per Get-ADUser zu holen kann zwar jeder — aber eben nicht jeder kann es. Genau deshalb steht die Gruppe im Binary und nicht in einer Datei daneben: eine Datei zu löschen können auch die, die keine LDAP-Abfrage schreiben können. Wer die Assembly dekompiliert und patcht, kommt an dieselbe Auskunft ohnehin schneller über PowerShell.

Eine Grenze bleibt: Das gilt nur, solange der Nutzer die EXE nicht ersetzen kann. Liegt LDAPeek in einem Ordner, in den er schreiben darf, gehört ihm auch das Binary. Für eine belastbare Regel gehört die Anwendung an einen nur für Administratoren beschreibbaren Ort, etwa C:\Program Files\LDAPeek.

Kein Zugriff

Gerade erst in die Gruppe aufgenommen?

Windows friert die Gruppenmitgliedschaften beim Anmelden im Zugriffstoken ein — eine frische Aufnahme steht dort noch nicht drin. LDAPeek fängt das ab: wird der Zugang anhand des Tokens verweigert, fragt es automatisch noch einmal direkt im Verzeichnis nach (dauert Millisekunden). Erst wenn auch das verneint, erscheint die Abweisung — mit einem „Erneut prüfen"-Knopf für den Fall, dass die Aufnahme gerade eben passiert ist.

Einstellungen

Über das Zahnrad in der Titelleiste. Alles ist optional — ohne eine einzige Einstellung findet LDAPeek die Anmeldedomäne selbst.

Einstellungen

Einstellung Bedeutung
Domäne oder Domain Controller Leer = Anmeldedomäne des angemeldeten Benutzers. Ein konkreter DC ist nur nötig, wenn ein bestimmter geprüft werden soll.
Port / LDAPS Standard 389. Auch ohne LDAPS ist die Sitzung verschlüsselt: der Kerberos-Bind wird signiert und versiegelt.
Such-Basis Leer = ganze Domäne. Eine einzelne OU beschleunigt die Suche spürbar.
Benutzerkonto / Passwort Leer = angemeldetes Windows-Konto. Nur nötig, wenn das Alltagskonto nicht lesen darf. Das Passwort wird per DPAPI an das Windows-Konto gebunden gespeichert, nie im Klartext.
Höchstzahl Treffer Standard 200.
Update-Ordner Netzwerkordner mit den Paketen.

Die Konfiguration liegt unter %LOCALAPPDATA%\LDAPeek\settings.json.

Updates

LDAPeek sieht beim Start im Update-Ordner nach und meldet eine neuere Version als Hinweiszeile. Installiert wird sie über ⓘ → Auf Updates prüfen → Update installieren: LDAPeek kopiert das Paket lokal, entpackt es, tauscht sich selbst aus und startet neu.

Ausrollen ist ein Kopiervorgang: das ZIP unverändert nach \\samba01\542$\5424_IT-Basis-Dienste\LDAPeek legen. Der Dateiname trägt die Version (LDAPeek-1.2.0-win-x64.zip), und es gewinnt immer die höchste Version — nicht die zuletzt kopierte Datei. Ein zurückkopiertes altes Paket löst also kein „Update" nach unten aus. Ist der Ordner nicht erreichbar (Notebook ohne Netz), passiert schlicht nichts.

Logs und Fehlersuche

Logdateien liegen unter %LOCALAPPDATA%\LDAPeek\logs\ (Tagesarchiv, 14 Tage) und sind über ⓘ → Logdateien öffnen erreichbar. LDAPeek protokolliert jede Abfrage samt Filter und Dauer — bei einer überraschenden Auskunft steht dort, welcher Domain Controller sie geliefert hat. Passwörter und Tokens werden automatisch maskiert.

Häufige Meldungen:

Meldung Ursache
Der Verzeichnisserver ist nicht erreichbar Keine Verbindung ins Firmennetz — VPN prüfen.
Anmeldung abgelehnt Das in den Einstellungen hinterlegte Konto oder Passwort stimmt nicht.
Zeitüberschreitung Suche zu breit — Such-Basis auf eine OU eingrenzen.

Entwicklung

dotnet build   # bauen
dotnet test    # Tests
dotnet run --project LDAPeek

Release: VS-Code-Task „release (tag + push)" — prüft den Git-Zustand, setzt den Tag und stößt die GitHub-Action an, die das ZIP baut.

Bilder neu erzeugen

Die Bildschirmfotos in dieser Datei entstehen aus dem Programm selbst:

dotnet run --project LDAPeek -- --screenshots docs

Der Schalter existiert nur im Debug-Build. Er baut die Fenster mit erfundenen Daten (DemoDirectoryService), rendert sie über Avalonias eigenen Renderer in PNG-Dateien und beendet sich — ohne Verzeichniszugriff und ohne dass ein Fenster auf dem Bildschirm erscheint.

Zwei Gründe für diesen Weg statt eines Bildschirmabzugs von Hand:

  • Es dürfen keine echten Daten ins Bild. Dieses Repository ist öffentlich; ein Screenshot aus der Produktivdomäne würde Namen, Telefonnummern und Gruppenmitgliedschaften realer Personen veröffentlichen. Mit erfundenen Daten kann das gar nicht erst passieren.
  • Fenster von außen abzugreifen (PrintWindow, UI-Automation) sieht für verhaltensbasierte Virenscanner wie eine Fernsteuerung aus und wird blockiert. Außerdem hinge das Ergebnis von Fokus, Skalierung und verdeckenden Fenstern ab.

Details zu Architektur und Fallstricken: CLAUDE.md.

Lizenz

MIT — siehe LICENSE.