Hamish Burke | 2025-06-29
Auto-Disabling Unused Active Directory Accounts
- Identify idle accounts
- Exclude service-principal accounts or whitelisted accounts
- Notify/Get approval via email
- Disable Accounts
- Logs and auditing/reversing
- Automating It
Notify/Approve via email
- “If you approve this account for disablement, please update the user’s
ExtensionAttribute1
toApproved
in Active Directory.” - If wanted approval link in email
- create web service (Flask/Node.js) (always running)
- add link in email body:
[Approve User1](http://intranet.local/approve?user=User1&action=approve)
- Writes
ExtensionAttribute1 = Approved
using PowerShell Remoting or Graph API - Script polls/re-runs daily, looking for approved flag
- Power platform
$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
- Trigger a flow to send approval requests to each user manager
- Click approve/reject from email or teams
- On approve, flow update user in AD, or set flag (in SharePoint)
- 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)
- When new item made in sharepoint list, start flow:
- Send Start and wait for approval to
ManagerEmail
- Approve/Reject button in email
- If approved -> Update list items
ApprovalStatus
to Approved - Set Date Approved to
utcNow()
- Send Start and wait for approval to
- Have powershell script poll SharePoint via graph API or CSOM
$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
- Log everythng to central DB or CSV
Name,SamAccountName,DisabledOn,ScriptUser
- Or to sharepoint is going power automate route
- 7 day grace window, so users can request re-enablement via portal
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
- Or use Azure RunBook
- Has managed identity, built-in approvals, and logging to log analytics
Full script
- This scripts assumed standalone approach (not adding items to ShareSheet and polling that, just sending email), requiring manager manually adding approved tag to AD
# 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