Another revision.
Added logic for when "lastlogontimestamp" does not exist. This indicates the account has never logged in. So now if "lastlogontimestamp" doesn't exist it checks the account's creation date and disables the account if the creation date is past the expiration threshold.
Also added basic email reporting.
param (
[string]$group,
[string]$days = 30,
[string]$test = "y"
)
# This script will search AD for eligible accounts to disable if they have either
# 1) never logged in and are older than the expration, or 2) if the last login is older than the expiration.
$emailAddrTo = "
[email protected]"
$emailAddrFrom = "
[email protected]"
$emailSMTP = "mail.domain.org"
$logStart = get-date -format g
$hostName = $env:COMPUTERNAME
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
$scriptName = $MyInvocation.MyCommand.Name
$log = "$scriptPath\$scriptName.log"
$delimitedList = "$scriptPath\$scriptName.delimited.txt"
# If the group parameter is not specified, throw an error and short script usage example.
if ( -not ($group)) {
echo "Group parameter missing."
echo "Script usage: $scriptName -group `'AD Group`' -days 30 -test NO"
echo "If `"-days`" isn't specified the default is 30."
echo "If `"-test NO`" isn't specified, no changes will be made."
exit
}
echo "Disabling accounts in group $group that have no logged in for more than $days day(s)."
if ( $test -ne "NO") { echo "Running in **TEST** mode. No changes will be made!" }
import-module activedirectory
# Select AD accounts based on group parameter
if ( $group -eq "All") {
echo "Group All specified, grabbing all Active Directory users"
$disableList = @(get-aduser -filter * | select -expandproperty SamAccountName)
}
else {
echo "Grabbing Active Directory users that are a member of $group"
$disableList = @(get-adgroupmember $group | select -expandproperty SamAccountName)
}
# Set expiration threshold based on days parameter
$expiration = (get-date).adddays(-$days)
# Define arrays to log eligible accounts
$noLogons = @()
$expiredLogons = @()
# Loop through accounts
foreach ($acct in $disableList) {
# Reset $lastLogonTS to accomodate for null results.
$lastLogonTS = ''
echo "Processing account $acct"
# Get user's distinguished name
$acctDN = get-aduser $acct -properties distinguishedname | select -expandproperty distinguishedname
# Check if account is disabled. If disabled, skip account.
$isEnabled = get-aduser $acct -properties enabled | select -expandproperty enabled
if ( $isEnabled -eq $false) {
echo "$acct is already disabled, skipping."
}
else {
# Get the last logon timestamp for user. If user has no timestamp, this will error (which means user has never logged in)
$lastLogonTS = get-aduser $acct -properties lastlogontimestamp | select -expandproperty lastlogontimestamp -ErrorAction SilentlyContinue
# If last logon timestamp does not exist, check when the account was created. If the account is older than the threshold, disable.
if (!$lastLogonTS) {
$acctCreation = get-aduser $acct -properties whencreated | select -expandproperty whencreated
if ( $acctCreation -lt $expiration) {
echo "$acct has no recorded login and was created more than $days ago (created $acctCreation) which makes it eligible for deactivation."
if ($test -eq "NO") {
disable-adaccount -identity $acct
echo "$acct disabled"
$noLogons += "$acct | $acctDN | Created: $acctCreation"
}
else {
$noLogons += "$acct | $acctDN | Created: $acctCreation | TEST ONLY"
}
}
}
else {
# Convert last logon timestamp from file time to date time
$lastLogon = [datetime]::FromFileTime($lastLogonTS)
# If last logon timestamp is older than the threshold, disable account.
if ($lastLogon -lt $expiration) {
echo "$acct's last logon was more than $days days ago ($lastLogon) and is eligible for deactivation."
if ($test -eq "NO") {
disable-adaccount -identity $acct
echo "$acct disabled"
$expiredLogons += "$acct | $acctDN | Last Logon: $lastLogon"
}
else {
$expiredLogons += "$acct | $acctDN | Last Logon: $lastLogon | TEST ONLY"
}
}
}
}
}
# Compile report
# Start log file
$logEnd = get-date -format g
write-output "Log for $scriptName`r`nExecuted on $hostName`r`nScript started $logStart`r`nScript ended $logEnd`r`n" | out-file $log
# Generate list of users removed from group, if any.
if (!$noLogons) {
write-output "Accounts older than $days days with no logon were not found (this is good!).`r`n" | out-file -append $log
}
else
{
write-output "The following accounts have been disabled because they are older than $days days and have never been used:" | out-file -append $log
write-output $noLogons | out-file -append $log
write-output "" | out-file -append $log
}
# Generate list of users added to the group, if any.
if (!$expiredLogons) {
write-output "Accounts with the last logon older than $days days were not found (yay!)." | out-file -append $log
}
else
{
write-output "The following accounts have been disabled because their last logon was more than $days days ago:" | out-file -append $log
write-output $expiredLogons | out-file -append $log
}
# Dump account information to text file to be attached to the email.
write-output $noLogons | out-file $delimitedList
write-output $expiredLogons | out-file -append $delimitedList
# Send log to $emailAddr if variable is set.
if (!$emailAddrTo) {
write-output "`r`nNo email address specified, no report sent." | out-file -append $log
}
else {
$emailBody = get-content -path $log | out-string
send-mailmessage -from "$hostName <$emailAddrFrom>" -to $emailAddrTo -subject "$scriptName Report" -body $emailBody -smtpserver $emailSMTP -attachments $delimitedList
}