static void Main() { try { //Begin - Section 1: Enable Logging EnableLogging(); //End - Section 1 //Begin Section 2: - Get SSDP object var syncServDp = new SynchronizationServiceDataProvider(_logger); var syncServices = syncServDp.GetServiceConfigurations(); //End - Section 2 //Begin Section 3: - Start The Service if (Debugger.IsAttached) { var debugConfig = syncServDp.GetServiceConfiguration(DebugConfigID); //Launch the Service LDAPSyncService.Sync(debugConfig.DataItems[0].ConfigID); } else { var servicesToRun = new List <ServiceBase>(); foreach (var serviceConfigurationModel in syncServices.DataItems) { switch (serviceConfigurationModel.ConfigTypeID) { //This determines all the service configuration for the LDAP that needs to be run case ((int)ConfigType.LDAP): { if (debugMode) { EventLog.WriteEntry("SynchronizationService", "Adding service for ConfigXML " + serviceConfigurationModel.ConfigXML, EventLogEntryType.Information); } if (debugLogFileMode) { using (StreamWriter sw = File.AppendText("Log.txt")) { sw.WriteLine("Adding service for ConfigXML " + serviceConfigurationModel.ConfigXML); } } servicesToRun.Add(new LDAPSynchronizationService(serviceConfigurationModel.ConfigID)); break; } } } ; ServiceBase.Run(servicesToRun.ToArray()); } //End Section 3 } catch (Exception e) { EventLog.WriteEntry("SynchronizationService", "Error launching services: " + e.Message, EventLogEntryType.Error); } }
protected override void OnStart(string[] args) { var syncServ = new SynchronizationServiceDataProvider(_logger); var config = syncServ.GetServiceConfiguration(_configID).DataItems[0]; using (XmlReader reader = XmlReader.Create(new StringReader(config.ConfigXML))) { // get the services that need to be started, and their intervals, from the db reader.ReadToFollowing("Timer"); reader.ReadToDescendant("Interval"); reader.MoveToFirstAttribute(); var interval = Convert.ToDouble(reader.Value); _timerClock.Elapsed += delegate { LDAPSyncService.Sync(_configID); }; _timerClock.Interval = interval * 60 * 1000; // interval (in minutes) to execute process _timerClock.Enabled = true; } }
//public static void Sync(Object source, ElapsedEventArgs e) public static void Sync(int configID) { _debugMode = ConfigurationManager.AppSettings["Debug"] != null && Convert.ToBoolean(ConfigurationManager.AppSettings["Debug"]); _debugLogFileMode = ConfigurationManager.AppSettings["DebugLogFile"] != null && Convert.ToBoolean(ConfigurationManager.AppSettings["DebugLogFile"]); // first lets get our current config, in case something has been updated var syncServ = new SynchronizationServiceDataProvider(_logger); var config = syncServ.GetServiceConfiguration(configID).DataItems[0]; // we only want to run this service is we have an active config for it // todo: the plan is at some point to have a network monitoring tool to set which configs are active, so services on multiple servers know if they should be running or not // NOTE: by having the services continue to check their configs, the configs can be changed if (_debugMode) { EventLog.WriteEntry("SynchronizationService", "Using the following ConfigXML: " + config.ConfigXML, EventLogEntryType.Information); } if (_debugLogFileMode) { using (StreamWriter sw = File.AppendText("Log.txt")) { sw.WriteLine("Using the following ConfigXML: " + config.ConfigXML); } } if (config != null && config.IsActive != null && (bool)config.IsActive) { /* * config.ConfigXML reads from the DB the configuration database containing * SyncServer * - ProcessingServer * Timer * - Interval * LDAPServer * - LDAPPath * - LDAPUserFilter * - LDAPRoleFilter * - Name * - Port: Defaultvalue="389" */ using (XmlReader reader = XmlReader.Create(new StringReader(config.ConfigXML))) { // create a directory identifier and connection, reader.ReadToFollowing("SyncServer"); reader.ReadToDescendant("ProcessingServer"); reader.MoveToFirstAttribute(); var processingServer = reader.Value; reader.ReadToFollowing("LDAPServer"); reader.ReadToDescendant("LDAPPath"); reader.MoveToFirstAttribute(); var ldapPath = reader.Value; reader.ReadToFollowing("LDAPUserFilter"); reader.MoveToFirstAttribute(); var ldapUserFilterFromConfig = reader.Value; reader.ReadToFollowing("LDAPRoleFilter"); reader.MoveToFirstAttribute(); var ldapRoleFilterFromConfig = reader.Value; if (_debugMode) { EventLog.WriteEntry("SynchronizationService", "Sync Server host name should be " + System.Net.Dns.GetHostName() + ", ldap sync server configured is " + processingServer + ", ldap path configured is " + ldapPath + ", ldap user filter configured is " + ldapUserFilterFromConfig + ", ldap role filter from config is " + ldapRoleFilterFromConfig, EventLogEntryType.Information); } if (_debugLogFileMode) { using (StreamWriter sw = File.AppendText("Log.txt")) { sw.WriteLine("Sync Server host name should be " + System.Net.Dns.GetHostName() + ", ldap sync server configured is " + processingServer + ", ldap path configured is " + ldapPath + ", ldap user filter configured is " + ldapUserFilterFromConfig + ", ldap role filter from config is " + ldapRoleFilterFromConfig); } } //Till here make sure that you have the right configuration on the right machine // we need to look at the previous batch to know which updates to start requesting, as well as to make sure its completed before starting a new batch var lastBatch = syncServ.GetLastBatch(config.ConfigID); // the batches are by config, not config type, as you can have more than 1 config for a given type if ( processingServer == System.Net.Dns.GetHostName() && // we want to make sure we have the ldap info we need to pull what we need from AD ( ldapPath != string.Empty && ldapUserFilterFromConfig != string.Empty && ldapRoleFilterFromConfig != string.Empty ) && // only proceed w/ a new AD request, once the last request has been completed ( lastBatch.DataItems.Count < 1 || (lastBatch.DataItems[0] != null && lastBatch.DataItems[0].BatchStatusID >= (int)BatchStatus.Completed) ) ) { var usnChanged = (lastBatch.DataItems.Count > 0) ? lastBatch.DataItems[0].USN : 0; var ldapUserFilter = ldapUserFilterFromConfig.Replace(_usnChangedToken, usnChanged.ToString()); if (_debugMode) { EventLog.WriteEntry("SynchronizationService", "Searching AD for users using ldap filter string: " + ldapUserFilter, EventLogEntryType.Information); } if (_debugLogFileMode) { using (StreamWriter sw = File.AppendText("Log.txt")) { sw.WriteLine("Searching AD for users using ldap filter string: " + ldapUserFilter); } } var resultsUsers = SearchAD(ldapPath, ldapUserFilter); var ldapRolesFilter = ldapRoleFilterFromConfig.Replace(_usnChangedToken, usnChanged.ToString()); if (_debugMode) { EventLog.WriteEntry("SynchronizationService", "Searching AD for roles using ldap filter string: " + ldapRolesFilter, EventLogEntryType.Information); } if (_debugLogFileMode) { using (StreamWriter sw = File.AppendText("Log.txt")) { sw.WriteLine("Searching AD for roles using ldap filter string: " + ldapRolesFilter); } } var resultsRoles = SearchAD(ldapPath, ldapRolesFilter); // we only want to create a new batch, if there are actually results to be processed if ((resultsUsers != null && resultsRoles != null) && (resultsUsers.Count > 0 || resultsRoles.Count > 0)) { // add this new request to the db var batch = new ServiceBatchModel { BatchStatusID = (int)BatchStatus.Requesting, BatchTypeID = (int)BatchType.ADSynService, ConfigID = config.ConfigID, USN = _lastUSN + 1, IsActive = true }; batch.BatchID = syncServ.AddBatch(batch).ID; if (_debugMode) { EventLog.WriteEntry("SynchronizationService", "Batch created, ID: " + batch.BatchID, EventLogEntryType.Information); } if (_debugLogFileMode) { using (StreamWriter sw = File.AppendText("Log.txt")) { sw.WriteLine("Batch created, ID: " + batch.BatchID); } } var dtUsers = BuildUsersDataTable(resultsUsers, batch.BatchID, ldapPath); if (_debugMode) { EventLog.WriteEntry("SynchronizationService", "Inserting users into UserStage table.", EventLogEntryType.Information); } if (_debugLogFileMode) { using (StreamWriter sw = File.AppendText("Log.txt")) { sw.WriteLine("Inserting users into UserStage table."); } } syncServ.BulkInsert(dtUsers, UserStageTable, _debugMode, _debugLogFileMode); var dtRoles = BuildRolesDataTable(resultsRoles, batch.BatchID); if (_debugMode) { EventLog.WriteEntry("SynchronizationService", "Inserting roles into RoleStage table.", EventLogEntryType.Information); } if (_debugLogFileMode) { using (StreamWriter sw = File.AppendText("Log.txt")) { sw.WriteLine("Inserting roles into RoleStage table."); } } syncServ.BulkInsert(dtRoles, RoleStageTable, _debugMode, _debugLogFileMode); // also, lets populate which groups the users belong to var dtUserRoles = BuildUserRolesDataTable(resultsRoles, batch.BatchID, ldapPath); if (_debugMode) { EventLog.WriteEntry("SynchronizationService", "Inserting user's roles into RoleStage table.", EventLogEntryType.Information); } if (_debugLogFileMode) { using (StreamWriter sw = File.AppendText("Log.txt")) { sw.WriteLine("Inserting user's roles into RoleStage table."); } } syncServ.BulkInsert(dtUserRoles, UserRoleStageTable, _debugMode, _debugLogFileMode); // if we've added any staging data to be processed, update the batch created for this interval for keeping up w/ the data to be processed // NOTE: adding +1 to the last usn, as we are doing a >= to filter by usn, so we don't want to get the last usn again, the next time we look for updates batch.BatchStatusID = (int)BatchStatus.Completed; batch.BatchTypeID = (int)BatchType.ADSynService; batch.USN = _lastUSN + 1; if (_debugMode) { EventLog.WriteEntry("SynchronizationService", "Updating batch to Pending status with USN " + batch.USN + ".", EventLogEntryType.Information); } if (_debugLogFileMode) { using (StreamWriter sw = File.AppendText("Log.txt")) { sw.WriteLine("Updating batch to Pending status with USN " + batch.USN + "."); } } syncServ.UpdateBatch(batch); } } } } }
/// <summary> /// This function helps to authenticate the AD Users /// </summary> /// <param name="username"></param> /// <param name="pwd"></param> /// <returns></returns> public int IsAuthenticated(string username, string pwd) { int statusCode = -6; var syncServ = new SynchronizationServiceDataProvider(_logger); var path = syncServ.GetServiceConfiguration("ActiveDirectoryPath").DataItems[0].ConfigXML; var groupNameconfig = syncServ.GetServiceConfiguration("ActiveDirectoryGroupName").DataItems[0].ConfigXML; DirectoryEntry entry = new DirectoryEntry(path, username, pwd); if (entry == null) { statusCode = -7; return(statusCode); } try { DirectorySearcher search = new DirectorySearcher(entry); search.Filter = "(SAMAccountName=" + username.Split('\\')[1] + ")"; // Instead of checking for the groups below this will be a faster approach to check for the group. It will have to wait for a bit. // search.Filter = "(&(objectClass = user)(sAMAccountName = " + username.Split('\\')[1] + ")" + ApplicationSettings.LDAPUserGroup; // Check for Group Currently we are loading the common name properties which points to the group. // Group Objects: cn https://msdn.microsoft.com/en-us/library/ms676913(v=vs.85).aspx // CN = Common Name //OU = Organizational Unit //DC = Domain Component search.PropertiesToLoad.Add("cn"); search.PropertiesToLoad.Add("memberOf"); SearchResult result = search.FindOne(); if (result == null) { // Set A message to display that User Does not exist statusCode = -6; return(statusCode); } int groupCount = result.Properties["memberOf"].Count; if (groupCount < 1 || (string)result.Properties["memberOf"][0] == "No Group") { // Set A message to display that User Does not belong to a group statusCode = -6; return(statusCode); } for (int groupCounter = 0; groupCounter < groupCount; groupCounter++) { if (((string)result.Properties["memberOf"][groupCounter]).Equals(groupNameconfig.ToString(), StringComparison.CurrentCultureIgnoreCase)) { statusCode = 1; return(statusCode); } } } catch (Exception ex) { //There is no Exception Method but an Error Method. _logger.Error("Active Directory Communication is failing", ex); statusCode = -5; } return(statusCode); }