Creating Python Service to Query AD Attributes
I'm integrating our AD with web services running Python on linux using Python-LDAP over SASL(DIGEST-MD5) to query AD 2012 user attributes (division, department, phone extension, email, etc). After working out the kinks specific to my service against an AD 2003 I started to run into an SPN error against our new AD 2012, that the digest-uri didn't match any SPNs on the server. I've cross referenced the SPN list for both servers and they contain identical analogues of each other.
The Error: The digest-uri does not match any LDAP SPN's registered for this server
The Fix?
This was fixed by running:
setspn -A ldap/<Domain_Name> <Computer_Name>
Note that creating a service account did not fix my SPN error even when the following command was run:
setspn -A ldap/<Domain_Name> <Domain_Name>/<Service_Account_Name>
simple_bind_s() doesn't need SPN, sasl_interactive_bind_s() needs SPN
Only adding the SPN to the local machine SPN list worked for my Python-LDAP service using sasl_interactive_bind_s(). I should also note that the SPN step can be skipped if I use simple_bind_s() but this method sends credentials in cleartext which is unacceptable.
However I noticed that the record only stays on the SPN list for about a minute before disappearing? There are no errors when I run the setspn command, the event logs are completely empty, there are no duplicates anywhere, checked with the -F forest-wide search on the base dn and nothing. I've added and tried to re-add and removed and moved the SPN from object to object to verify that it's not hiding anywhere, but the second I add the object anywhere and then attempt to re-add it notifies me of a duplicate. So I'm very confident that there isn't a duplicate hidden somewhere.
The Hack
For now I've got a scheduled task re-running the command to keep the record on the list so my service will work aptly named "SPN Hack"
cmd.exe /C "setspn -A ldap/<Domain_Name> <Computer_Name>"
until I can find out why the SPN is being cleaned off the list.
I'm not the primary administrator for this particular AD, could the admin have a service running that syncing the SPN from another service on the AD and not be aware of it? My title is Web Developer, not as an excuse but to explain my ignorance for matters Active Directory. I've been told to make the AD the master user DB and I've been reading a lot but I can't find anywhere where people are having an issue with the SPN being 'overwritten' or 'cleaned' periodically and none of the admins are very familiar with SPN outside SQLServer entries.
Why do I need the hack?
So far my hack doesn't appear to have caused any issues for any users or services and hasn't generated any errors, so the admin says he'll just let it run and I'll keep looking. But then I find myself in the precarious situation of writing a service whose implementation is built on, essentially a cron hack /shiver… So, any help would be appreciated.
Update
After a conversation with the sysadmin he's agreed that building a service on top of a hack isn't a solution, therefore he's given me permission to spin up a local service with endpoint encryption that I can use for my purposes, the result is the same. I'll keep an eye out for what is causing the SPN to clear out. Local binds aren't a problem using Python-LDAP and the local service is already up and running after only an hour or so. It's unfortunate that I'm essentially wrapping functionality built into LDAP but we do what we have to do.
Best Answer
This is a truly interesting (and annoying) phenomenon and I insist that we find out what's going on here.
Fortunately, Windows Server has some fine grained auditing policies since 2008, and we can use auditing to track down who did this. To do so, we'll need to:
Find out where the SPN modification occurs:
Open an elevated command prompt on a domain controller and issue this command:
The output will contain the name of the Domain Controller who originally wrote the current version of the servicePrincipalName attributes value:
Enable AD DS object change auditing:
If a global audit policy is not already defined, you can make this change to the local security policy on the Domain Controller identified in the previous step
Open the Group Policy Management Console (
gpmc.msc
) and locate theDefault Domain Controllers Policy
and edit it.Computer Configuration -> Windows Settings -> Security Settings
Local Policies -> Security Options
Advanced Audit Policy -> Audit Policies -> DS Access
Set an audit ACE on the object:
Open Active Directory Users and Computers (
dsa.msc
) and Check the "Advanced Features" setting in the "View" menu.Navigate to the computer account object, right-click it and select Properties. Choose the Security tab, and hit the "Advanced" button.
In the prompt, select the Auditing tab and ensure that "Write all properties" is being audited for Everyone. If not, or if you're in doubt, Add a new entry:
(If you're lazy you can just select "Write all properties")
Reproduce the error
From your question it seems that the SPN get's deleted every minute or so, so this is probably the easiest step. Take a 1 minute music lesson in the mean time.
Inspect the security log on the offending DC
Now that a minute has passed, let's inspect the security log on the Domain Controller identified as the originator in step 1. This can be a pain in large domains, but filtering can help with this:
Windows Logs -> Security
<All Event IDs>
", input 5136 (this is the event id for directory object modification)You should now be able to find an event entry for each change to the
servicePrincipalName
attribute on the computer account.Identify the "Subject" responsible for the change and see where it came from. Kill that process/machine/account with fire!
If the subject is identified as
SYSTEM
,ANONYMOUS LOGON
or a similarly generic description, we're dealing with internal processing on the domain controller itself, and we'll need to break out some NTDS Diagnostic Logging to find out what's going on. Please update the question if this is the case