While this is a blog on Technet and reasonably should be targeted towards infrastructure topics, I am including a little bit of development context in relation to Active Directory (AD). I share this as we often observe a barrier in communication between the administrators of AD and the developers who write code against AD. Specifically, this is for the benefit of AD administrators so that conversations between AD administrators and developers can be a little more constructive.
Often times myself and my peers have observed applications take outages because of coding practices in connecting to AD. Unfortunately, in general, AD administrators do not have enough development background to provide usefully precise recommendations to the developers in how to use code to leverage AD. Thus, I hope this post and the previous post on strategies for locating DCs will allow AD administrators to provide some reference guidance to help the developers identify some options to be a little more dynamic in their ability to locate DCs.
Binding to RootDSE:
Moving forward, in talking about serverless binds, I'm surprised at how frequently the question "How do I locate a Domain Controller (DC) or Global Catalog?" is encountered. This is usually in the context of diagnosing an application that is hard-coded to a DC, and the application fails because a DC goes offline. In one of the previous blog posts I spoke about the various pros and cons of using different methods to locate a DC. That's doing it all the hard way, but useful if more control is needed. ADSI (and System.DirectoryServices) and WLDAP32 (and System.DirectoryServices.Protocols) have some really nice functionality to take the work out of figuring out which DC to connect to.
There is not much to add that this article does not cover, at least for ADSI: Serverless Binding and RootDSE (Windows). Some key points from the article:
- If possible, do not hard-code a server name.
- In this case, a default domain controller from the domain that the security context of the calling thread is in will be used.
- If a domain controller cannot be accessed within the site, the first domain controller that can be found will be used.
Since this information is a little hard to find or scattered across multiple pieces of content, to assist in the recommendations for non-ADSI binds populate the method/function parameters as follows to bind to RootDSE:
- distinguishedName = null
- ldapFilter = "(objectClass=*)"
- searchScope = SearchScope.Base
- attributeList = null
attributeList = string array of the attributes you want
- ldap_search - Reference (Page 16) http://download.microsoft.com/download/3/d/3/3d32b0cd-581c-4574-8a27-67e89c206a54/uldap.doc
- base = NULL
- scope = LDAP_SCOPE_BASE
- filter = "(objectClass=*)"
- attributeList = NULL
Using the above to communicate with a specific server for consistency purposes:
As mentioned in the previous post, the only reason (at least that I've heard so far) to code against a specific DC is when there is a need for consistency. An option for many scenarios were consistency is needed, rather than hard-code a specific DC, is to use RootDSE to find a server. Specifically, read the data in the "dnsHostName" attribute from the RootDSE object returned in the search.
If the data in "dnsHostName" is used as the server name for all future connections, this will provide the consistency needed for most applications, while allowing changes to the environment to be much more dynamic. Though from here it gets more complex, depending on how the application handles errors from the DC due to inaccessibility. This has more to do with application design questions and moves beyond the scope of this article. But at the very least restarting the application will allow the application to locate an available/online DC and resume functioning.
Additionally, this will allow the application to port between domains easier, especially given bullet number two above. Just by changing the security context the application is running in, a DC in a separate domain will be located.
This has to do with many applications, but not all. There are some exceptions, though those usually have to do with using AD metadata for synchronization purposes.
With limited familiarity of Java, the ability to provide specifics is limited. But according to the documentation, LDAP Naming Service Provider for the Java Naming and Directory InterfaceTM (JNDI), section 6.2 specifies "The LDAP service provider supports the use of DNS configuration for automatically discovering the LDAP service." So a similar approach is possible.