Thursday, May 28, 2009

Importing Users into Active Directory on Server 2008

I have recently been tasked with figuring out how to import a large number of users into Active Directory in our Server 2008 environment. Now, I know there are several options out there, and I'm sure someone will try and sell me something in the comments section, but I found a way to do it and it works. And best of all, it's free!

I am utilizing a few different things to accomplish this task: csvde (built into Windows Server), admod (a free utility available here), and a batch file. The data sources are two files: a CSV file with the user data, and a tab-delimited file with user passwords.

There is a site with great examples on how to do a basic import with csvde located here. From that page you will find several other links to more complicated examples, and more in-depth looks at the procedure.

First things first, we need to create a CSV file with the desired LDAP attributes. For my purposes, I decided on the following:
  • DN - Distinguished name in the directory (ex: CN=user,OU=employees,DC=domain,DC=com)
  • objectClass - Defines the type of object to create (ex: user)
  • name - The user's name -- equivalent to CN (ex: Joe Smith)
  • displayName - self explanatory (ex: Joe Smith)
  • userAccountControl - This one takes a little math, but a good explanation can be found here (ex: 514)
  • sAMAccountName - this is what shows up in the pre-Windows 2000 logon name field in ADUC (ex: jsmith)
  • mail - email address (ex:
  • givenName - the user's first name
  • sn - the user's last name
  • userPrincipalName - this defines the user's logon account (including domain) (ex:
Not all of these are necessarily required (though some are), so you may need to play around with the options to get it just right for your environment. Remember: the first line of your CSV file needs to be the attribute names.

Now, the one downside to csvde is that it does not take user passwords into account. So, if you have a domain policy that has a strict password policy, the import may fail. That's why, in my example, I chose the userAccountControl value of 514 (this defines the object as a normal user, but as a disabled account). Next, we'll need to define passwords. For this I created a separate text file (passwords.txt) that is a tab-delimited file that contains two values per row: the DN and the associated password. In a moment, you'll see why.

Since we now have our source files ready to go, we're good to import! For this I created a batch file that looks like the following:
@echo off
echo "Importing from CSV File"
csvde -i -v -k -f %1

echo "Setting Passwords and enabling accounts. Passwords never expire."
REM Loop through password file and update records
FOR /F "tokens=1,2 delims= " %%G IN (%2) DO (
admod -b %%G unicodepwd::%%H -kerbenc
admod -b %%G "userAccountControl::66048")

UPDATE: Apparently this Blog removes Tabs and replaces them with spaces. In the line "FOR /F "tokens=1,2 delims= " %%G IN (%2) DO (" above, there is actually a TAB in between "delims=" and the closing quotation mark. Be sure to remove the space and replace it with a Tab, by pressing the Tab key. Thanks to Jennifer for helping discover this!

This batch file takes two parameters: the first being the path to the csv source file and the second being the path to the tab-delimited password file. Now let's take a look at what we're doing here :)
In the first section we are bulk importing users with the following command:
csvde -i -v -k -f %1
The "i" option switches to import mode. "v" is verbose, "k" means to ignore common warnings and "f" means to use the file located by the following value. "%1" is just the way to specify the first command line argument to the batch file. When this command has completed, the users will be populated into Active Directory, but will be disabled and without a password.

Enter the next chunk:
FOR /F "tokens=1,2 delims= " %%G IN (%2) DO (
admod -b %%G unicodepwd::%%H -kerbenc
admod -b %%G "userAccountControl::66048")

This loops through the tab-delimeted file specified by the "%2" (second command line argument) and does two things. First:
admod -b %%G unicodepwd::%%H -kerbenc
This command modifies the object specified by the DN in the text file to have the associated password. The passwords are saved as plain text in the file.
And second:
admod -b %%G "userAccountControl::66048
This command modifies the object specified by the DN to update the user account control value. The value specified here enables the account (now that it has a valid password) and sets it so that the password never expires -- which was something just for our environment. Take another look at the control codes to set this value to whatever you need.

And that's it! Now you have an Active Directory populated with enabled users with valid passwords. If you have any questions about this process, feel free to leave a comment below.

*DISCLAIMER* Always do stuff like this in a test environment first. I in no way guarantee this will work for you in your environment, or that it won't completely break your directory -- so again, always test first!