The Surly Admin

Father, husband, IT Pro, cancer survivor

New User Automation – Part 1

I think just about every Windows Administrator takes a look at new user automation, and frankly in Windows 2003 rarely did more then look.  With the “Copy” feature in Active Directory Users and Computers (ADUC) and the Exchange 2003 plug-ins to ADUC you could pretty much do everything you wanted from one Window.  But with Exchange 2007 Microsoft decided to “improve” things and make the process 2 steps instead of one.  Suddenly doing things in scripting started making a lot more sense.  Here’s my take on it.

Background

First thing to decide, as with any script, is what exactly we want to accomplish.  I wanted to make a nice easy script that would create my users, set the mailbox and let me know the results.  My new user process uses a combination of Sharepoint and Spiceworks.  The way I did this was I created a custom list in Sharepoint and gave my HR department access to the list.  I then logged into Sharepoint using my Help Desk user ID and configured the Sharepoint list to notify me whenever something was put in new in the list.  Sharepoint will then email my help desk ID and automatically generate a ticket in Spiceworks.  Since I have a ticket # in Spiceworks already I wanted my script update the existing ticket.

Getting the Information

The first challenge is getting the user information we need.  Well, it turns out if you’re copying an existing user there’s not actually a lot of information that you need.  Honestly, we can get away with 4 pieces of information.  First name, last name, user we’re copying and the Spiceworks ticket #.  If your company is like mine, then there’s pretty much a job title for every user so you’ll probably need that too, but for now we’ll concentrate on the big 4.

Normally I like to just put these in parameters and put any user prompting I need in there (using Read-Host).  And while you can specify everything in parameters I also decided to put some user friendliness in here and that meant removing the default parameters out of the PARAM section and doing it manually.  This way I could clear the screen, put a nice little header in there and prompt the user for each parameter that wasn’t specified when the script was initially run.

Param (
[string]$FirstName,
[string]$LastName,
[string]$LikeUN,
[string]$Ticket,
[string]$UPN = "@surlyadmin.corp",
[string]$NTDomain = "surlyadmin",
[string]$ExchangeServer = "exchangeservername",
[string]$EmailDomain = "@thesurlyadmin.com",
[string]$SWEmail = "helpdesk@thesurlyadmin.com",
[string]$From = "Admin@thesurlyadmin.com",
[string]$SMTPServer = "relay.surlyadmin.corp"
)
cls
Write-Host "********************************************************************"
Write-Host "**            SeraCare New User Creation Script                   **"
Write-Host "********************************************************************"
If ($FirstName -eq "")
{ $FirstName = (Read-Host "First Name")
}
If ($LastName -eq "")
{ $LastName = (Read-Host "Last Name")
}
If ($LikeUN -eq "")
{ $LikeUN = (Read-Host "Security 'like' User Name")
}
If ($Ticket -eq "")
{ $Ticket = (Read-Host "Spiceworks Ticket #")
}
Write-Host "`nFirst Name:`t`t$FirstName"
Write-Host "Last Name:`t`t$LastName"
Write-Host "Security 'Like':`t$LikeUN"
Write-Host "Spiceworks Ticket:`t$Ticket`n"
$Answer = Read-Host "Is this the information you want to use (y/N)"
If ($Answer.ToUpper() -ne "Y")
{ Write-Host "`n`nOK.  Please rerun the script and reenter the data correctly.`n"
Break
}

Pretty straight forward stuff, and you’ll see in the Parameters section that there’s a lot of information in there that we need.  This is all needed for the user creation steps, and the emailing of the information to Spiceworks.

UPN: User Principal Name – which is simply the username plus your domain name in the @domain.name format.
NTDomain: NT domain name, nothing too exciting
EmailDomain: Just the last bit of your email domain.  I could extract this out of the “like” user, but it’s easier to just specify it here.

Then the last little bit just redisplay’s what you’ve entered and gives you a chance to exit out if it’s not right.

Veryify the Username’s

So we now have the first name, last name and username of the user we want to copy.  Now we need to verify that this will work for us.  At my company we use first initial and last name for user names.  So let’s check and make sure that user name does not already exist.  If it does exist we’re going to prompt you to manually put the name in and then we’re going to check again and loop to infinity until you give it what it wants.

$TempUN = $FirstName.SubString(0,1)+$LastName
Do {
$User = $null
Write-Host "If you see an error message here, that's ok..."
$User = Get-ADUser $TempUN -ErrorAction SilentlyContinue
If ($User)
{ Write-Host "Username: $TempUN already exists"
$TempUN = (Read-Host "Enter user name manually")
}
Else
{ $UserName = $TempUN
}
} Until ($UserName -ne $null)

$TempDN is where we construct the user name, then use Get-ADUser to see if that user already exists.  If we get a $null return, we’re happy and will exit out of the DO loop.

Next, we essentially want to do the same thing for the “like” user but this time we’re looking for a positive return instead of a $null.

$TempUN = $LikeUN
Do {
$User = $null
Write-Host "If you see an error message here, that's ok..."
$User = Get-ADUser $TempUN -ErrorAction SilentlyContinue
If (-not ($User))
{ Write-Host "Username: $TempUN doesn't exist"
$TempUN = (Read-Host "Enter user name manually")
}
Else
{ $LikeUserName = $TempUN
}
} Until ($LikeUserName -ne $null)

As you can see, the code is almost identical except for what IF clause, where we’re looking for a $null and prompting for the user name manually and doing the same infinity loop until we get good information.  I really thought about making this into a function, but since these only appear the 2 times, and each one is subtly different from the other it just seemed like more work to get the functions working then anything I might save.

Copying a User

I have used this method for years in AD.  One of the fields in my custom list in Sharepoint is what user’s security should the new user mimic.  Then simply copy that user and get all of their group information, title, department, whatever is in there.  Turns out Powershell has this ability too (kinda), here’s the syntax:

Get-ADUser mimicuser | New-ADUser -Givenname "New" -SurName "User" ...all the other parameters...

But this turned out to be pretty inadequate, and in retrospect it makes sense.  If you were to run this command you’d get a new user with pretty much nothing copied from the original user!  Why?  Get-ADUser recalls only the default parameters and these are pretty limited, and the ones it does recall are all unique (mostly) to the user so nothing much is done.  If you use the -Properties parameter and specify all the properties you want to copy, it will work.

Still had some problems though.  When creating a new user you have to specify what OU you want to put the user account in and the copy method above doesn’t do this either.  Luckily, the information is all in the user object of the user we’re copying.  The distinguished name of the user account has their user name, and the rest of the name is the OU information we want.  But how to extract just that information?  I decided to use a little string manipulation for this.  We know that the FQDN of a user is composed of CN=username,OU=organization unit,OU=another OU,DC=domain,DC=name.  Notice the first OU= actually begins the information we need to extract out of the string.  So locate the first OU= and keep the rest of the string.  The first problem with this theory is that the distinguishedName property of a user object is not actually a string, so SubString and the other string manipulation methods aren’t available to us.  So first we have to convert it to a string using Out-String.  Next I decided to use “IndexOf” as it will locate the location of the phrase we indicate (OU=) then we can use SubString to extract what we need.

$LikeUN = $LikeUser.DistinguishedName | Out-String
$OU = $LikeUN.Substring($LikeUN.IndexOf("OU="))

Next we’re going to set a variable $LikeUser with the user object and we’re going to use an extended property -properties and load up all the properties we want copied.  Also going to load up the memberof property, even though it won’t actually copy in the code below:

$LikeUser = Get-ADUser $LikeUserName -Properties MemberOf,Title,Office,Manager,Department,ScriptPath,HomeDirectory
$UPN = $UserName+$UPN
$LikeUN = $LikeUser.DistinguishedName | Out-String
$OU = $LikeUN.Substring($LikeUN.IndexOf("OU="))
$LikeUser | New-ADUser -GivenName $FirstName -Surname $LastName -Name "$LastName, $FirstName" -SamAccountName $UserName -UserPrincipalName $UPN -Path $OU -AccountPassword $Password

User Groups

Copy works great, except for user groups!  Probably the most important part of copy user (that and user folder creation) is the ability to copy user groups, and to be honest this is the primary reason why I copy users and not just create new ones.  Unfortunately, piping a user object into New-ADUser simply doesn’t do the groups.  So we have to do that manually.  We already have the MemberOf property loaded into $LikeUser, and MemberOf is an array with all of the group names, so a simple loop through the array will add the groups to the new user.

ForEach ($Group in ($LikeUser.MemberOf))
{ Add-ADGroupMember $Group $UserName
}

That’s it for now, but there’s still quite a bit of work to do.  Another thing the copy user technique doesn’t do is create the home directory and set the permissions.  Then we need to activate the Exchange 2010 mailbox for the user and then last we need to append the Spiceworks ticket with the information (nothing fancy here, we’re just using an email technique to get the information in there).

So stay tuned for Part 2!

December 10, 2012 - Posted by | PowerShell | , ,

3 Comments »

  1. […] Part 1 of New User Automation we looked at creating the user account in Active Directory, copying all of the properties we needed […]

    Pingback by New User Automation – Part 2 « The Surly Admin | December 17, 2012 | Reply

  2. […] written about New User Automation here and here, it only made sense to start working on User Termination Automation.  Read on to see how […]

    Pingback by User Termination Automation – Part 1 « The Surly Admin | December 27, 2012 | Reply

  3. […] create new users.  It sounds like a simple thing but it’s actually quite involved (here was my take on it, if you don’t believe me).  Instead go for simple things.  How do I list a user’s […]

    Pingback by Powershell – Steep Learning Curve? « The Surly Admin | March 28, 2013 | Reply


Leave a reply to New User Automation – Part 2 « The Surly Admin Cancel reply