- C# 96.6%
- PowerShell 3.4%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
CI / build-test (push) Successful in 1m29s
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> |
||
| .forgejo/workflows | ||
| .github | ||
| .vscode | ||
| docs | ||
| LDAPeek | ||
| LDAPeek.Tests | ||
| scripts | ||
| .editorconfig | ||
| .gitignore | ||
| CLAUDE.md | ||
| Directory.Build.props | ||
| Directory.Packages.props | ||
| global.json | ||
| ldapeek.policy.example.json | ||
| LDAPeek.slnx | ||
| LICENSE | ||
| README.md | ||
LDAPeek
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.
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
- Links einen Suchbegriff eintippen und Suchen (oder Eingabetaste). Ab zwei Zeichen; zuletzt gesuchte Begriffe schlägt das Feld selbst vor.
- Einen Treffer anklicken. Rechts oben stehen die Stammdaten, darunter die Gruppen.
- 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.
RequiredGroupnimmt 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.
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.
| 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.


