/// <summary> /// Get a user in a principal context /// </summary> /// <param name="userName"></param> /// <param name="pc"></param> /// <returns></returns> private static UserPrincipal FindUser(string userName, PrincipalContext pc) { UserPrincipal user; PrincipalSearcher searcher; var parsedName = new FqdnNameParser(userName); user = new UserPrincipal(pc); user.SamAccountName = parsedName.SamAccountName; searcher = new PrincipalSearcher(user); user = searcher.FindOne() as UserPrincipal; return(user); }
/// <summary> /// Search a user hierarchicaly in the AD structure /// </summary> /// <param name="userName">The user name or identifier</param> /// <param name="ac">The principal context global configuration</param> /// <param name="pc">The principal context this user was found in</param> /// <returns></returns> private static UserPrincipal SearchUser(string userName, AccountManagementPrincipalContext ac, out PrincipalContext pc) { UserPrincipal user = null; var name = new FqdnNameParser(userName); if (name.ContextType == ContextType.Machine) { pc = BuildPrincipal(null); user = FindUser(userName, pc); if (user != null) { return(user); } pc.Dispose(); return(null); } // Probar sin OU pc = BuildPrincipal(ac); user = FindUser(userName, pc); if (user != null) { return(user); } pc.Dispose(); // Probar con OU pc = BuildPrincipalWithoutOu(ac); user = FindUser(userName, pc); if (user != null) { return(user); } pc.Dispose(); return(null); }
/// <summary> /// Get a group in a principal context /// </summary> /// <param name="groupName">The group name or identifier</param> /// <param name="pc">The principal context</param> /// <returns></returns> private static GroupPrincipal FindGroup(string groupName, PrincipalContext pc) { GroupPrincipal group; PrincipalSearcher searcher; var parsedName = new FqdnNameParser(groupName); // Search by SamGroupName if (!string.IsNullOrWhiteSpace(parsedName.SamAccountName)) { group = new GroupPrincipal(pc); group.SamAccountName = parsedName.SamAccountName; searcher = new PrincipalSearcher(group); group = searcher.FindOne() as GroupPrincipal; if (group != null) { return(group); } } // Search by name (original approach, backwards compatiblity) if (!string.IsNullOrWhiteSpace(parsedName.SamAccountName)) { group = new GroupPrincipal(pc); group.Name = parsedName.SamAccountName; searcher = new PrincipalSearcher(group); group = searcher.FindOne() as GroupPrincipal; if (group != null) { return(group); } } if (parsedName.Sid != null) { group = GroupPrincipal.FindByIdentity(pc, IdentityType.Sid, parsedName.Sid.ToString()); if (group != null) { return(group); } } return(null); }
/// <summary> /// Search for a group in diferent principal context in the following order: local, domain without OU, domain with OU /// </summary> /// <param name="groupName"></param> /// <param name="ac"></param> /// <param name="pc"></param> /// <returns></returns> private static GroupPrincipal SearchGroup(string groupName, AccountManagementPrincipalContext ac, out PrincipalContext pc) { var name = new FqdnNameParser(groupName); GroupPrincipal group = null; if (name.ContextType == ContextType.Machine) { pc = BuildPrincipal(null); group = FindGroup(groupName, pc); if (group != null) { return(group); } pc.Dispose(); return(null); } // Look in provided OU pc = BuildPrincipal(ac); group = FindGroup(groupName, pc); if (group != null) { return(group); } pc.Dispose(); // Look in domain pc = BuildPrincipalWithoutOu(ac); group = FindGroup(groupName, pc); if (group != null) { return(group); } pc.Dispose(); return(null); }
/// <summary> /// Create a user or return one if it does not exist. /// </summary> /// <param name="identity"></param> /// <param name="password"></param> /// <param name="displayName"></param> /// <param name="logger"></param> /// <param name="acp"></param> /// <returns></returns> public static UserPrincipal EnsureUserExists( string identity, string password, string displayName, ILoggerInterface logger, AccountManagementPrincipalContext acp) { var parsedUserName = new FqdnNameParser(identity); if (parsedUserName.UserPrincipalName.Length > 64) { throw new Exception($"Windows account userPrincipalName '{parsedUserName.UserPrincipalName}' cannot be longer than 64 characters."); } using (PrincipalContext pc = BuildPrincipal(acp)) { UserPrincipal up = FindUser(identity, pc); string samAccountName = parsedUserName.SamAccountName; logger.LogInfo(false, $"Ensure windows account exists '{samAccountName}@{password}' with userPrincipal '{identity}'"); if (up == null) { up = new UserPrincipal(pc, samAccountName, password, true); } else { logger.LogInfo(true, $"Found account IsAccountLockedOut={up.IsAccountLockedOut()}, SamAccountName={up.SamAccountName}"); // Make sure we have the latest password, just in case // the pwd algorithm generation changes... try { up.SetPassword(password); } catch (Exception e) { logger.LogWarning(true, "Cannot update password for account: " + e.Message + e.InnerException?.Message); } } up.UserCannotChangePassword = true; up.PasswordNeverExpires = true; up.Enabled = true; up.DisplayName = displayName; up.Description = parsedUserName.UserPrincipalName; // If we are in a domain, assign the user principal name if (pc.ContextType == ContextType.Domain) { logger.LogInfo(true, "Setting UserPrincipalName to '{0}'", parsedUserName.UserPrincipalName); up.UserPrincipalName = parsedUserName.UserPrincipalName + "@" + parsedUserName.DomainName.ToLower(); } if (up.IsAccountLockedOut()) { try { up.UnlockAccount(); } catch (Exception e) { logger.LogWarning(true, "Cannot unlock account: " + e.Message + e.InnerException?.Message); } } try { up.Save(); } catch (Exception e) { logger.LogException(new Exception("Error while saving user", e), EventLogEntryType.Warning); // Sometimes it crashes, but everything was OK (weird?) // so we check again if the user has been created Thread.Sleep(500); up = FindUser(identity, pc); if (up == null) { // Rethrow the original, whatever it was. ExceptionDispatchInfo.Capture(e).Throw(); } } return(up); } }