DumpSPN

Script zur Dokumentation der aktuell registrierten Service Prinzipal Names und kontrolle auf Eindeutigkeit

Service Prinzipal Name - Was ist das und wofür ?

Server aber auch Dienste und IIS-Application Pools des IIS haben eine eigene "Persönlichkeit" und greifen auf verschiedene andere Dienste zu. Hierzu ist natürlich eine Authentifizierung erforderlich zu der Kerberos genutzt werden kann. Und jetzt sind wir erst mal am Ziel, da ein Kerberos Tickets einen "Service Prinzipal Name" enthalten für welche Sie ausgestellt werden.

Wenn ich mit meinem Browser einen Webserver erreichen möchte, dann fordert mein PC in meinem Namen ein "Ticket" für diesen Dienst beim Kerberos Distribution Center an. Wenn ich mit der Straßenbahn fahren möchte, dann muss ich mir auch ein Ticket für die Straßenbahnlinie kaufen und komme mit einem Air Berlin Flugschein nicht wirklich weiter. Der "Schaffner" sagt mir das aber, so dass ich an dem "Automaten" das richtige Ticket bekomme. Der Automat ist mit dem KDC (Kerberos Distribution Center) vergleichbar.

Hier begegnen wir dann auch wieder dem Service Prinzipal Name, da der KDC im Active Directory eben nach dem Namen sucht, um ein Ticket für diesen Dienst auszustellen. Hat ein Dienst nun keinen SPN veröffentlicht oder, schlimmer noch, haben zwei Systeme den gleichen SPN, dann kann der KDC kein Ticket ausstellen. Ich kann also dann nicht mit der Straßenbahn fahren, bzw. muss wieder beim Schaffner Zahlen (NTLM oder Basic Authentication statt Kerberos). Das funktioniert bei vielen Diensten ebenfalls, aber wenn Sie zwingend Kerberos benötigen, dann müssen Sie das Problem fixen.

Was macht DumpSPN ?

Natürlich können Sie nun ganz einfach mit CSVDE, LDIFDE, LDP oder Softerra LDAP eine LDAP-Suche im Active Directory machen. Aber eine Dublettenerkennung ist nicht so einfach möglich. Auch für eine Dokumentation ist natürlich eine Ausgabe in eine XML-Datei sehr hilfreich.

Genau das macht DumpSPN. Es verbindet sich mit einem globalen Katalog (GC) in ihrem Active Directory und sucht alle Objekte mit einem Service Prinzipal Name. Die Daten werden sowohl in einer XML als auch eine CSV-Datei ausgegeben. In beiden Dateien finden Sie dann den Status der SPNs, d.h. ob diese "OK" sind oder ein Konflikt vorliegt.

Das Skript kann allerdings nicht erkennen, wenn ein Dienst seinen SPN nicht registriert hat.

Download und Einsatz

Laden Sie sich zuerst das Script hier herunter:

dumpspn.1.0.vbs.txt
Nach dem Download auspacken und mit der Endung VBS speichern.

Der Aufruf des Scripts erfolgt am besten in einer DOS-Box, damit die Ausgaben einfacher lesbar sind.

cscript DumpSPN.1.0.vbs

Wie viele andere Skripte im Bereich Franks Tools legt auch dieses Script die obligatorische Protokolldatei dam XML-Ausgabe an.

DumpSPN Verzeichnis

Das ebenfalls immer wieder angelegte Stylesheet erlaubt eine einfache Anzeige im Browser. Sie erkennen hier einfach die verschiedenen DNs und die zugeordneten SPN's.

DumpSPN - IEAusgabe 

Die Spalte "STATUS" meldet, ob ein SPN des jeweiligen Objekts in Konflikt mit einem anderen Objekt steht.

Hinweis:
Das Skript erkennt natürlich nur beim zweiten Vorkommen den Konflikt. d.h. Wenn Objekt A und Objekt B den gleichen SPN registriert haben, dann steht nur bei bei Objekt B der Konflikt, während bei Verarbeitung von Objekt A ja noch nicht die Information von B vorhanden war.

Weiterhin schreibt DumpSPN eine CSV-Datei, welche die Informationen ebenfalls zeilenweise enthält. So ist auch eine Auswertung mit Excel und Filtern entsprechend möglich:

DumpSPN CSV-Ausgabe 

Hier wird dann für jeden SPN eine eigene Zeile ausgegeben.

PowerShell Version

Ich habe noch keine "komplette" PowerShell-Version fertig aber so schwer ist das gar nicht. Hier mal ein paar Schritte mit dem "ActiveDirectory" Modul um sie auf PowerShell neugierig zu machen:

# Liste alle Objekte, die einen Serviceprincipalname haben.
Get-ADObject -ldapFilter "serviceprincipalname=*" -Properties serviceprincipalname 

# nun gruppieren wie diese um doppelte Einträge zu finden. Group ist nicht case sensibel
Get-ADObject `
   -ldapFilter "serviceprincipalname=*" `
   -Properties serviceprincipalname `
| select distinguishedname,serviceprincipalname `
   -ExpandProperty serviceprincipalname `
|group 

# und nun das ganze gefilters auf SPNs die mehr als einmal vorkommen
Get-ADObject `
   -ldapFilter "serviceprincipalname=*" `
   -Properties serviceprincipalname `
| select distinguishedname,serviceprincipalname `
   -ExpandProperty serviceprincipalname `
| group `
| where {$_.count -gt 1}

Nun wissen Sie schon mal, welche SPNs mehrfach verwendet werden und entsprechend "gefixt" werden sollen. Dieser Einzeiler liefert aber noch nicht die betroffenen Objekte mit. Die gehen auf dem Weg durch die Pipeline noch verloren. Aber auch das lässt sich elegant lösen. Man muss nur selbst die Auflistung auffalten. diesmal aber nicht als Einzeiler.

# 
$adlist = Get-ADObject `
   -ldapFilter "serviceprincipalname=test*" `
   -Properties serviceprincipalname
$spnlist = foreach ($adobject in $adlist) {
   foreach ($spn in $adobject.serviceprincipalname){
      $out = $adobject |select distinguishedname,spn;
      $out.spn = $spn
      $out
   }
}
$problemlist = ($spnlist | group spn | where {$_.count -ne 1})
foreach ($problementry in $problemlist) {
   $problementry.group
}

Es ist immer wieder erstaunlich, wie einfach in PowerShell solche Dinge möglich sind.

Weitere Links