Skip to content

Instantly share code, notes, and snippets.

@Gunslap
Last active June 29, 2020 04:05
Show Gist options
  • Save Gunslap/223ada0870c3d5ce89c9 to your computer and use it in GitHub Desktop.
Save Gunslap/223ada0870c3d5ce89c9 to your computer and use it in GitHub Desktop.
Scans Active Directory for inactive accounts and disables and relocates them accordingly.
<#
.SYNOPSIS
This function disables accounts that are older than a certain threshhold.
.DESCRIPTION
Searches active directory for users based on an inputted searchbase for users that haven't logged in since a certain threshhold or haven't logged in ever and were created before that threshhold and disables them and marks in their description when and why they were disabled.
.PARAMETER $SearchBase
This is where to search in Active Directory. Must be in DN form: "ou=x,ou=x,dc=x,dc=x".
.PARAMETER NbDays
This is the number of days a user must be inactive for to require disabling
.PARAMETER LogFile
The location of the logfile. If a file is not present in that location, it will attempt to make it.
.PARAMETER emailTo
The email address to send general results to (never as thorough as logging)
.PARAMETER server
The AD Domain Controller to search from.
.EXAMPLE
FindAndDisable-Accounts -SearchBase "ou=Students,dc=Contoso,dc=com" -nbDays 100 -LogFile "\\Contososerver\scriptlogs$\DisabledStudentsLog.txt" -Verbose
This will search in the OU Students in the Contoso.com domain, that are inactive for 100 days, and verbosely log to the logfile specified.
#>
function FindAndDisable-Accounts
{
[CmdLetBinding()]
Param(
[string]$SearchBase = "Nothing",
[string]$NbDays = 365,
[string]$LogFile,
[string]$emailTo = "[email protected]",
[string]$server = "domaincontroller"
)
#Create the Log File if it doesn't already exist
if (-not (Test-Path $LogFile))
{
New-Item $LogFile -ItemType file
}
#Get the current date
#Convert the local time to UTC format (because all dates are expressed in UTC [GMT] format in Active Directory)
$CurrentDate = (Get-Date).ToUniversalTime()
#Calculate the time stamp in Large Integer format using the $NbDays specified above
#LastLogonThreshhold holds the cutoff time for disabling
$LastLogonThreshhold = ($CurrentDate.AddDays(- $NbDays)).ToFileTimeUtc()
#Initialize the string for the body of the email report
#Write out the header information to the log file
$EmailBody = "Disabling Accounts Output`r`n" + $CurrentDate.Date + "`r`n*************************************`r`n"
$EmailBody >> $LogFile
$EmailBody += "For more information see the logfile at $LogFile"
#Get all users to work with
$Users = get-aduser -server $server -Filter * -SearchBase $SearchBase -Properties *
#Get all the properties that we need for those users
$Users = $Users | Select-Object -Property SamAccountName,Name,CN,DisplayName,lastLogonTimestamp,DistinguishedName,whenCreated,Enabled
foreach ($user in $Users)
{
#initialize output and get the lastlogontimestamp for readability later
$Output = ""
$LastLogonTimeStamp = $user.lastLogonTimeStamp
#set the LastLogonTimeStamp to when the user was created if it is null. This occurs when the user hasn't logged in.
if($LastLogonTimeStamp -eq $null)
{
$LastLogonTimeStamp = ($user.whenCreated).toFileTime()
}
#set readable values for printing of the lastLogonTimeStamp and Threshhold
#these are used in logging only, and 1600 years must be added to make them the proper year
$ReadableLastLogonTimeStamp = ([System.Datetime]$LastLogonTimeStamp).AddYears(1600)
$ReadableLastLogonThreshold = ([System.Datetime]$LastLogonThreshhold).AddYears(1600)
#Bypass any users that are disabled or are in the _Disabled OU
if (($user.Enabled -eq $false) -or ($user.DistinguishedName -match "OU=_DISABLED"))
{
$Output = "Bypassing " + $user.DisplayName + " as it is already disabled."
#4>&1 pipes VERBOSE output into standard output, and >> pipes standard output to append to the specified destination
Write-Verbose $Output 4>&1 >> $LogFile
#$EmailBody += $Output
}
#if any of the name fields start with an underscore, that denotes an account we do not want changed
elseif ( ($user.Name -like "_*") -or ($user.CN -like "_*") -or ($user.DisplayName -like "_*") )
{
$Output = "Skipping " + $user.DisplayName + " (" + $user.SamAccountName + ") for one of it's names starting with an underscore."
Write-Verbose $Output 4>&1 >> $LogFile
#$EmailBody += $Output
}
#compare the lastlogontimestamp to the threshhold value (determined earlier by nbDays)
#in the case the user hasn't logged in, lastLogonTimeStamp will have been set to the date their account was created
elseif ($LastLogonTimeStamp -lt $lastLogonThreshhold)
{
#at this point, it meets the criteria of being disabled
$Output = "Changing " + $user.DisplayName + " (" + $user.SamAccountName + "). Last Logon is " + $ReadableLastLogonTimeStamp + ". Threshhold is $ReadableLastLogonThreshold"
Write-Output $Output >> $LogFile
$EmailBody += $Output
Disable-Account -UserToDisable $user -LogFileLocation $LogFile -IsStudent $isStudent.IsPresent -friendlyDate $ReadableLastLogonTimeStamp
}
#this case does not meet the disabling criteria so there is no need to change it.
else
{
$Output = "Not Changing " + $user.DisplayName + " (" + $user.SamAccountName + "). Last logon is " + $ReadableLastLogonTimeStamp + ". Threshhold is $ReadableLastLogonThreshold"
Write-Verbose $Output 4>&1 >> $LogFile
#Shouldn't need to email this part.
#$EmailBody += $Output
}
}
#Email list of changes made to the helpdesk:
$emailFrom = "[email protected]"
$subject = "Disabled Users Report for - $CurrentDate"
$smtpServer = "smtp.contoso.com"
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($emailFrom, $emailTo, $subject, $Emailbody)
}
function Disable-Account
{
param(
$UserToDisable,
$LogFileLocation,
$isStudent,
$friendlyDate
)
#get the current date
$CurrentDate = Get-Date
#get the user speicifed and set their account to disabled and their description to indicate the dates
Get-ADUser $UserToDisable.SamAccountName | Set-ADUser -Enabled $False -Description "DISABLED: $CurrentDate - LAST LOGON: $friendlyDate" #-WhatIf
#move their documents to the _old_user_accounts folder on their server
Move-Documents -UserToDisable $UserToDisable -LogFileLocation $LogFileLocation -isStudent $isStudent
}
function Move-Documents
{
param(
$UserToDisable,
$LogFileLocation,
)
#get the nsid
$samAccountName = $UserToDisable.SamAccountName
$profile_folders = "\\$Server\ProfilesShare$"
$home_folders = "\\$Server\HomeShare$"
#make a hashtable of the folders needed
$array_folders = ($profile_folders,$home_folders)
foreach ($folder in $array_folders)
{
Write-Host "Scanning $folder..."
#get the folder itself
$MainFolders = Get-ChildItem -Path $folder -Force
foreach ($SubFolder in $MainFolders)
{
#if the account name matches the foldername and the folder isn't in the old_user_accounts folder already
if (($samAccountName | Select-String -Pattern $SubFolder) -and ($SubFolder -notlike "*_Old_user_accounts*"))
{
#move and log the move
Write-Host "The user's folder: $SubFolder exists in: $folder"
$Output = "--> Moving the folder $folder\$SubFolder to _Old_user_accounts folder `r"
Write-Host $Output
Write-Output $Output >> $LogFileLocation
#Make sure the _Old_user_accounts folder exists:
if (-not (Test-Path $folder\_Old_user_accounts))
{
New-Item ("$folder\_Old_user_accounts") -type directory
}
Move-Item -Path $folder\$SubFolder $folder\_Old_user_accounts\$samAccountName\ -Force #-WhatIf
}
}
}
}
#Sample Run:
#FindAndDisable-Accounts -SearchBase "ou=Users,dc=contoso,dc=com" -nbDays 365 -LogFile "\\ContosoServer\e$\_Logs\DisabledUserssLog.txt" #-Verbose
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment