Active Directory modify attribute issue

I am having an issue modifying an attribute on an object. Of course, it is a somewhat complicated setup that causes me issues. I have 2 domains:

parent.domain.com

|

+-- child.parent.domain.com

Here are the steps that cause me the issue:

1) Create a new object in the "parent" domain (i.e. cn=NewObj,ou=myOU,DC=parent,DC=domain,DC=com)

2) Modify a distinguished name attribute on a user object in the child domain (cn=MyUser,cn=Users,DC=child,DC=parent,DC=domain,DC=com) and add the DN of the object created in step #1.

I am connected to the LDAP server for the domain parent.domain.com. Step #2 fails with the following exception:

javax.naming.directory.InvalidAttributeValueException: [LDAP: error code 19 - 000020B5: AtrErr: DSID-03152392, #1:0: 000020B5: DSID-03152392, problem 1005 (CONSTRAINT_ATT_TYPE), data 0, Att 26620062 (myDNAttribute) ]; remaining name ''

If I wait some period of time between step #1 and step #2, step #2 succeeds. Is there something else I should be doing in JNDI to make sure this succeeds? There are occasions where I don't need a delay between step #1 and #2 and it works. So, it definately seems to be a timing thing but I obviously can't just put an arbitrary delay in my code.

Also, if I create the new object in the child domain, I can modify the DN attribute on the user in the child domain without an issue.

Any suggestions appreciated.

Tony

[1465 byte] By [tony.thompsona] at [2007-10-3 4:32:27]
# 1
Would you be able to share your code ?Not entirely clear what object classes & attributes that you are modifying.In anycase, with multiple domain controllers & multiple domains, you need to be aware of the role of global catalogs and of the latency due to
adler_stevena at 2007-7-14 22:35:58 > top of Java-index,Core,Core APIs...
# 2

Of course, my code is not really that straight forward to share. I haven't taken the time to split things out into some sample code that fails yet either.

The object class that I am modifying is a user. The attribute that I am modifying on the user object is an attribute that I added to the schema and it is not flagged to be replicated into the global catalog. It seems like this is logically how things work:

1) ask parent.domain.com LDAP server to modify cn=MyUser,cn=Users,DC=child,DC=parent,DC=domain,DC=com

2) LDAP server throws a referral to child.parent.domain.com LDAP server

3) ask child.parent.domain.com LDAP server to modify cn=MyUser,cn=Users,DC=child,DC=parent,DC=domain,DC=com

4) the value to add to an attribute on the user is cn=NewObj,ou=myOU,DC=parent,DC=domain,DC=com

So, for step #4 to succeed, would child.parent.domain.com LDAP server just go verify that cn=NewObj,ou=myOU,DC=parent,DC=domain,DC=com exists? Which, at this point it does because I created it before I started the attribute modification. And this is where it seems to fail until some amount of time has passed. I am not using the global catalog to do this. I am just doing it through a normal LDAP connection. And this is where I ususally get started on my rant about why would Micro$oft create Active Directory only to force you to replicate everything back to the global catalog which amounts to a single flat domain.

Any chance you can point me to some documentation that talks about the global catalog and the replication latency issues?

tony.thompsona at 2007-7-14 22:35:58 > top of Java-index,Core,Core APIs...
# 3

I just happened to read this today...

It mentions that the default replication interval is 5 minutes (before the modified DC send a message to the other DCs that it has been modified). Maybe you can modify this value, to lower latency, or at least plan around it, but this doesn't sound at all ideal. Maybe you can figure out a way to do all your modifications in one domain...

Rich

http://www.informit.com/articles/article.asp?p=26866&seqNum=5&rl=1

Intersite and Intrasite Replication

There are distinct differences in internal and intersite domain controller replication. In theory, the network bandwidth within a site is sufficient to handle all network traffic associated with replication and other Active Directory activities. By the definition of a site, the network must be reliable and fast. A change notification process is initiated when modifications occur on a domain controller. The domain controller waits for a configurable period (by default, five minutes) before it forwards a message to its replication partners. During this interval, it continues to accept changes. Upon receiving a message, the partner domain controllers copy the modification from the original domain controller. In the event that no changes were noted during a configurable period (six hours, by default), a replication sequence ensures that all possible modifications are communicated. Replication within a site involves the transmission of uncompressed data.

awhiga at 2007-7-14 22:35:58 > top of Java-index,Core,Core APIs...
# 4

The latter post somewhat answered the question of replication.

You can find information on Active Directory replication, (probably much more than you want to know), at http://technet2.microsoft.com/WindowsServer/en/library/1465d773-b763-45ec-b971-c23cdc27400e1033.mspx?mfr=true

I'll directly avoid answering your question as to why Active Directory can be partitioned into multiple domains but it is important to understand that there are many reasons why this occurs and in general they are usually political rather than technology decisions.

One is simply that customers found it easier to migrate existing NT 4 domains in situ rather than clean up their network, another is for management reasons (delegation of administration), another could be for geographical reaons (avoid replication of data across low bandwidth WAN connections), and yet another for organizational reasons (separation of business units, mergers & acquisitions).

Active Directory was designed as a loosely coupled distributed system where the data converges over time. No different to programming for a distributed database using two phase commits. As a developer, you just have to deal with it.

To the best of my knowledge, when you are modifying an attribute of syntax distinguishedName, the domain controller will verify the name against a global catalog. This is because verifying a name can be more efficiently performed by querying a GC, rather than determining which domain is authoritative for the object and then generating an internal referral to that domain controller.

However I could be wrong as it could be possible that no GC exists in the current site, whereas a DC for the other doamin may exist in that site, and there may be less latency involved in querying a local DC rather than a GC across the WAN.

Imagine, Domain A, Domain B, Site 1 and Site 2. There are DC's for Domain A & Domain B in both sites 1 & 2,.Let's call them DAS1, DAS2, DBS1 and DBS2. And lets also say that DAS1 and DBS2 host the Global Catalog.

If you are modifying the manager attribute for a user UserB in Domain B on DBS2. If the value is the name of a user, UserA in Domain A, because DBS2 also hosts the GC, it will query itself for the existence of UserA. However if UserA was only recently created on DAS1, there will be a replication delay before UserA is replicated from DAS1 to DAS2 and hence to the GC on DBS2. (GC's replication can be quite complex, they can either source changes from other GC's or from DC's, depending on the network & replicatioon topology)

Whilst the latter post described how you can change the replication latency, unless you are a network administrator and understand your network topology and your replication requirements, don't fiddle with the knobs.

First of all I suggest that your code connects to the "correct" domain controllers (try and use an Active Directory "site" in which DC's for all domains exist) and secondly that your code elegantly handles the fact that it is working in a distributed, loosely coupled environment.

I would encourage you to read http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnactdir/html/efficientadapps.asp.

adler_stevena at 2007-7-14 22:35:58 > top of Java-index,Core,Core APIs...
# 5

Some time has passed on this issue and I haven't given up on it. I do have a better understanding of what is going on now. Let me go back to your example and simplify it a bit because it is easy enough to setup in the lab. Let's say we have DAS1 and DBS1 (DB is a sub-domain of DA). If both DAS1 and DBS1 host a GC, the scenario I outlined in my original post happens. Basically, DBS1 gets the modify request, doesn't see the object in its domain, checks its local GC and fails the request. The interesting part is, if I remove the GC from DBS1, the request works perfectly because DBS1 goes back to DAS1 to determine the existence of the object.

So, I went over to Google Groups and had a conversation with some guys closer to Microsoft (here it is if you want to see the whole thing http://groups.google.com/group/microsoft.public.active.directory.interfaces/browse_thread/thread/3a713c9b0afa4efd/9d2d80a40ca203d5?lnk=raot#9d2d80a40ca203d5). After much deliberation and some research on their part, they presented a solution to the problem. When I send the modify request, I need to include the LDAP_SERVER_VERIFY_NAME_OID control in the request.

So, since I am using JNDI, I have a bit of an issue. First, I have JNDI managing referrals. When I create the object I may have been sent a referral to another server to create the object but I never saw it. Is there any way for me to figure out where that request was fulfilled without managing referrals myself (not something I really want to do or should have to do, IMHO)?

Second, if I did know the server the object was created on, I don't have that control available in the JDK at the moment. Is that something I could write myself? Any tips (code examples) for doing that?

Thanks.

Tony

tony.thompsona at 2007-7-14 22:35:58 > top of Java-index,Core,Core APIs...
# 6

Hi Tony,

I'll have a quiet chuckle to myslef at your comment "some guys closer to Microsoft ". Ah, God bless our MVP's ! (I'm rather amused when they discuss the DNT, There aren't that many people who understand DNT and the ESE table layout, and I'm not one of them !)

Anyway, you've probably answered some of your questions regarding referral yourself. If you want to find out where your are being referred to,one solution is handling the referral yourself. Quite well documented at http://java.sun.com/products/jndi/tutorial/ldap/referral/throw.html

And for your last question regarding the LDAP Control, have a look at the topic I just posted entitled at http://forum.java.sun.com/thread.jspa?threadID=5117992

The sample at the bottom illustrates how to use the LDAP_SERVER_VERIFY_NAME_OID control.

Good luck.

adler_stevena at 2007-7-14 22:35:58 > top of Java-index,Core,Core APIs...