Sup pshhomies? A colleague of mine Martijn Monshouwer was getting his PowerShell on when he ran into a little snag. A little birdie told him to run his script by me, which he did! “Dear PowerShell…” You had me at PowerShell… 🙂 Incidentally starting any email with PowerShell is a good way to get my attention.
The script is suppose to:
- find user account(s) past expiration date
- disable the user account(s)
- move account(s) to a specific OU
- clear the user group membership, all but three groups
Martijn did the grunt work. All that was missing was the remove group membership. I learned my lesson not to overwhelm but assist, so no rewriting entire scripts! At that time I was right in the middle of a migration, but hey, it’s PowerShell and Martijn was clever enough to appease my ego… Now how could I say no eh? 😉
I did a quick scan… “Read-Host… Yeah… let’s make that a parameter”. “Write-Host… Better change that to Write-Verbose lest we incur the wrath of Don Jones…” Ok Urv remember, no rewriting… (Well maybe just a little… old habits die hard…)
So here’s the end result:
<# Author: M. Monshouwer / I. Strachan Version: 1.0 Version History: N/A Purpose: Get expired AD accounts that are not disabled and move to disabled OU .\Move-ExpiredDisabledUserToDisableOU –Verbose #> [CmdletBinding()] param( [string]$ChangeNumber='12345', [string]$Initials='I.S' ) # Import Active Directory module Import-Module ActiveDirectory -Verbose:$false #region: Define variables #Get expired AD accounts that are not disabled Write-Verbose 'Searching for accounts that are enabled but expired...' $ExpiredAccountsNotDisabled = Search-ADAccount -AccountExpired | Where-Object { $_.Enabled -eq $true } Write-Verbose "Found $(@($ExpiredAccountsNotDisabled).count) that meet criteria" #Define groups that will NOT be removed, Use the DistinguishedName $ExcludedGroups = @( 'CN=GroupX,OU=Groups,OU=Resources,DC=pshirwin,DC=local' 'CN=GroupY,OU=Groups,OU=Resources,DC=pshirwin,DC=local' ) #Define OU for Disabled Accounts. Change to reflect your OU $DisabledAccountsOU = 'OU=Disabled,OU=Users,OU=IPI,DC=pshirwin,DC=local' #Get current date $Date = Get-Date -Format g #endregion #Loop through Expired Users ForEach($User in $ExpiredAccountsNotDisabled) { Write-Verbose "Processing user $($user.SamAccountName) group membership" #Get User Group Membership $userMembership = Get-ADUser $user.SamAccountName -Properties MemberOf | Select-Object -ExpandProperty memberof Write-Verbose "User membership count: $(@($userMembership.Count))" foreach($member in $userMembership) { # Remove User Group membership if (!$ExcludedGroups.Contains($member)){ try{ Write-Verbose "Removing user $($User.SamAccountName) from $($member)" Get-ADGroup $member | Remove-ADGroupMember -Members $user.SamAccountName -Confirm:$false } catch{ Write-Error "Something went wrong removing $($User.Name) from `'$member`'" } } } #Process user further try{ # Write Description & Disable Account Write-Verbose "Setting user's Description to: `"Disabled $Date; $ChangeNumber; $Initials`"" Set-ADUser -Identity $User.SamAccountName -Description "Disabled $Date; $ChangeNumber; $Initials" -Enabled $false # Move user to OU for Disabled Accounts Write-Verbose 'Moving user to Disabled OU' Get-ADUser -identity $User.SamAccountName | Move-ADobject -targetpath $DisabledAccountsOU } catch{ Write-Error "Something went wrong processing `'$($User.DistinguishedName)`'" } }
Martijn was quite happy with his script! Welcome to the club! 😉
While at the gym ( my other favorite past time) I had an epiphany (Sounds more dramatic eh?)
What if you needed to reinstate a user? The user would have to be moved back to the original OU, ReEnabled and be made member of all the groups removed from. Of Course this could be done manually but what’s the fun in that? Oh and some logging would be nice…
So Martijn…
Try making your script more resilient. Level up! Learning PowerShell is fun!!!
Ttyl,
Urv
I love this script and wanted to thank you. I was hoping that you could add to it just a little. I do not want to search all of AD for expired accounts. I would like to only search a specific OU for expired accounts. How can I achieve that with this current script?
LikeLike
Hi Jerome, just add -SearchBase “ou=..,dc=..” to search-adaccount… That way you won’t scan all of AD… Rg./Irwin
LikeLike
Thank you Irwin! I ended up figuring that part out. Now working on grabbing a log of employees and the groups they were part of in case we need to enable them. This really got me started off well. Thank you so much!
LikeLiked by 1 person