views:

2594

answers:

4

I've got an Active Directory synchronization tool (.NET 2.0 / C#) written as a Windows Service that I've been working on for a while and have recently been tasked with adding the ability to drive events based on changes in group membership. The basic scenario is that users are synchronized with a security database and, when group membership changes, the users need to have their access rights changed (ie. if I am now a member of "IT Staff" then I should automatically receive access to the server room, if I am removed from that group then I should automatically lose access to the server room).

The problem is that when doing a DirectorySynchronization against groups you receive back the group that has had a member added/removed, and from there when you grab the members list you get back the list of all members in that group currently not just the members that have been added or removed. This leads me to quite an efficiency problem - that being that in order to know if a user has been added or removed I will have to keep locally a list of each group and all members and compare that against the current list to see who has been added (not in local list), and who has been deleted (in local list, not in current members list).

I'm debating just storing the group membership details in a DataSet in memory and writing to disk each time I've processed new membership changes. That way if the service stops/crashes or the machine is rebooted I can still get to the current state of the Active Directory within the security database by comparing the last information on disk to that from the current group membership list. However, this seems terrible inefficient - running through every member in the group to compare against what is in the dataset and then writing out changes to disk each time there are changes to the list.

Has anyone dealt with this scenario before? Is there some way that I haven't found to retrieve only a delta of group members? What would you do in this situation to ensure that you never miss any changes while taking the smallest performance hit possible?

Edit: The AD might contain 500 users, it might contain 200,000 users - it depends on the customer, and on top of that how many groups the average user is a member of

+1  A: 

I'd say it depends on how many active directory objects you need to keep track of. If it's a small number (less than 1000 users) you can probably serialize your state data to disk with little noticable performance hit. If you're dealing with a very large number of objects it might be more efficient to create a simple persistence schema in something like SQL Express and use that.

Joseph Daigle
+2  A: 

You can set up auditing for the success of account modifications in group policy editor

You may then monitor security log for entries and handle log entries on account modifications.

E.g.

  EventLog myLog = new EventLog("Security");

  // set event handler
  myLog.EntryWritten += new EntryWrittenEventHandler(OnEntryWritten);
  myLog.EnableRaisingEvents = true;

Make sure that you have privileges to acces Security event log http://support.microsoft.com/kb/323076

Claus Thomsen
+1  A: 

You know there are products which help you with directory synchronization and user provisioning (google those terms)? Not invented here and all that, and you may have to justify the investment in the current climate, but developing and maintaining code for which there already is a commercial solution is not, let us say, always the most cost-effective way in the long run.

Not all of the support eventing/provisioning, but they do support tracking changes and distributing them: it's not a big deal creating eventing solutions on top of those capabilities.

Microsoft has the Identity Integration Server (MISS) which is being repackaged as part of Identity Lifecycle Manager. It was originally built on a more general meta/master data management product, but is workable. IBM has the Tivoli Directory Integrator (but you need to keep up with the biyearly name changes!). Oracle has an Oracle Identity Manager, and Sun an Identity Manager. Most of these are leading products bought by the major players to fill a gap in their portfolios.

Of course, these are enterprise-class products, meaning large & expensive, but generally pretty future-safe and extensible. If you don't need their full strength (yet!), you'll need to look at storing a copy for yourself. In that case, have you considered storing your replica of the last known AD tree using AD LDS (formerly AD/AM)? It's not in an optimum format for comparing differences, but a directory database will scale reasonably well, even the lightweight kind.

Pontus Gagge
A: 

JustinD, did you ever come up with a solution to this problem? I have the same problem I am trying to solve right now.

Thx!

borbird
I didn't come up with a good one - I ended up taking Joseph's advice and just serializing the data to disk and then also keeping the information in memory (I'm storing limited data - basically their guid base64 encoded and the group IDs). I store them in a DataSet and then write that DataSet to XML and then only rewrite the XML when there are changes - that way if the service restarts I can read the XML back into the DataSet and not lose any changes. It's far from ideal, but so far it's worked on AD's ranging from 500 to 20,000 users
JustinD