Anders G. Nordby

Lead Consultant at Itera

Creating AD users from code and adding them to a group

In my current project, I had to provide a crude admin interface for adding, editing and deleting users in an ActiveDirectory. Creating, deleting and editing users work fine. Finding users and groups also worked perfectly. But adding users to a group failed. I tried a lot of various ways to do this, and kept getting the error message “Information about the domain could not be retrieved (1355)”.

Finally I found this helpful blogpost:

 

Here is a portion of my finished code:

using System;
using System.Configuration;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
using System.Globalization;
using System.Web.UI.WebControls;

namespace MyNamespace
{
    public struct GlobalNames
    {
        public struct AppSettings
        {
            public struct AdAdmin
            {
                public const string Domain = "AdAdmin.Domain";
                public const string Ou = "AdAdmin.Ou";
                public const string UserName = "AdAdmin.UserName";
                public const string PassWord = "AdAdmin.PassWord";
                public const string RegexMobilePattern = "AdAdmin.RegexMobilePattern";
                public const string SomeImportantGroup= "AdAdmin.SomeImportantGroup";
            }
        }
    }

    public class AdAdmin
    {
        private static PrincipalContext GetContext()
        {
            var adDomain = ConfigurationManager.AppSettings[GlobalNames.AppSettings.AdAdmin.Domain];
            var adOu = ConfigurationManager.AppSettings[GlobalNames.AppSettings.AdAdmin.Ou];
            var adUsername = ConfigurationManager.AppSettings[GlobalNames.AppSettings.AdAdmin.UserName];
            var adPassword = ConfigurationManager.AppSettings[GlobalNames.AppSettings.AdAdmin.PassWord];

            return new PrincipalContext(ContextType.Domain, adDomain, adOu, adUsername, adPassword);
        }

        public void ResetPassword(DirectoryEntry entry, string password)
        {
            entry.Invoke("SetPassword", new object[] { password });
            entry.Properties["LockOutTime"].Value = 0;
        }

        private static string GetMessage(Exception ex)
        {
            var message = ex.Message;
            if (message == "Exception has been thrown by the target of an invocation." && ex.InnerException != null)
                message = ex.InnerException.Message;

            return message;
        }

        private static void SetUserProperty(DirectoryEntry entry, string property, string value)
        {
            entry.Properties[property].Value = value;
        }

        private void CreateNewUser(PrincipalContext context, string userName, string givenname, string surname, string password, Label outputLabel)
        {
            using (var userPrincipal = new UserPrincipal(context))
            {
                userPrincipal.SamAccountName = userName;
                userPrincipal.Enabled = true;
                userPrincipal.Save();

                var newUser = userPrincipal.GetUnderlyingObject() as DirectoryEntry;
                if (newUser == null)
                    return;

                SetUserProperty(newUser, "sAmAccountName", userName);
                SetUserProperty(newUser, "givenName", givenname);
                SetUserProperty(newUser, "sn", surname);

                WriteMessage(outputLabel, string.Format("Created user: '{0},{1},{2}'", userName, givenname, surname));
                newUser.CommitChanges();

                try
                {
                    ResetPassword(newUser, password);
                    newUser.CommitChanges();
                }
                catch (Exception ex)
                {
                    WriteMessage(outputLabel, string.Format("ERROR while setting password: {0}", GetMessage(ex)));
                }

                try
                {
                    var someImportantGroup= ConfigurationManager.AppSettings[GlobalNames.AppSettings.AdAdmin.SomeImportantGroup];

                    var group = GroupPrincipal.FindByIdentity(context, someImportantGroup);
                    if (group != null)
                    {
                        var user = UserPrincipal.FindByIdentity(context, userName);
                        if (user != null)
                        {
                            string userSid = string.Format("<SID={0}>", ToSidString(userPrincipal));
                            var groupDirectoryEntry = (DirectoryEntry)group.GetUnderlyingObject();
                            groupDirectoryEntry.Properties["member"].Add(userSid);
                            groupDirectoryEntry.CommitChanges();
                        }
                        else
                        {
                            WriteMessage(outputLabel, string.Format("ERROR: User '{0}' not found.", userName));
                        }
                    }
                    else
                    {
                        WriteMessage(outputLabel, string.Format("ERROR: Group '{0}' not found.", someImportantGroup));
                    }
                }
                catch (Exception ex)
                {
                    WriteMessage(outputLabel, string.Format("ERROR during assignment to group: '{0}'", GetMessage(ex)));
                }

                newUser.Close();
            }
        }

        public static string ToSidString(Principal principal)
        {
            if (null == principal)
                throw new ArgumentNullException("principal");

            var sid = principal.Sid;
            if (null == sid || 0 == sid.BinaryLength)
                return null;

            var buffer = new byte[sid.BinaryLength];
            sid.GetBinaryForm(buffer, 0);
            var hexBytes = Array.ConvertAll(buffer, b => b.ToString("X2", NumberFormatInfo.InvariantInfo));
            return string.Concat(hexBytes);
        }

        private static void WriteMessage(Label label, string text)
        {
            if (string.IsNullOrEmpty(label.Text))
            {
                label.Visible = true;
                label.Text = text;
            }
            else
            {
                label.Text += string.Format("<br />{0}", text);
            }
        }
    }
}

My AppSettings look something like this:

  <appSettings>
    <add key="AdAdmin.Domain" value="the.ad.domain" />
    <add key="AdAdmin.Ou" value="OU=ouForServiceAccount,DC=dcForServiceAccount,DC=local" />
    <add key="AdAdmin.UserName" value="ServiceAccountUserName" />
    <add key="AdAdmin.PassWord" value="ServiceAccountPassword" />
    <add key="AdAdmin.SomeImportantGroup" value="CN=SomeImportantGroup,OU=ouForSomeImportantGroup,DC=dcForSomeImportantGroup,DC=local" />
  </appSettings>

Note 1: I normally place the keys for my appsettings, querystring, etc in a separate file called GlobalNames.cs, which avoids spelling errors and also makes it easy to see what appsettings I have available in my project.
Note 2: The code calling CreateNewUser is only available after checking that there is no existing user with that username. You’ll probably need this check somewhere in your code.

Advertisements

One response to “Creating AD users from code and adding them to a group

  1. Anders G. Nordby 2013-02-14 at 15:36

    Some refactoring…

    private static List MemberOf(DirectoryEntry entry)
    {
    var retval = new List();
    var memberOf = entry.Properties[“memberOf”];
    if (memberOf != null && memberOf.Value != null)
    {
    if (memberOf.Value.GetType() == typeof (object[])) // member of several groups
    retval.AddRange(from g in (object[]) memberOf.Value select g.ToString());
    else
    retval.Add(memberOf.Value.ToString()); // member of single group
    }

    return retval;
    }

    private static void AddUserToGroup(UserPrincipal user, GroupPrincipal group)
    {
    if (user == null || group == null)
    return;

    var groups = MemberOf((DirectoryEntry)user.GetUnderlyingObject());
    if (groups.Contains(group.DistinguishedName))
    return;

    string userSid = string.Format(“”, ToSidString(user));
    var groupDirectoryEntry = (DirectoryEntry)group.GetUnderlyingObject();
    groupDirectoryEntry.Properties[“member”].Add(userSid);
    groupDirectoryEntry.CommitChanges();
    }

    private static void RemoveUserFromGroup(UserPrincipal user, GroupPrincipal group)
    {
    if (user == null || group == null)
    return;

    var groups = MemberOf((DirectoryEntry)user.GetUnderlyingObject());
    if (!groups.Contains(group.DistinguishedName))
    return;

    string userSid = string.Format(“”, ToSidString(user));
    var groupDirectoryEntry = (DirectoryEntry)group.GetUnderlyingObject();
    groupDirectoryEntry.Properties[“member”].Remove(userSid);
    groupDirectoryEntry.CommitChanges();
    }

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: