예제 #1
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);
                }
            }
        }