I wanted to know which command or script that can be used or customized to search for the AD user account that was disabled in the past 6 months?
Script 1: Not sure how to customize this script below since it is quite complex.
# When an account is disabled, the userAccountControl attribute is set to 514.
# Therefore, with Get-ADReplicationAttributeMetadata to find out when that attribute was the last set
$disabledUsers = Get-ADObject -Filter "ObjectClass -eq 'User' -and userAccountControl -eq '514'"
foreach ($disabledUser in $disabledUsers)
{
Get-ADReplicationAttributeMetadata $disabledUser -Server localhost |
Where-Object { $_.AttributeName -eq 'UserAccountControl' } | Select Object, LastOriginatingChangeTime |
Where-Object { $_.LastOriginatingChangeTime -gt (Get-Date).AddDays(-180) }
}
Script 2: I was able to use this script and getting all the column & filtering I need, however, it does not show the AD account that was disabled in the past 6 months?
Import-Module ActiveDirectory
$domainDN = (Get-ADDomain).DistinguishedName
$excludeOUs = @(
'OU=Shared Mailbox'
'OU=Company Leaver'
) | ForEach-Object { $_ + ',' + $domainDN }
$Past = -180
$Days = (Get-Date).AddDays($Past)
$ResultPath = "C:\TEMP\ADLastLogonPast_$($Past)_Days.csv"
$properties = @('Name', 'mail', 'physicalDeliveryOfficeName', 'DisplayName', 'title', 'SamAccountName', 'CanonicalName', 'lastlogondate')
$filter = { (LastLogonDate -notlike '*' -or LastLogonDate -le $Days) -and (passwordLastSet -le $Days) -and (enabled -eq $True) -and (PasswordNeverExpires -eq $false) -and (whenCreated -le $Days) }
Get-ADUser -properties $properties -Filter $filter -SearchBase $domainDN |
Select-Object DisplayName,
Title,
PhysicalDeliveryOfficeName,
UserPrincipalName,
LastLogonDate,
@{ n = 'LastLogonDaysAgo'; e = { [int]((Get-Date) - $_.LastLogonDate).TotalDays } },
@{ n = 'CN'; e = { Split-Path $_.CanonicalName -Parent } },
@{ n = 'ParentContainer'; e = { $_.DistinguishedName -replace '^CN=.*?(?=CN|OU)' } } | Where-Object {
($_.SamAccountName -notmatch '^(Calendar|Room|Account|Fax|Team|Office|Test|User|SM_|HealthMailbox|SVC)$') -and
($excludeOUs -notcontains $_.ParentContainer)
} |
Export-Csv -NoTypeInformation -Path $ResultPath
Assuming you want to find accounts that were changed from enabled to disabled within the last 6 months, then your second script won't tell you that. You're simply finding accounts that are disabled and haven't been used in more than 6 months. Or at best, you can modify that to give you accounts that are disabled and last updated in the last 6 months. But some of those could have been disabled more than 6 months ago.
The first script will get you what you want, since using Get-ADReplicationAttributeMetadata
allows you find when a specific attribute was modified. So you can find out when the userAccountControl
attribute was modified. But it does need some modification.
First, this:
# When an account is disabled, the userAccountControl attribute is set to 514.
This is not necessarily true. The userAccountControl
attribute is a bit flag, meaning that every bit in the binary value is a flag that means something different (1
= on, 0
= off). So the decimal value doesn't really have any relevance. To find out if an account is disabled, you want to look at the second bit. To do that, you use the bitwise operator -band
.
That script is also pointing at localhost
, which means you'd have to run it on a domain controller. But you can easily modify that to find a domain controller to point at.
I also added a condition in Get-ADObject
to only find accounts that have been modified in the last 6 months, since if the account was disabled less than 6 months ago, that surely means it was modified less than 6 months ago. This lowers the number of accounts you have to call Get-ADReplicationAttributeMetadata
on, lowering the amount of time this script will take to run. (Note the single quotes around the filter, that's important because of how PowerShell handles the date.)
$sixMonthsAgo = (Get-Date).AddDays(-180)
$disabledUsers = Get-ADObject -Filter 'ObjectClass -eq "User" -and whenChanged -ge $sixMonthsAgo -and UserAccountControl -band 2'
$server = Get-ADDomainController
foreach ($disabledUser in $disabledUsers)
{
Get-ADReplicationAttributeMetadata $disabledUser -Server $server -Properties UserAccountControl |
Where-Object { $_.AttributeName -eq 'UserAccountControl' } | Select Object, LastOriginatingChangeTime |
Where-Object { $_.LastOriginatingChangeTime -gt $sixMonthsAgo }
}
(For some reason, I found that Get-ADReplicationAttributeMetadata
doesn't give me any data when I run this script in the PowerShell ISE, but it works just fine when I copy/paste into a normal PowerShell window. No idea why, but it's worth mentioning)
Technically this still may not find exactly when an account was disabled, since it's looking for any change in userAccountControl
. It's possible that, for example, someone set the account to "don't expire password" after the account was disabled, which would also change the userAccountControl
attribute, and this script would be looking at the date of the "don't expire password" change, not the disabled date. But in most cases, that kind of thing isn't going to happen.