Hamish Burke | 2025-06-29


Auto-Disabling Unused Active Directory Accounts

  1. Identify idle accounts
  2. Exclude service-principal accounts or whitelisted accounts
  3. Notify/Get approval via email
  4. Disable Accounts
  5. Logs and auditing/reversing
  6. Automating It

Notify/Approve via email

$toNotify = $toDisable | Select Name, @{Name='Manager';Expression={(Get-ADUser $_.SamAccountName -Properties Manager).Manager}}

$body = $toNotify | ConvertTo-Html -Property Name, Manager -Title 'Pending AD Disable Approval'

Send-MailMessage -To $managerEmail -From $svcAccountEmail -Subject "[Action Required] Disable Idle AD Accounts" -Body $body -BodyAsHtml -SmtpServer $smtpServer

# Proceed only after attribute 'ApprovalStatus' set to 'Approved'
$approved = $toDisable | Where-Object { (Get-ADUser $_.SamAccountName -Properties ExtensionAttribute1).ExtensionAttribute1 -eq 'Approved' }

Power Automate Approval Flow

  1. Trigger a flow to send approval requests to each user manager
  2. Click approve/reject from email or teams
  3. On approve, flow update user in AD, or set flag (in SharePoint)
  4. Powershell script queries that status and disables approved users

Sharepoint

UserSamAccountName (Text)
UserDisplayName (Text)
ManagerEmail (Person or Text)
ApprovalStatus (Choice: Pending, Approved, Rejected)
DateSubmitted (Date)
DateApproved (Date)
ProcessDate (Date)
$approvedUsers = Get-SharePointListItems -List "DisableApprovals" |
	Where-Object { $_.ApprovalStatus -eq "Approved" }

foreach ($user in $approvedUsers) {
	Disable-ADAccount -Identity $user.UserSamAccountName
	# Could update sharepoint to mark processed
}

Logs and Auditing

Search-ADAccount -AccountDisabled -UsersOnly |
	Where-Object { $_.DisabledOn -gt (Get-Date).AddDays(-7) } |
	Enable-ADAccount

Automating it

schtasks /create /tn "AD_AutoDisable" /tr "powershell.exe -File C:\Scripts\AutoDisableAD.ps1" /sc daily /st 02:00 /rl highest /f

Full script

# First, find all stale AD accounts with Search-ADAccouunt
$stale = Search-ADAccount -AccountInactive -TimeSpan 90.00:00:00 -UsersOnly

# get whitelisted accounts
$whitelist   = Get-ADGroupMember "No-Disable"

# Get Org accounts
$serviceOUs  = Get-ADOrganizationalUnit -Filter "Name -like '*ServiceAccounts'*" | Select -ExpandProperty DistinguishedName

# Filter stale accounts, to remove accounts in above two vars
$toDisable = $stale | Where-Object {
        $_.DistinguishedName -notin $whitelist.DistinguishedName -and
        -not ($serviceOUs -match $_.DistinguishedName)
    }

# Get manager accounts of all accounts about to disable (handles manager being null)
$toNotify = $toDisable | ForEach-Object {
    $user = $_
    $userDetails = Get-ADUser $user.SamAccountName -Properties Manager
    [PSCustomObject]@{
        Name    = $user.Name
        Manager = $userDetails.Manager
    }
}

# Create email body
$body = $toNotify | ConvertTo-Html -Property Name, Manager -Title 'Pending AD Disable Approval'


# TESTING ONLY: Static recipients
$managerEmail   = "admin@example.com"
$svcAccountEmail = "automator@example.com"
$smtpServer     = "smtp.example.com"

Send-MailMessage -To $managerEmail -From $svcAccountEmail -Subject "[Action Required] Disable Idle AD Accounts" -Body $body -BodyAsHtml -SmtpServer $smtpServer

# 6. Filter only approved accounts (where ExtensionAttribute1 == 'Approved')
$approved = $toDisable | Where-Object {
    (Get-ADUser $_.SamAccountName -Properties ExtensionAttribute1).ExtensionAttribute1 -eq 'Approved'
}

# 7. Disable approved accounts
$approved | Disable-ADAccount