What Is an SPN?
An SPN is a reference to a specific service, for example, an instance of SQL or a web application run by IIS. Since SPNs are specific, they reference not only what the service is (such as an SQL server), but also which hostname runs the instance and on which port it’s running (however, you don’t have to specify the port if running on default ports).
Service Principal Names are already in use for every computer and user account. Though not usually seen, there is a default SPN established at the time of account creation which is identified as the SAMAccountName with a Dollar Sign appended to it. Therefore, JoeUser@contoso.com would have a Service Principal Name of Contoso\JoeUser$ which is referenced by the domain during authentication and ticket granting.
When Should You Set an SPN?
Service Principal Names are not always necessary. Again, using the SQL Server as an example, once the SQL instance is established, a web application that uses the databases in the instance may point directly at the server. In that case, an SPN is not required, because there is no confusion about where the authentication is going to take place or where the service is located. However, in some cases you do not reference the SQL Server by direct name.
Another time that you may need to configure SPNs through the use of SetSPN is when using Kerberos to connect to a web application. In many cases, web applications running on IIS 7.5 will be using Kernel Mode authentication and will not require the use of SPNs to authenticate properly. But not all use cases can take advantage of Kernel Mode Authentication: SharePoint 2010 is an example of a web application that does not support Kernel Mode Authentication, even when running on IIS 7.5.
There are more use cases published by Microsoft that provide examples of when you will need to set a Service Principal Name with SetSPN.
Making it Simple:
There are a lot of articles out there on setting up Kerberos Service Principal Names but today I’m going to make it simple. Bear with me as I start off with the basics; by the end of the post it will all be very clear.
Throughout this post I’ll make reference to a scenario of a client computer connecting to an SQL server called sql1.domain.com however the same applies for any service, for example a web server where the client connects via HTTP.
The SQL server service is running under a domain service account called “domain\SQLSVC“. No SPNs have been set yet.
Active directory user and computer accounts are objects in the active directory database. These objects have attributes. Attributes like Name and Description.
Computer and User accounts are actually very similar in the way they operate on a Windows domain and they both share an attribute called ServicePrincipalName. An account object can have multiple ServicePrincipalName attributes defined.
The setspn.exe tool manipulates this attribute. That’s all it does.
The client wants to access the SQL server so he asks his domain controller: “Please may I have a ticket for accessing MSSQLSvc/sql1.domain.com”
Now the domain controller asks the active directory database: “Give me the name of the account object who’s ServicePrincipalName is MSSQLSvc/sql1.domain.com“
The active directory database replies: “Sorry, there are no account objects with that ServicePrincipalName”
So the domain controller asks the active directory database again: “Ok then, give me the account object who’s ServicePrincipalName is HOST/sql1.domain.com“
All computer accounts have, by default ServicePinciaplName attributes set to:
HOST/[computername] and HOST/[computername].[domain]
So the active directory database replies to the domain controller: “The account object that has that ServicePrincipalName is sql1.domain.com’s computer account“
The domain controller now creates a ticket that only the computer account of sql1.domain.com can read. He gives the ticket to the client.
The client goes to the SQL service on sql1.domain.com and says “here is my ticket, may I come in?”
The SQL service will attempt to read the ticket. The problem is, the SQL service is not running under the computer account; it is running under a domain service account. It can not read the ticket; the ticket is only intended for the computer account of sql1.domain.com. Authentication fails (falls backto NTLM).
Now lets run the setspn.exe tool to manipulate the ServicePrincipalName attribute of the SQL service account.
setspn -a MSSQLSvc/sql1.domain.com domain\SQLSVC
We will also add sql1 (without the domain name) in case we want to access the the server without the domain name appended.
setspn -a MSSQLSvc/sql1 <strong>domain\SQLSVC</strong>
Now run through the scenario again and this time notice that the domain controller will return a ticket that the SQL server service account can read.
Obviously this is heavily paraphrased but hopefully it helps you understand the reason for setting the SPN attribute on the account that runs a given service. Of course if the service runs under the local NetworkService or LocalSystem account then everything will just work because these local accounts represent the computer account in active directory.
SetSPN.exe Switches and Syntax
You may have noticed the “-a” switch used on the previous examples. SetSPN can be used with no switch, but then it doesn’t set an SPN, it displays them.
This example displays all SPNs that have been set on the SQL service account. Here are the most common switches used with SetSPN:
-a Add an entry to an account (explicitly)
-s Add an entry to an account (only after checking for duplicates first)
-d Delete an entry from an account
-x Search the domain for duplicate SPNs
-q Query the domain for a specific SPN
There are also a few switches that specify whether an account is a computer or user (-c and –u), but if you omit those you’re likely all right, as it will check for computers first and then check for users. If in your domain environment you have computers and users that share account names, then you will want to use the –u switch to modify user accounts.
Another way to check if SPN is working on the service account.
Open the Service Account properties and goto the Delegation tab. You should be able to see enterprises here if everything is setup correctly. If SPN is not registering even though a command prompt query says its there.
To make sure the SPN show up:
Click Add on the window above. The Add Services dialog box shows up.
Click Users or Computer and add the same user account. ( I know this sounds silly, because you are adding the account to itself), but this way it can see if the SPNs that are registered to the account and will show the available services automatically.
One the services show up. Click Select All and OK.
The services show up correctly to be used for Kerberos Only authentication.
Important things to know:
SPNs should be unique within the domain. If you set an AD account to have an SPN, do not set it on another account. This goes for the SPN being set on multiple computers, multiple users; it will also not function properly if there is both a user and a computer account that have the same SPN.
You can search for SPNs in the domain by using the –q switch. This will tell you if there is already an account that is using that SPN. For example:
SetSPN –q HTTP/MyWeb.mowasay.com
And if you need to troubleshoot a problem with an SPN, a good place to start is by verifying that there are no duplicate entries: