Home .NET Active Directory Sync

Active Directory Sync

by admin

On duty I had to deal with Active Directory. I had to read and experiment with classes, but it all worked perfectly.
First of all I would like to describe a little bit about the Directory Synchronization objectwhich appeared in.net framework 2.0. You can read about it, and about other advantages of the 2nd framework at the microsoft site (http://msdn.microsoft.com/en-us/magazine/cc188700.aspx ). I personally found it useful, even though I don’t have a lot of information about dyrSync on the web.
I use the Web-Service for synchronization, the steps are as follows :
1. Web service receives LDAP request path.

[WebMethod]
public void Synchronize ( string DomainPath, string Filter, string EntryPath)
{
DirectoryEntryde = new DirectoryEntry (DomainPath);
using (SqlConnection conn = new SqlConnection(Globals.ConnectionString))
{
conn.Open();
SqlCommand command = conn.CreateCommand();
command.CommandText = "INSERTINTOSyncTable (Snapshot, OU) VALUES (@Snapshot, @OU, @ExchangeServer)" ;
command.Parameters.AddWithValue( "@Snapshot" , GetSyncData(de, filter));
command.Parameters.AddWithValue( "@OU" , EntryPath);
command.ExecuteNonQuery();
conn.Close();
}
}

2. GetSyncData returns AD cookie:

public byte [] DirectorySync (DirectoryEntry DomainDE, string Filter)
{
ADInit.Init();
try
{
using (DirectorySearcher srch = new DirectorySearcher(DomainDE, Filter))
{
srch.SearchScope = SearchScope.Base;
srch.DirectorySynchronization = new DirectorySynchronization();
foreach (SearchResult se in srch.FindAll())
{
}
MemoryStream ms = new MemoryStream();
BinaryFormatter bFormat = new BinaryFormatter();
bFormat.Serialize(ms, srch.DirectorySynchronization.GetDirectorySynchronizationCookie());
ms.Close();
return ms.GetBuffer();
}
}
catch (Exception Ex)
{
throw Ex;
}
}

You have to use Domainas an entry point because DirSynch works with the root element of the tree. The filter can be in the form of : OU=myOU or something like that. In my case, I got around this feature quite easily by creating a hierarchical structure, fromwhich you can select both LDAP path to domain and LDAP path to this object. The filter, on the other hand, through the name of the objectto be synchronized.
3. Reverse synchronization + reconciliation

[WebMethod]
public bool GetRegionEntry ( string Domain, string Filter, string EntryPath)
{
DirectoryEntry de = new DirectoryEntry (Domain);
RegionInfo _regionInfo = regionEntry.GetEntry();
using (SqlConnection conn = new SqlConnection(Globals.ConnectionString))
{
conn.Open();
SqlCommand command = conn.CreateCommand();
command.CommandText = "SELECT* FROMSyncTable WHERE OU= @OU" ;
command.Parameters.AddWithValue( "@OU" , EntryPath);
SqlDataReader reader = command.ExecuteReader();
if (reader.Read())
{
return regionEntry.GetSyncDelta(de, Filter, ( byte [])reader[ «Snapshot» ]);
}
else
{
throw new Exception (“Can’t read Sync Cookie from Database!”);
}
conn.Close();
}
return _regionInfo;
}

Do your own thing here, either get a bool(there is a difference – no difference) or get a full delta.

///publicDictionary<string, object> GetSyncDelta (DirectoryEntry DomainDE, stringFilter, byte[] _cookie)
public bool GetSyncDelta (DirectoryEntry DomainDE, string Filter, byte [] _cookie)
{
Dictionary< string , object > _delta = new Dictionary< string , object > ();
BinaryFormatter bf = new BinaryFormatter();
byte [] cookie = ( byte []) bf.Deserialize( new MemoryStream(_cookie));
DirectorySynchronization dirSync = new DirectorySynchronization(cookie);
DirectorySearcher srch = new DirectorySearcher(DomainDE, Filter);
srch.DirectorySynchronization = dirSync;
foreach (SearchResult sr in srch.FindAll())
{
foreach ( string attrName in sr.Properties.PropertyNames)
{
_delta.Add(attrName, sr.Properties[attrName]);
}
return true ;
}
return false ;
//return _delta;
}

( Dictionary< string , object > is not serialized by standard methods in XML, try using your arrays with keyvaluepair, or rewrite the serialization).
4. To save the entire history of record changes, create another table, add an identifier field to it and put a trigger on INSERT/ UPDATE:

ALTER TRIGGER [SyncTableTrg]
ON [dbo].[SyncTable]
AFTER INSERT , UPDATE
AS
BEGIN
INSERT INTO SyncTableLog (OU, Snapshot)
SELECT OR, Snapshot FROM inserted
END

That way you get a pretty good history on each of the entries you sync. That’s not the only way though.
thank you for your attention
s.s. don’t judge. never blogged before( first experience

You may also like