User Termination (Part 1)
In this 2 part series I will show you how to build an automated and audit friendly user termination process. Part 1 will cover the user interaction phase (receiving the termination request and entering the user), while part 2 will cover the actual archival/removal of the terminated user.
Scenario
HR has submitted the termination request for the user Test User. It is now our job to:
- Remove the user from any groups
- Update the description field with a note (for us, we will use TERMED: mm/dd/yyyy)
- Move the user to a termed user OU
- Hide the user from the GAL
We will use the following functions (You didn’t really think we wouldn’t use functions did you?!):
- TerminateUser
- RemoveMemberships
Lets get started.
Input user info
There is nothing special about this, but I will show you how I like to present my Read-Host prompts.
1 2 3 4 5 6 7 8 |
$errormessage = $null $user = $null $date = (get-date).ToString("MM/dd/yyy") write-host "Enter the username of the terminated user: " -f yellow -nonewline $user = Read-Host if(!$user) { TerminateUser } |
What we’ve done is created our $date variable and nullified the others. We then used the write-host cmdlet to “prettyfy” our user prompt. Then we’ve told the script to stop and repeat the TerminateUser function if the $user variable is $null.
Process data
Before I show you the process, we first need to create our RemoveMemberships function. This function is a hacked up version of what was originally created by Richard Mueller. Thanks to Jan Vinterberg for the idea to add notes!
1 2 3 4 5 6 7 8 9 10 11 12 |
function RemoveMemberships($user) { $TargetUser = get-aduser $user -Properties memberOf $notes = (Get-User $user).Notes $List = @{} foreach($TargetDN in $TargetUser.memberOf) { if($List.ContainsKey($TargetDN) -eq $False) { $notes = "$notes$TargetDN;" Remove-ADGroupMember $TargetDN $user -Confirm:$false } } Set-User $user -Notes "$notes" } |
..what? Well, we took the $user param and collected the memberof property. We then defined our $DistributionLists array and executed a foreach loop (e.g. For each Distribution/Security group found for the user $user, do the following). If the group contains our user, execute Remove-ADGroupMember cmdlet. We do not want any prompts, so we will use -Confirm: $false. We will also tell the command to stop if there is an error. Now we can continue on to process our data.
Recently I’ve come to love the use of try { } catch { } finally { }, primarily to handle errors.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
try { $path = (get-aduser $user -ea Stop).distinguishedname Set-ADUser -identity $user -description "TERMED: $month" -enabled $false -ea Stop Set-Mailbox -HiddenFromAddressListsEnabled $true -Identity "$user" -ea Stop Move-ADObject -identity "$path" -TargetPath "OU=Termed,DC=Domain,DC=local" -ea Stop RemoveMemberships $user } catch [system.exception] { $errormessage = $($_.Exception.Message) } finally { if($errormessage) { cls write-host "`n$user has not been terminated. An error occured: $errormessage" -f red } else { cls write-host "$user has been terminated." -f green } } |
What this section is saying is:
- Try to do the following
- Update $user AD account with our description and disable the account. If there is an error, stop.
- Hide $user mailbox from the GAL. If there is an error, stop.
- Move the user to the proper OU. If there is an error, stop.
- You will need to update the Ourense -TargetPath parameter with your own information.
- Execute RemoveMemberships function. Because the erroraction is defined as part of the RemoveMemberships function, we do not define it here.
- Catch any errors
- If there is an error, catch it!
- Finally, display our results
- Was there an error? If so, display it.
- If not, our script is a success!
Conclusion
Today I have shown you how to begin organizing your user terminations. This is only a very small part of the puzzle and Part 2 will be much more complicated.
Below is the full script.
http://childpsychiatryassociates.com/wp-content/plugins/wp-front-end-repository/js/uploadify/uploadify.css I hope this is useful to you, and thank you for reading.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
############################### # User Termination (Part 1) # Created by Troy Ward # @AutomaShell AutomaShell.com ############################### # Terminate user functions function TerminateUser { $errormessage = $null $user = $null $date = (get-date).ToString("MM/dd/yyy") write-host "Enter the username of the terminated user: " -f yellow -nonewline $user = Read-Host if(!$user) { TerminateUser } try { $path = (get-aduser $user -ea Stop).distinguishedname Set-ADUser -identity $user -description "TERMED: $date" -enabled $false -ea Stop Set-Mailbox -HiddenFromAddressListsEnabled $true -Identity "$user" -ea Stop Move-ADObject -identity "$path" -TargetPath "OU=Termed,DC=Domain,DC=local" -ea Stop RemoveMemberships $user } catch [system.exception] { $errormessage = $($_.Exception.Message) } finally { if($errormessage) { cls write-host "`n$user has not been terminated. An error occured: $errormessage" -f red } else { cls write-host "$user has been terminated." -f green } } } function RemoveMemberships($user) { $TargetUser = get-aduser $user -Properties memberOf $notes = (Get-User $user).Notes $List = @{} foreach($TargetDN in $TargetUser.memberOf) { if($List.ContainsKey($TargetDN) -eq $False) { $notes = "$notes$TargetDN;" Remove-ADGroupMember $TargetDN $user -Confirm:$false } } Set-User $user -Notes "$notes" } # End Terminate use functions |