Exemplo n.º 1
0
        private static void uniTest()
        {
            //using (var fs = new System.IO.StreamWriter(Path.Combine(HomeFolder, "cpr.txt"), false))
            //{
            //    fs.Write(cprContent);
            //    fs.Close();
            //}

            UserProperties userPropsFrom = new UserProperties()
            {
                { "L", new string[] { "Boston", "Tokio" } },
                { "facsimileTelephoneNumber", null }, // new string[]{"123"}
                { "mobile", new string[] { "7" } },
                { "memberOf", new string[] { "CN=Exchange Services,CN=Users,DC=egar,DC=egartech,DC=com", "CN=IIS_IUSRS,CN=Builtin,DC=kireev,DC=local" } },
                { "mail", new string[] { "123DfG123" } },
                { "userPrincipalName", new string[] { "123" } },
            };
            UserProperties userPropsTo = new UserProperties()
            {
                { "L", new string[] { "Boston" } },
                { "facsimileTelephoneNumber", new string[] { "456" } },
                { "userAccountControl", new string[] { Convert.ToString((uint)Utils.UserAccountControl.SMARTCARD_REQUIRED) } },
                { "mobile", new string[] { "4" } },
                { "memberOf", new string[] { "CN=Exchange Services,CN=Users,DC=egar,DC=egartech,DC=com", "CN=IIS_IUSRS,CN=Builtin,DC=kireev,DC=local" } },
            };

            string        transResult;
            ADHintElement adHint = ADHintsConfigurationSection.GetOUByAttributes(userPropsTo, userPropsFrom, out transResult);

            if (adHint != null)
            {
                var qualityCheck = adHint.QualityCheck(userPropsFrom);
                //var transResult = adHint.GetTransitionByUserAttributes(userPropsFrom, userPropsTo);
            }
        }
Exemplo n.º 2
0
        public CheckResult CheckDestOUsExists()
        {
            string errors = string.Empty;

            bool anySuccess = false;

            foreach (var server in configuration.DestADServers)
            {
                bool hasSuccessHintOU = false;
                log.LogDebug("check ADHints in " + server.ToString() + " ...");
                var msg = CheckOUExists(server, ADHintsConfigurationSection.GetAllOUs(), out hasSuccessHintOU);
                errors += (errors.Length > 0 ? Environment.NewLine : "") + msg; // some errors may be even if hasSuccessHintOU
                if (hasSuccessHintOU)
                {
                    anySuccess = true;
                    break; // one working server is enough
                }
            }
            if (!anySuccess)
            {
                return(CheckResult.FailWith("No valid DestOUs found in ADHintSettings." + Environment.NewLine + errors));
            }

            anySuccess = false;
            foreach (var server in configuration.SourceADServers)
            {
                log.LogDebug("check OUsDNToMonitor in " + server.ToString() + " ...");
                bool hasSuccessMonitor = configuration.OUsDNToMonitor.Count == 0;
                var  msg = CheckOUExists(server, configuration.OUsDNToMonitor.ToArray(), out hasSuccessMonitor);
                errors += (errors.Length > 0 ? Environment.NewLine : "") + msg; // some errors may be even if hasSuccessMonitor
                if (hasSuccessMonitor)
                {
                    anySuccess = true;
                    break; // one working server is enough
                }
            }
            if (!anySuccess)
            {
                return(CheckResult.FailWith("No valid OUs found in OUsDNToMonitorSettings." + Environment.NewLine + errors));
            }

            if (!string.IsNullOrEmpty(errors))
            {
                return(CheckResult.WarningWith("Errors occured while checking OUsDNToMonitorSettings:" + Environment.NewLine + errors));
            }

            return(CheckResult.Success);
        }
Exemplo n.º 3
0
 private static void CacheAllGroups()
 {
     foreach (var server in config.SourceADServers)
     {
         try
         {
             PollAD.GetGroupMembers(server, ADHintsConfigurationSection.GetAllGroupsFromConfig());
             return; // first available source AD
         }
         catch (Exception ex)
         {
             log.LogDebug("Failed to connect to " + server.ToString() + ": " + ex.Message);
         }
     }
     throw new Exception("No Source AD Servers available");
 }
Exemplo n.º 4
0
        private static void BackgroundPoll()
        {
            bool logVerbose = config.LogVerbose;

            //var accountToMonitor = config.SamAccountsToMonitor;
            //if (accountToMonitor.Count > 0)
            //    log.LogDebug("Monitoring only " + accountToMonitor.Count + " accounts: " + string.Join(";", accountToMonitor));

            if (oUsToMonitor.Count > 0)
            {
                log.LogDebug("Monitoring only " + oUsToMonitor.Count + " OU(s): " + string.Join(";", oUsToMonitor));
            }
            if (oUsDNToMonitor.Count > 0)
            {
                log.LogDebug("Monitoring only " + oUsDNToMonitor.Count + " OU(s) DNs: " + string.Join(";", oUsDNToMonitor));
            }

            // get attributes for replicate:
            var allAtributes = ADHintsConfigurationSection.GetAllAttributeNames();

            PollAD.AddSourcePropNames(allAtributes);
            PollAD.AddDestinationPropNames(allAtributes);

            PollAD.Log             = log;
            CCMApi.log             = log;
            CCMApi.interCcmSpacing = config.interCcmSpacing;

#if DEBUG
            uniTest();
#endif
            InitializeAllAccounts();

            while (true)
            {
                try
                {
                    if (!canWork)
                    {
                        break;
                    }

                    if (File.Exists(Path.Combine(HomeFolder, config.CCMCPRFile)))
                    {
                        cprContent = SettingsConfiguration.LoadCPRFile(Path.Combine(HomeFolder, config.CCMCPRFile));
                    }
                    else
                    {
                        cprContent = SettingsConfiguration.CPRFileContent;
                    }

                    PollAD ad      = GetAvailableAD(config.SourceADServers, lastHighUSNs, false);
                    bool   success = false;

                    if (ad == null)
                    {
                        log.LogError("Unable to connect to any AD Servers");
                    }
                    else
                    {
                        if (ad.ChangedUsersProperties.Count == 0)
                        {
                            success = true; // no changes
                        }
                        else
                        {
                            int cnt = ad.ChangedUsersProperties.Count;
                            //log.LogInfo("Found update for " + cnt + " user(s) in Source AD. Current USN = " + ad.CurrentHighUSN + ". InvocationID=" + ad.GetInvocationID);

                            FilterAccounts(ad.ChangedUsersProperties, config.DestADServers.Select(s => s.ServerUserName), oUsToMonitor, oUsDNToMonitor);
                            if (cnt - ad.ChangedUsersProperties.Count > 0)
                            {
                                log.LogInfo("Filtered out " + (cnt - ad.ChangedUsersProperties.Count) + " accounts");
                            }

                            if (ad.ChangedUsersProperties.Count == 0)
                            {
                                success = true; // no changes
                            }
                            else if (0 != PutToDestinationAD(config.DestADServers, ad.ChangedUsersProperties, false))
                            {
                                success = true; // saved to Dest AD
                            }
                            //  if at least 1 user is succeeded then assume that whole iteration is succeeded
                            //  If all users are failed than seems to be CCM or AD is down and iteration should run again.
                        }

                        // if iteration is secceeded and highUSN is changed than save it to DB
                        if (success && (!lastHighUSNs.ContainsKey(ad.GetInvocationID) || lastHighUSNs[ad.GetInvocationID] != ad.CurrentHighUSN))
                        {
                            lastHighUSNs[ad.GetInvocationID] = ad.CurrentHighUSN;
                            // SaveCurrentHighUSN(ad.GetInvocationID, ad.CurrentHighUSN);
                        }
                    }
                    if (initializationFails.Count > 0)
                    {
                        log.LogInfo("Process " + initializationFails.Count + " accounts which failed on startup ...");
                        PutToDestinationAD(config.DestADServers, initializationFails.Values.ToList(), false);
                    }
                }
                catch (Exception ex)
                {
                    log.LogError(ex, "BackgroundPoll");
                }
                finally
                {
                    stopEvent.WaitOne(config.PoolsInterval * 1000); // each 2 sec
                }
            }
        }
Exemplo n.º 5
0
        private static void InitializeAllAccounts()
        {
            CacheAllGroups();

            log.LogInfo("Initialize accounts ...");
            PollAD adSource = GetAvailableAD(config.SourceADServers, lastHighUSNs, true);
            PollAD adDest   = GetAvailableAD(config.DestADServers, lastHighUSNs, true);

            lastHighUSNs[adSource.GetInvocationID] = adSource.CurrentHighUSN;

            try
            {
                IDictionary <string, UserProperties> userByObjectSID  = new Dictionary <string, UserProperties>(adDest.ChangedUsersProperties.Count);
                IDictionary <string, UserProperties> userBySamAccount = new Dictionary <string, UserProperties>(adDest.ChangedUsersProperties.Count);
                log.LogInfo("Loaded " + adSource.ChangedUsersProperties.Count + " accounts from SourceAD " + adSource.DnsHostName + " and " + adDest.ChangedUsersProperties.Count + " accounts from Destination AD " + adDest.DnsHostName);
                foreach (var userProps in adDest.ChangedUsersProperties)
                {
                    userProps.Remove("ObjectSID");
                    if (userProps.ContainsKey("Pager") && userProps["Pager"] != null)
                    {
                        userByObjectSID[userProps["Pager"][0]] = userProps;
                    }
                    userBySamAccount[userProps["samAccountName"][0]] = userProps;
                }

                log.LogDebug("  " + userByObjectSID.Count + " users has initialized ObjectSID in DestAD");
                var changedUsers = new List <UserProperties>();

                var cnt = adSource.ChangedUsersProperties.Count;
                FilterAccounts(adSource.ChangedUsersProperties, config.DestADServers.Select(s => s.ServerUserName), oUsToMonitor, oUsDNToMonitor);
                if (cnt - adSource.ChangedUsersProperties.Count > 0)
                {
                    log.LogInfo("Filtered out " + (cnt - adSource.ChangedUsersProperties.Count) + " accounts");
                }

                // Compare Source and Destination users ...
                foreach (var userProps in adSource.ChangedUsersProperties)
                {
                    UserProperties destUser = null;
                    if (!userByObjectSID.TryGetValue(userProps["ObjectSID"][0], out destUser) || destUser == null)
                    {
                        userBySamAccount.TryGetValue(userProps["samAccountName"][0], out destUser);
                    }

                    if (destUser == null) // not found by SID nor samAccountName
                    {
                        log.LogDebug("  '" + userProps["samAccountName"][0] + "' is new user");
                        changedUsers.Add(userProps); // new user
                    }
                    else
                    {
                        ADHintElement adHint = null;
                        try
                        {
                            string notUsed;
                            adHint = ADHintsConfigurationSection.GetOUByAttributes(userProps, destUser, out notUsed);
                        }
                        catch (Exception)
                        {
                        }

                        // {[distinguishedName, CN=user3. sdfsdf,OU=Office31,OU=Office3,OU=Domain Controllers,DC=kireev,DC=local]}
                        // simple way to determine if OU is changed
                        if (adHint != null && destUser["distinguishedName"][0].IndexOf(adHint.DestOU, StringComparison.OrdinalIgnoreCase) < 0)
                        {
                            log.LogDebug("  '" + destUser["distinguishedName"][0] + "' need to move to " + adHint.DestOU);
                            changedUsers.Add(userProps); //  OU is changed
                        }
                        else
                        {
                            foreach (var prop in userProps)
                            {
                                string[] destPropVal;
                                if (!PollAD.propIgnoreDest.Contains(prop.Key) &&
                                    destUser.TryGetValue(prop.Key, out destPropVal) && prop.Value != null && !Utils.CheckEquals(prop.Value, destPropVal))
                                {
                                    log.LogDebug("  '" + userProps["samAccountName"][0] + "' changed [" + prop.Key + "]='" + Utils.PropVal(destPropVal) + "' -> '" + Utils.PropVal(prop.Value) + "'");
                                    changedUsers.Add(userProps);
                                    break;
                                }
                            }
                        }
                    }
                }

                if (changedUsers.Count == 0)
                {
                    log.LogInfo("Initialization complete. No differences between SourceAD and DestinationAD found.");
                }
                else
                {
                    log.LogInfo("Need to update " + changedUsers.Count + " accounts...");
                    var updatedCnt = PutToDestinationAD(config.DestADServers, changedUsers, true);
                    log.LogInfo("Initialization complete. Successfully updated " + updatedCnt + " of " + changedUsers.Count + " accounts.");
                }
            }
            catch (Exception ex)
            {
                log.LogError(ex, "Failed to Initialize: " + ex.Message);
                return;
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Add or Update user in Destination AD
        /// return: 0  - succesfully updated
        ///         1  - succesfully updated and changedImportantProps
        ///         -1 - error
        /// </summary>
        public static int AddUser(ADServer server, UserProperties newProps, string cprContent, ADServer[] serversToWait)
        {
            // props["userPrincipalName"], props["displayName"], props["givenName"], props["sn"], props["mail"], props["initials"], props["objectSID"]
            string samAccountName    = newProps["samAccountName"][0];
            string oldSamAccountName = null;
            bool   isNewUser         = false;

            //bool isChangedOU = false;

            using (DirectoryEntry searchOU = new DirectoryEntry(server.path, server.ServerUserName, server.ServerPassword, server.authTypes))
            {
                DirectoryEntry oldUser = LoadUserByObjectSID(searchOU, newProps["objectSID"][0], samAccountName);

                UserProperties oldProps = null;
                if (oldUser != null)
                {
                    oldProps          = GetUserProperties(oldUser);
                    oldSamAccountName = (string)oldUser.Properties["samAccountName"].Value;
                }
                isNewUser = oldUser == null;

                string transResult;
                var    adHint = ADHintsConfigurationSection.GetOUByAttributes(newProps, oldProps, out transResult);
                if (adHint == null)
                {
                    var messageHint = "ADHint is not found for user " + quote(samAccountName) + ". Attributes:" + PrintAttributes(newProps);
                    messageHint += ADHintsConfigurationSection.PrintMemberOfAttributes(newProps.GetPropValue("memberOf"));

                    if (Settings.Default.DataMismatchLogging)
                    {
                        log.LogWarn(messageHint);
                    }
                    else
                    {
                        log.LogDebug(messageHint);
                    }
                    return(0);
                }

                var qualityCheck = adHint.QualityCheck(newProps);
                if (qualityCheck.Count > 0)
                {
                    log.LogError("QualityCheck validation fails for user '" + samAccountName + "' with attributes:" + Environment.NewLine + string.Join(Environment.NewLine, qualityCheck.ToArray()));
                    return(15);
                }

                // Process ...
                if (adHint.Type == ADHintElement.AdHintType.Terminate)
                {
                    return(CCMApi.Terminate(oldSamAccountName));     // return 0 if success
                }
                string destPath = server.path + "/" + adHint.DestOU; // ="LDAP://myServ.local:636/OU=Office21,OU=Office2,OU=Domain Controllers,DC=myServ,DC=local"

                using (var destOU = new DirectoryEntry(destPath, server.ServerUserName, server.ServerPassword, server.authTypes))
                {
                    string changedImportantProps = transResult;
                    string changedAllProps       = "";
                    string msg = " '" + samAccountName + "' . HintNum=" + adHint.Num + ". " + adHint.Type + ". ";
                    if (isNewUser) // new user
                    {
                        //log.LogInfo(" '" + samAccountName + "' . HintNum=" + adHint.Num + ". New user in '" + destOU.Path + "'" + (server.SSL ? "(SSL)" : "(not SSL)") + " ...");
                        msg    += "Add user into '" + destOU.Path + "'" + (server.SSL ? "(SSL)" : "(not SSL)");
                        oldUser = destOU.Children.Add("CN=" + samAccountName, "user");
                    }
                    else
                    {
                        // check if OU is changed for user
                        if (!oldUser.Parent.Path.Equals(destOU.Path, StringComparison.OrdinalIgnoreCase))
                        {
                            //log.LogInfo(" '" + samAccountName + "' move from '" + oldUser.Parent.Path + "' -> '" + destOU.Path + "' " + (server.SSL ? "(SSL)" : "(not SSL)") + ". HintNum=" + adHint.Num + " ...");
                            msg += "Move from '" + oldUser.Parent.Path + "' -> '" + destOU.Path + "' " + (server.SSL ? "(SSL)" : "(not SSL)");
                            oldUser.MoveTo(destOU);
                            changedAllProps += "OU;";
                        }
                        else
                        {
                            //log.LogInfo(" '" + samAccountName + "' update in OU '" + destOU.Path + "' " + (server.SSL ? "(SSL)" : "(not SSL)") + ". HintNum=" + adHint.Num + " ...");
                            msg += "Update in OU '" + destOU.Path + "' " + (server.SSL ? "(SSL)" : "(not SSL)");
                        }
                    }

                    changedImportantProps += CheckAndSetProperty(oldUser.Properties, "samAccountName", new string[] { samAccountName }); // AD key

                    changedAllProps += SetPropertiesToUser(oldUser, newProps);
                    changedAllProps += CheckAndSetProperty(oldUser.Properties, "Pager", newProps["objectSID"]); // the surrogate key

                    bool terminate = !isNewUser && changedImportantProps.Length > 0;
                    if (terminate)
                    {
                        log.LogInfo(msg + ". Terminating. Changed attributes: " + Environment.NewLine + changedAllProps + Environment.NewLine + changedImportantProps);
                        CCMApi.Terminate(oldSamAccountName);
                    }
                    else if (!isNewUser && string.IsNullOrEmpty(changedAllProps) && string.IsNullOrEmpty(changedImportantProps))
                    {
                        log.LogDebug("No attributes changed. Skip updating.");
                        return(0); // skip to commit
                    }
                    else
                    {
                        log.LogInfo(msg + "Changed attributes: " + Environment.NewLine + changedAllProps + Environment.NewLine + changedImportantProps);
                    }

                    if (!terminate && CCMApi.IsActive(samAccountName) != 0)
                    {
                        return(-1); // card is already active
                    }
                    oldUser.Properties["userAccountControl"].Value = Utils.UserAccountControl.NORMAL_ACCOUNT | Utils.UserAccountControl.ACCOUNTDISABLE | Utils.UserAccountControl.PWD_NOTREQD;

                    //Console.WriteLine("  CommitChanges '" + samAccountName + "' ...");
                    oldUser.CommitChanges();

                    if (isNewUser)
                    {
                        WaitDestinationADReplication(samAccountName, newProps["objectSID"][0], serversToWait);
                    }

                    // Dest AD is commited.
                    // Process CCM ....

                    if (Settings.Default.CCMHost.Trim().Length == 0)
                    {
                        log.LogWarn("CCMHost is not set. Skip CCM processing");
                        return(0);
                    }

                    int ccmResult;
                    try
                    {
                        ccmResult = CCMApi.CreateCPR(samAccountName, cprContent, adHint.CardPolicy); // return 0 if success
                    }
                    catch (Exception ex)
                    {
                        log.LogError(ex, "update user '" + samAccountName + "' in CCM: " + ex.Message);
                        return(-1);
                    }

                    if (ccmResult != 0)
                    {
                        // Rollback AD ...
                        if (oldProps == null) // if created then delete
                        {
                            destOU.Children.Remove(oldUser);
                            destOU.CommitChanges();
                        }
                        else
                        {
                            SetPropertiesToUser(oldUser, oldProps); // return to oldProps
                            oldUser.CommitChanges();
                        }
                        log.LogWarn2("Rollback processed in AD for account '" + samAccountName + "' due to CCM error " + ccmResult + ". " + (oldProps == null ? "Account deleted in DestinationAD" : "Account attributes restored in DestinationAD"));
                        return(-1);
                    }
                    return(ccmResult);
                }
            }
        }