Beim Betrieb einer SharePoint-Farm ist man auf die korrekte Pflege von Accounts im Active Directory angewiesen. Gerade im Zusammenhang mit Kerberos ist es wichtig, dass alle Einstellungen im Active Directory richtig eingetragen werden, damit die Authentifizierung auch ohne Probleme funktioniert.
Als SharePoint-Farm Administrator hat man dazu allerdings nicht immer ohne weiteres Zugriff auf das Active Directory, zumindest nicht auf die Management-Tools. Nun stellt sich also die Frage, wie kann ich feststellen, welche Service-Principles alle für einen Account im Active Directory registriert wurden. Wenn ich Zugriff auf einen Domain-Controller hätte, dann würde ich ganz einfach SETSPN
verwenden.
C:\>SETSPN spIntranetWA Registered ServicePrincipalNames for CN=spIntranetWA,OU=Dienstkonten,OU=HeadQuarter,DC=acme,DC=local: HTTP/sp01.acme.local HTTP/intranet.acme.local
Aber SETSPN kann ich nur direkt auf einem Domain Controller ausführen, da komme ich als SharePoint Farm-Admin also nicht drauf. Was nun?
Wie bei allen Administrativen gibt es eine Ultimative Antwort: PowerShell!
Die Lösung ist so einfach, ich traue mich die ja schon kaum zu posten. Mit folgendem Befehl kann ich alle Einträge im Active Directory suchen, deren Account-Name “spIntranetWA” ist:
C:\> ([adsisearcher]"samaccountname=spIntranetWA").FindAll() Path Properties ---- ---------- LDAP://CN=spIntranetWA,OU=Dienstkonten,OU=HeadQuarter,... {logoncount, codepage, objectcategory, usnchanged...}
Damit habe ich schon mal ein paar Informationen.
Das funktioniert natürlich von jedem Arbeitsplatz mit PowerShell. Im Gegensatz zu den Active-Directory cmdlets verwende ich hier den ADSISearcher
(dabei handelt es sich um ein Alias für die DirectorySearcher
-Klasse aus dem .Net Framework). Das ist eine der genialen Dinge der PowerShell – ich kann mal eben so was aus dem .Net Framework verwenden. Um nun Objekte im Active-Directory zu suchen kann man dem ADSISearcher
LDAP-Abfragen übergeben.
Insbesondere die Properties sind hierbei interessant. Die kann man sich auch etwas genauer ansehen.
C:\> $accounts = ([adsisearcher]"samaccountname=spIntranetWA").FindAll() C:\> $accounts.properties Name Value ---- ----- logoncount {323} codepage {0} objectcategory {CN=Person,CN=Schema,CN=Configuration,DC=acme,DC=local} usnchanged {15699245} instancetype {4} name {spIntranetWA} pwdlastset {128843629222870406} serviceprincipalname {HTTP/sp01.acme.local, HTTP/intranet.acme.local} objectclass {top, person, organizationalPerson, user} samaccounttype {805306368} lastlogontimestamp {130265658248173942} usncreated {19523} dscorepropagationdata {21.06.2013 13:56:40, 21.06.2013 12:28:23, 20.07.2012 09:54:16, 01.01.1601 18:16:33} whencreated {16.04.2009 13:42:02} adspath {LDAP://CN=spIntranetWA,OU=Dienstkonten,OU=HeadQuarter,DC=acme,DC=local} useraccountcontrol {590336} cn {spIntranetWA} countrycode {0} primarygroupid {513} whenchanged {18.10.2013 10:30:24} lastlogon {130270479005600192} distinguishedname {CN=spIntranetWA,OU=Dienstkonten,OU=HeadQuarter,DC=acme,DC=local} samaccountname {spIntranetWA} objectsid {1 5 0 0 0 0 0 5 21 0 0 0 130 139 166 40 17 195 95 115 138 167 50 63 245 22 0 0} displayname {spIntranetWA} objectguid {217 8 220 57 70 168 118 76 178 20 180 160 198 219 146 67} accountexpires {9223372036854775807} userprincipalname {spIntranetWA@acme.local}
Hier kann man auch den ServicePrincipleName ablesen. Der Rest ist dann nur noch ein wenig PowerShell gefummel, um das ganze dann auch tabellarisch angezeigt zu bekommen.
C:\> ([adsisearcher]"samaccountname=sp*").FindAll()|select @{name='cn'; expression = {$_.properties['cn']}}, @{name="spn"; expression={$_.properties["ServicePrincipalName"]}} cn spn -- --- spCrawl spDBAccount spExtranetWA spFarm spInternetWA spIntranetWA {HTTP/sp01.acme.local, HTTP/intranet.acme.local} spMySites spSearch spSPService