Find duplicated SPNs in Active Directory

Today’s script will help you to in easy way find duplicated SPNs in Active Directory.

What is SPN?

SPN (Service Principal Name) according to Microsoft definition is unique identifier of service instance. To better understand it we can compare it to alias (CNAME record) in DNS.
A Service Principal Name is a pointer to account created in Active Directory domain. It can be either created for service account or computer object account.
HTTP/TestWebSite is an alias for the account\TestWebSiteAccount.

Below screenshot from Active Directory attribute of Service Principal.

How script works?

Script is gathering all users and computers account from Active Directory where Service Principal Name attribute is not empty.
In next section it is analyzing all service principal names and looks for duplicated.
If the script will find Service Principal Names with different SamAccountNames it will notify user that duplicated SPN has been found.

$AllSPNsObjects = Get-ADObject -Filter "(objectClass -eq 'user') -and (objectClass -eq 'computer')" -Properties sAMAccountName, servicePrincipalName | Where-Object servicePrincipalName -ne $null
$SPNArray = @()
foreach ($SPNObject in $AllSPNsObjects)
   $SamAccountName = $SPNObject.SamAccountName
   $ServicePrincipalNames = $SPNObject.ServicePrincipalName
   foreach ($ServicePrincipalName in $ServicePrincipalNames)
		if ($SPNArray.ServicePrincipalName -like "$ServicePrincipalName")
			$MatchedSPNs = $SPNArray.ServicePrincipalName -like "$ServicePrincipalName"
			foreach ($MatchSPN in $MatchedSPNs)
				$MatchSamAccountName = $MatchSPN.SamAccountName
				if ($MatchSamAccountName -ne $SamAccountName)
				   Write-Error "Duplicated SPN has been found for $ServicePrincipalName!!!"
			$Properties =  @{
                "SamAccountName" = $SamAccountName
                "ServicePrincipalName" = $ServicePrincipalName
             $SPNArrayRow = New-Object PSObject -Property $Properties
             $SPNArray += $SPNArrayRow

Please note that script can be running for a while in bigger environments as filtering all objects with SPNs takes some time.
Script is not using standard SPN cmdlet setspn as it is always better to use PowerShell command instead of command line tool (at least in my humble opinion ;).

Hope it will be usefull for some of you 😉

3 thoughts on “Find duplicated SPNs in Active Directory

  1. Hi and thanks for this script. I found a couple of small errors I’ve mentioned below.

    Lines 6 and 7 should use $SPNObject no $ADOject as in your code
    Line 13 should be $SPNArray.ServicePrincipalName not $SPNArray as in your code

    Also, instead of $SPNArray = @() I’ve changed to $SPNArray = New-Object System.Collections.ArrayList and used $SPNArray.add(SPNArrayRow) as this is significantly faster than the += notation, especially on very large data sets.

  2. Hi Daniel,

    You are correct, I’ve already adjusted script.
    Regarding $SPNArray, I believe that in production environments shouldn’t be many of duplicated SPNs 🙂 However, you are right if there will be big number of duplicated SPNs your solution can be faster.

    Thanks for tip!

  3. Also, if you want to create a PSCustomObject for each item that goes into your array, it’s easier to do:

    $SPNArrayRow = [pscustomobject]@{
    SamAccountName = $SamAccountName
    ServicePrincipalName = $ServicePrincipalName

    If you still want to use “+=” to add the object to your array, you can condense it a bit more:

    $SPNArray += [pscustomobject]@{
    SamAccountName = $SamAccountName
    ServicePrincipalName = $ServicePrincipalName

    Or using the ArrayList.Add() method:

    SamAccountName = $SamAccountName
    ServicePrincipalName = $ServicePrincipalName

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.