You are here: Sysadmins of the North » Windows Server » List all SPNs used in your Active Directory

List all SPNs used in your Active Directory

There are a lot of hints & tips out there for troubleshooting SPNs, or Service Principal Names. Listing duplicate SPNs is fairly easy, just use setspn -X on your command-line and you’ll find out. But how do you find out which SPNs are used for which users and computers are used for this?

An SPN or Service Principal Name is a unique identity for a service, mapped with a specific account (mostly service account). Using an SPN, you can create multiple aliases for a service mapped with an Active Directory domain account.

SetSPN command-line

To set, list or delete the SPN, we use an in-built command line tool SETSPN (setspn.exe) provided by Microsoft. It Reads, modifies, and deletes the Service Principal Names (SPN) directory property for an Active Directory service account. You use SPNs to locate a target principal name for running a service. You can use setspn to view the current SPNs, reset the account’s default SPNs, and add or delete supplemental SPNs.

Setspn is a command-line tool that is built into Windows Server 2008. It is available if you have the Active Directory Domain Services (AD DS) server role installed.

Quite some scripts assume you’re looking for a specific SPN (HTTP/…), a specific user, or a specific computer. For example, you can use setspn to find (query) Service Principal Names (SPNs) linked to a certain computer:

setspn.exe -L <ServerName>Code language: PowerShell (powershell)

Or you can use setspn to find (query) SPNs linked to a certain user account:

setspn.exe -L <domain\user>Code language: PowerShell (powershell)

And now you need a general script to list all SPNs, for all users and all computers…

You delete arbitrary SPNs, or Service Principal Names, using the -D switch:

setspn.exe -D <spn> accountnameCode language: HTML, XML (xml)

List SPNs using Powershell

Nice to know fact, Service Principal Names (SPNs) are set as an attribute on the user or computer accounts. That makes it fairly ease to query for that attribute. And modern admins do PowerShell, right?

So… Save the following code into a new PowerShell .ps1 file and run it in your domain. It will query and list the Service Principal Names – SPNs.

# Source / credit:
# https://social.technet.microsoft.com/wiki/contents/articles/18996.active-directory-powershell-script-to-list-all-spns-used.aspx

cls
$search = New-Object DirectoryServices.DirectorySearcher([ADSI]"")
$search.filter = "(servicePrincipalName=*)"

## You can use this to filter for OU's:
## $results = $search.Findall() | ?{ $_.path -like '*OU=whatever,DC=whatever,DC=whatever*' }
$results = $search.Findall()

foreach( $result in $results ) {
	$userEntry = $result.GetDirectoryEntry()
	Write-host "Object Name	=	"	$userEntry.name -backgroundcolor "yellow" -foregroundcolor "black"
	Write-host "DN	=	"	$userEntry.distinguishedName
	Write-host "Object Cat.	=	" $userEntry.objectCategory
	Write-host "servicePrincipalNames"

	$i=1
	foreach( $SPN in $userEntry.servicePrincipalName ) {
		Write-host "SPN ${i} =$SPN"
		$i+=1
	}
	Write-host ""
}Code language: PowerShell (powershell)

Or use dsquery on your CMD.exe command-line:

dsquery * "ou=domain controllers,dc=yourdomain,dc=com" -filter "(&(objectcategory=computer)
(servicePrincipalName=*))" -attr distinguishedName servicePrincipalName > spns.txtCode language: PowerShell (powershell)

This is a valuable script and information reference for your own documentation.

Conclusion

In this post, I showed you multiple methods of listing Service Principal Names, or SPNs. Using appropriate tools like setspn.exe dsquery.exe or PowerShell, you can query your Active Directory for service accounts. For example duplicate SPNs or SPNs used for specific users and computers.

Frequently Asked Questions

What are Service Principal Names (SPNs)?

An SPN or Service Principal Name is a unique identity for a service, mapped with a specific account (mostly service account). Using an SPN, you can create multiple aliases for a service mapped with an Active Directory domain account.

What tools can I use to look up SPNs?

To look up – or query – your Active Directory for service accounts, you can use a PowerShell script, setspn.exe or dsquery.exe.

Why would I want to query specifc SPNs?

You want to query specific SPNs, for example when you have migrated your file server share to a new and different file server. An SMB session might fail if you use an incorrect DNS CNAME SPN to the share in question. You may receive the error message “The target account name is incorrect.“.

10 thoughts on “List all SPNs used in your Active Directory”

  1. A few enhancement:

    class Spn {
        static [int]$counter
        [int]$id
        [string]$serviceClass
        [string]$name
        [string]$spnChain 
    
        Spn([string]$spnChainIs){
            
            $this.id = [Spn]::counter++
            $this.spnChain = $spnChainIs
            $temp = $spnChainIs.Split("/")
            $this.serviceClass = $temp[0]
            $this.name = $temp[1]
            
        }
    
        Spn([string]$portIs,[string]$objectIs){
            
            $this.id = [Spn]::counter++
            $this.serviceClass = $portIs
            $this.name = $objectIs
            $this.spnChain = ($this.serviceClass + "/" + $this.name)
        }
    
        [string] ToString(){
            return ("$($this.spnChain)")
        }
    
    }
    
    class Spns {
        hidden[string]$objectCategory
        hidden[string]$dN
        [string]$name
        [Spn[]]$spnss
    
    }
    
    Clear-Host
    $search = New-Object DirectoryServices.DirectorySearcher([ADSI]"")
    $search.filter = "(servicePrincipalName=*)"
    
    ## You can use this to filter for OU's:
    ## $results = $search.Findall() | ?{ $_.path -like '*OU=whatever,DC=whatever,DC=whatever*' }
    $results = $search.Findall()
    
    $report = @()
    
    foreach( $result in $results ) {
    	$userEntry = $result.GetDirectoryEntry()
        [Spns]$userSPNs = [Spns]::new()
        $userSPNs.dN             = $userEntry.distinguishedName
        $userSPNs.name           = $userEntry.name
        $userSPNs.objectCategory = $userEntry.objectCategory
    
        [Spn]::counter = 0
    	foreach( $SPN in $userEntry.servicePrincipalName ) {
            [Spn]$oneSpn = [Spn]::new($SPN)
            $userSPNs.spnss += $oneSpn #.ToString()
    	}
        $report += $userSPNs
    }
    
    $report | Measure-Object
    $report | Where-Object {($_.spnss).spnChain -like "*changepw*"}
  2. Thank you for your addition Purclot, thank you. It’s always great to have multiple methods available. Or use Get-ADComputer .

  3. if the tusk is just to list all the SPNs in your domain, why just not simply:
    Get-ADUser -filter * -prop * | where{$_.serviceprincipalname -ne $null} | select name, serviceprincipalname
    ?

  4. John Sullivan

    How can the above PowerShell script be modified to show just one server? I have tried different things but cannot get it to work.

    Thanks

  5. If using dsquery this filter will return user and computer objects
    -filter “(&(|(objectcategory=computer)(objectcategory=user))(servicePrincipalName=*))”

  6. Thanks for your addition!

    Update, a note to “John Doe’s” -Q addition: it seems like the -Q query modifier is removed in Windows Server 2016 and up. It’s available in the help of my Windows Server 2012 R2 servers, but not in 2016:

    d:\deployment>setspn /?
    Usage: setspn [switches data] computername
      Where "computername" can be the name or domain\name
    
      Switches:
       -R = reset HOST ServicePrincipalName
        Usage:   setspn -R computername
       -A = add arbitrary SPN
        Usage:   setspn -A SPN computername
       -D = delete arbitrary SPN
        Usage:   setspn -D SPN computername
       -L = list registered SPNs
        Usage:   setspn [-L] computername
    Examples:
    setspn -R daserver1
       It will register SPN "HOST/daserver1" and "HOST/{DNS of daserver1}"
    setspn -A http/daserver daserver1
       It will register SPN "http/daserver" for computer "daserver1"
    setspn -D http/daserver daserver1
       It will delete SPN "http/daserver" for computer "daserver1"
  7. Hé this is a great way to list all SPN’s used in my active directory network, thanks!

Leave a Comment

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

Scroll to Top