Ausgangslage: ein neuer Mitarbeiter fängt an
In den meisten Betrieben schickt die Personalabteilung eine Mail an die IT. Ein Administrator tippt die Daten ab und entscheidet nebenbei, wie der Anmeldename aussieht, in welchen Ordner das Konto gehört und welche Gruppen es bekommt. Das hat drei Schwächen.
- Es dauert. Zwischen Mail und fertigem Konto liegen Stunden bis Tage, je nachdem, wann jemand dazu kommt.
- Es wird uneinheitlich. Der eine schreibt
m.mueller, der anderemueller_m. Nach ein paar Jahren lässt sich kaum noch auswerten, wer worauf Zugriff hat. - Es braucht zu hohe Rechte. Wer Konten anlegt, arbeitet meist mit Vollzugriff auf das ganze Verzeichnis. Wer diese Zugangsdaten erbeutet, dem gehört das Netz. So laufen die Verschlüsselungsangriffe ab, von denen man in der Zeitung liest.
Wie es jetzt läuft
Die Personalabteilung füllt ein Formular aus. Die IT prüft und gibt frei. Danach tippt kein Mensch mehr. Ein geplanter Task auf dem Verwaltungsserver holt genehmigte Vorgänge alle fünf Minuten ab, ruft den passenden Befehl auf dem Domain Controller auf und meldet das Ergebnis zurück. Wer eingereicht, wer genehmigt und was der Dienst getan hat, steht in einem Protokoll, das nur ergänzt werden kann.
Das Erstpasswort eines neuen Kontos zeigt die Verwaltungsseite dem IT-Admin genau einmal an und löscht es danach aus der Datenbank. Im Protokoll steht, dass es abgerufen wurde.
Eintritt
Anmeldename nach fester Regel, richtige Abteilung, Gruppen und auf Wunsch eine Rolle.
Wechsel
Umzug in die neue Abteilung, Gruppen und Rolle werden getauscht, nicht ergänzt.
Austritt
Deaktivieren statt löschen, der Grund steht in der Kontobeschreibung.
Übersicht
Wer ist in welchen Gruppen, welche Konten waren 90 Tage nicht angemeldet, welche Gruppen sind leer.
Rezertifizierung
Je Gruppe bestätigt jemand für jede Person „behalten“ oder „entziehen“.
Protokoll
Jeder Antrag, jede Genehmigung, jede Ausführung, nur ergänzbar.
Den Entzug nach einer Rezertifizierung führt das Werkzeug bewusst nicht selbst aus. Er läuft als normaler Änderungsvorgang und braucht damit dieselbe Genehmigung und denselben Nachweis wie jede andere Änderung.
Die Entscheidungen, auf die es ankam
Ein Schalter statt eines Generalschlüssels
Der naheliegende Weg wäre, die Zugangsdaten eines Administrators irgendwo zu hinterlegen und ein Programm damit arbeiten zu lassen. Dieses Programm kann dann alles, was der Administrator kann. Bei mir läuft der Zugang zum Domain Controller über PowerShell JEA (Just Enough Administration). Erlaubt sind nur die drei Funktionen für Eintritt, Wechsel und Austritt, und die arbeiten nur unterhalb der OU „Mitarbeiter“.
Das ist technisch erzwungen, nicht vereinbart. Beim ersten Test habe ich nachgesehen, welche Befehle in dieser Sitzung überhaupt sichtbar sind: neun. Der eine Befehl für die Anlage und acht Standardfunktionen, die die Sitzung zum Betrieb braucht. Später kamen Ändern und Deaktivieren dazu, sonst nichts.
# Eintritt: Name nach Regel, Abteilung, Gruppen, optional Rolle
New-CompanyADUser
# Wechsel: Umzug, Abteilungsgruppe und Rolle tauschen
Set-CompanyADUser
# Austritt: deaktivieren, Grund in die Beschreibung
Disable-CompanyADUser
# Alles andere gibt es in dieser Sitzung nicht.
Ein Passwort, das niemand kennt
Der zweite klassische Fehler ist ein Dienstkonto mit festem Passwort in einer Konfigurationsdatei. Solche Passwörter werden nie geändert und stehen irgendwann in einer Dokumentation. Hier läuft der Dienst als gruppenverwaltetes Dienstkonto (gMSA): Windows erzeugt das Passwort selbst, wechselt es alle 30 Tage und gibt es nur an Server heraus, die namentlich dafür freigegeben sind. Es lässt sich weder weitergeben noch aus einer Datei stehlen.
Der Ort begrenzt, nicht eine Liste im Code
Welche Rollen das Formular anbietet, liest es aus einer eigenen OU im Verzeichnis. Was dort nicht liegt, kann niemand beantragen. Die Gruppe der IT-Administratoren liegt woanders und ist über das Werkzeug damit gar nicht erreichbar, auch nicht durch einen manipulierten Antrag.
Drei Schutzzonen, auch im Netz
Der Aufbau folgt dem Tier-Modell von Microsoft: Domain Controller, Verwaltungsserver und Webserver sind getrennte Zonen. Der Domain Controller nimmt Wartungsverbindungen nur vom Verwaltungsserver an. Der Webserver, auf dem das Formular läuft, ist zusätzlich ausgehend gesperrt. Gesperrt ist dabei nur der Verwaltungskanal, denn als Domänenmitglied braucht der Webserver weiter DNS und Anmeldung.
Ein Negativtest allein beweist nichts
Prüfen wollte ich, dass der Webserver den Domain Controller nicht erreicht. Der Test schlug fehl, genau wie gewünscht. Dann fiel mir auf, dass die Firewall auf dem Domain Controller seit der Installation ausgeschaltet war. Mein früherer erfolgreicher Test lief also unter anderen Bedingungen. Nach dem Einschalten habe ich beide Hälften wiederholt:
| Von welchem Server | Kommt durch? | Erwartet |
|---|---|---|
| Verwaltungsserver | Ja | Ja, er soll arbeiten können |
| Webserver | Nein | Nein, er hat dort nichts zu suchen |
Beide Server hängen im selben Netz. Der Unterschied kann also nur aus der Regel kommen. Erst damit ist belegt, dass die Absicherung greift und nicht einfach alles blockiert ist.
Was der erste echte Testlauf gefunden hat
Nachdem alle Bausteine gebaut waren, habe ich jede Vorgangsart einmal vollständig durchgespielt: Formular, Genehmigung, geplanter Task, JEA, Domain Controller. Dabei kamen sechs Fehler heraus, die auf dem Papier unsichtbar waren.
- JEA-Sitzungen erlauben keine eigene Logik. Sie laufen in einem Modus ohne Sprachelemente, Logik im übergebenen Skriptblock ist dort verboten. Jeder Lauf brach daran ab.
- Eine Typumwandlung griff auf das falsche Objekt. Im Parameter landete das ganze Objekt statt eines Feldes.
- Umlaute führten zu einem Fehler. PowerShell 5.1 schickte den Text nicht als UTF-8, jede Fehlermeldung mit Umlaut wurde abgelehnt.
- Die Rollen standen im Konzept verkehrt herum. In AD vererbt sich Mitgliedschaft nach oben, die Rollengruppe muss also Mitglied der Fachgruppe sein, nicht umgekehrt.
- AD kennt kein Recht „Verschieben“. Der Umzug in eine andere OU brauchte zusätzlich das Recht, dort Objekte zu löschen.
- Ein Rollenwechsel ließ die alte Rolle stehen. Ausgerechnet das Werkzeug gegen Rechte-Ansammlung sammelte selbst Rechte an.
Schon der allererste Test der Kontenanlage hatte eine Grenze gefunden: Ein Anmeldename darf höchstens 20 Zeichen lang sein. Der Testname traf diese Grenze genau, und als die Automatik zur Unterscheidung eine Ziffer anhängen wollte, verweigerte das System die Anlage. Im Betrieb wäre das erst aufgefallen, wenn zwei Mitarbeiter mit langem Namen gleich heißen.
Die Fehler 4 und 6 steckten in meinem eigenen Konzept. Gefunden hat sie die Übersichtsseite, weil sie den tatsächlichen Zustand im Verzeichnis zeigt und nicht den geplanten. Diese Prüfansicht baue ich seitdem früh und nicht am Ende.
Und ein Fehler in meinem eigenen Vorgehen
Vor jedem Neu-Ausrollen der Web-App löschte mein Ablauf die alten Dateien im Programmordner. Darin lag aber auch die Datenbank mit der Antragshistorie. Jedes Update hat sie still geleert. Die Konten in AD waren nicht betroffen, der Nachweis, wer was beantragt hatte, schon. Statt die Datei auf eine Ausnahmeliste zu setzen, liegt die Datenbank jetzt außerhalb des Programmordners. Dass sie ein Update übersteht, habe ich mit einem echten Durchlauf geprüft.
Was es nicht ist
Es ist ein Laboraufbau: drei virtuelle Server, eine Testdomäne, kein Echtbetrieb. Der Kern funktioniert nachweislich. Belastung, Ausfallsicherheit und Wiederanlauf habe ich nicht getestet. Offen ist auch eine Anmeldesperre für das Tier-0-Administratorkonto auf dem Webserver. Bisher schützt nur die Firewall davor, dass es sich dort anmeldet.
Technik
| Teil | Womit |
|---|---|
| Umgebung | Drei Windows-Server auf VMware: Domain Controller, Verwaltungsserver (Server Core), Webserver mit IIS |
| Zugriff auf AD | PowerShell JEA mit eigener Rollendefinition, läuft als gMSA, mit Sitzungsprotokoll |
| Web-App | ASP.NET Core mit Razor Pages, Windows-Anmeldung, Rollen über AD-Gruppen, SQLite mit Migrationen |
| Verarbeitung | Geplanter Task auf dem Verwaltungsserver, interne Schnittstelle über HTTPS mit Windows-Anmeldung |
| Lesen aus AD | LDAP unter der Identität des Webservers, ohne hinterlegte Zugangsdaten und ohne Schreibrecht |