Summary: Guest blogger, Gary Jackson, shares a technique to automate Active Directory accounts.
Microsoft Scripting Guy, Ed Wilson, is here. I met Gary Jackson at the Windows PowerShell Summit in April. We talked about some cool things he has been working on, so I invited him to write a guest blog post. First a little about Gary…
I am currently a senior database administrator in the healthcare field in Dallas, Texas. I started in the IT industry in 1983 with the Apple IIe. Over the years I’ve managed various systems from OpenVMS, Windows, UNIX, to Netware. Scripting has always been a big part of my daily life because I’m too lazy to do real work. My motto is, “Let the computer do the work.” I was introduced to Windows PowerShell (Monad at the time) in 2005, but I didn’t use it much until Windows PowerShell 2.0. At that point, I made the switch from VBScript to Windows PowerShell.
Creating Active Directory accounts is one of the job duties that most people in IT hate or strongly dislike. And if you’re one of the unlucky IT shops that doesn’t have a provisioning tool, I’d suggest using Windows PowerShell to automate the process. That is what I decided to do about five years ago.
To be effective, the script had to:
- Create the mailbox (requires the Microsoft.Exchange.Management.PowerShell.Admin add-in) and the Active Directory account.
- Place each mailbox in the appropriate storage group, based on the first initial of the user’s last name.
- Place each Active Directory account in the appropriate organizational unit, based on the user’s department.
- Create a shared home folder for each user.
- Apply appropriate group membership for each account.
- Set appropriate permissions for each home folder.
- Send an email to the Help Desk to notify them about the account status.
To further automate this process, I had one of our programmers create a hook into the Lawson HR system that would append each new user into a .csv file that my script would then parse to create the new Active Directory account.
User accounts are stored in departmental organizational units with template accounts. The template accounts are used for copying the correct group membership to each user account and for setting the ParentDN so that the new account is placed in the appropriate organizational unit.
By using the Exchange Server module for Windows PowerShell, the following command will create the user mailbox and Active Directory account, and place each mailbox in the appropriate storage group.
Import-Csv \\acmeweb02\c$\employees.csv |
foreach {
$name=$_.name
$alias=$_.alias
$user=$alias
$userprincipalname="$alias@acme.org"
$EmpID=$_.EmpID
$Title=$_.title
$Dept=$_.department
$LastNameInit=$_.Lastname
$LastNameInit=$LastNameInit.substring(0,1)
$DeptNumber=$_.DeptNumber
$suffix="TEMPLATE"
$tmplateUser="$DeptNumber$suffix"
$templateDN=get-qaduser-includedproperties parentContainerDN $tmplateUser | Select–ExpandProperty parentContainerDN
switch -regex ($LastNameInit)
{
"[A]" {$Database="ACMEMX02\6th Storage Group\A Mailboxes"}
"[B]" {$Database="ACMEMX02\7th Storage Group\B Mailboxes"}
"[E]" {$Database="ACMEMX02\10th Storage Group\E Mailboxes"}
"[F]" {$Database="ACMEMX02\11th Storage Group\F Mailboxes"}
"[G]" {$Database="ACMEMX02\12th Storage Group\G Mailboxes"}
"[S]" {$Database="ACMEMX02\13th Storage Group\S Mailboxes"}
"[T]" {$Database="ACMEMX02\14th Storage Group\T Mailboxes"}
"[U-V]" {$Database="ACMEMX02\15th Storage Group\U-V Mailboxes"}
"[W-Z]" {$Database="ACMEMX02\16th Storage Group\W-Z Mailboxes"}
"[H]" {$Database="ACMEMX02\17th Storage Group\H Mailboxes"}
"[I-K]" {$Database="ACMEMX02\18th Storage Group\I-K Mailboxes"}
"[L]" {$Database="ACMEMX02\19th Storage Group\L Mailboxes"}
"[M]" {$Database="ACMEMX02\20th Storage Group\M Mailboxes"}
"[N-O]" {$Database="ACMEMX02\21st Storage Group\N-O Mailboxes"}
"[P-Q]" {$Database="ACMEMX02\22nd Storage Group\P-Q Mailboxes"}
"[C]" {$Database="ACMEMX02\8th Storage Group\C Mailboxes"}
"[D]" {$Database="ACMEMX02\9th Storage Group\D Mailboxes"}
"[R]" {$Database="ACMEMX02\23rd Storage Group\R Mailboxes"}
}
new-mailbox -name $name -alias $alias -Firstname $_.Firstname -LastName $_.Lastname -userPrincipalName $userprincipalname `
-database $Database -OrganizationalUnit $templateDN -Password $Password
The following function is used to create the home shared folders:
function CreateHomeDir
{
Param([string]$user)
$homepath="f:\Users\$user"
$shareName="$user$"
$Type=0
$pathToShare="\\acmenet01\f$\Users\$user"
New-Item -type directory -path $pathToShare|Out-Null
$WMI=[wmiClass]"\\acmenet01\root\cimV2:Win32_Share"
$WMI.Create($homepath,$shareName,$Type)|Out-Null
}
As mentioned earlier, each departmental organizational unit contains a template account with the appropriate security group membership for that department. We use the template account to copy the group membership to the newly created user account. I use the Quest Active Directory tools (the Quest.ActiveRoles.ADManagement add-in), but the script can be easily modified to use the Active Directory module. The function is shown here:
function set-Attributes
{
Param(
[string]$user,
[string]$tmplateUser
)
AddToCompanyWideGroup -user $user
$groups=get-qaduser $tmplateUser | select-ExpandProperty memberof
foreach ($Group In $groups)
{
add-qadgroupmember-identity $Group -member $user
}
$arrAttrs="department"
$FirstName=$_.Firstname
$LastName=$_.Lastname
$displayName="$FirstName $LastName"
$State="TX"
$Country="United States"
$CountryAbbr="US"
$CountryCode="840"
$Company="Acme Corporation"
$ScriptPath="ACMELOG"
$HomeDrivePath="\\acmenet01\$user$"
$HomeDrive="U:"
$user.st=$State
$user.scriptpath=$ScriptPath
$user.company=$Company
$user.pwdLastSet=0
$user.countryCode=$CountryCode
$user.co=$Country
$user.c=$CountryAbbr
$user.employeeID=$EmpID
$user.title=$Title
$user.displayName=$displayName
$user.SetInfo()
$user.homeDrive=$HomeDrive
$user.homeDirectory=$HomeDrivePath
foreach ($Arr In $arrAttrs)
{
$updatedAttr=$UserToCopy.Get($Arr)
$user.Put($Arr,$updatedAttr)
}
$user.SetInfo()
$user.physicalDeliveryOfficeName=$user.department
$user.description=$user.title
$user.SetInfo()
}
Now we need to set the appropriate permission for the home folder.
function SetSharePerm
{
Param([string]$user)
$shareName="\\acmenet01\$user$"
$userName="acme\$user"
$SUBINACL='c:\subinacl.exe'
&$SUBINACL /Share $shareName /grant="acme\Domain Admins"=F /grant=$userName=C |Out-Null
}
Finally, we will send an email to the Help Desk to notify them that the accounts have been created.
function mailit {
Param(
[string]$user,
[string]$FirstName,
[string]$LastName
)
$EmailList="helpdesk@acme.org"
$MailMessage= @{
To=$EmailList
From="DONOTREPLY@acme.org"
Subject="NEW USER ACCorganizational unitNT"
Body="A new user account has been created. Initial login information listed below: `n
First name: $FirstName
Last name: $LastName
Userid: $user
Password: letmein
Thank You."
SmtpServer="smtp.acme.org"
ErrorAction="Stop"
}
Send-MailMessage @MailMessage
}
That’s all it takes. The script can be scheduled to run once a night, making Active Directory account creation totally hands free.
Automating this process gives us time to do more challenging and exciting work—like writing new Windows PowerShell scripts.
The full script can be downloaded from the Script Center Repository: PowerShell: Create AD Users from CSV File.
~Gary
Thanks for sharing your time and knowledge, Gary.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy