Skip to content

A quick script I put together to help me maintain user accounts in Active Directory in compliance with local security requirements.

Notifications You must be signed in to change notification settings

kismetgerald/AD-UserMaintenance-Script

Repository files navigation

AD User Maintenance Solution

Automate the cleanup of dormant Active Directory user accounts with intelligent DC health monitoring, detailed auditing, beautiful interactive HTML reports, and email notifications. Primarily written to help fellow SysAdmins out who work in air-gapped environments that must adhere to RMF requirements under either STIG or JSIG compliance regimes.

Overview

This repository contains a complete, production-ready PowerShell solution:

  • AD-UserMaintenance-v2.0.ps1 – The core maintenance script
  • AD-UserMaintenance-Installer-v1.0.ps1 – One-click installer that deploys the script as a daily Scheduled Task (supports standard accounts and gMSAs)

Key Features

  • Identifies inactive, expired password, and never-set-initial-password accounts
  • Disables accounts, removes non-protected group memberships, adds audit comments, moves to a Disabled Users OU
  • Automatic exclusion of service accounts (configurable prefixes)
  • Intelligent Domain Controller health check (critical for PowerShell 7+)
  • Parallel processing in PowerShell 7+ for large environments
  • Interactive, collapsible HTML reports with visual dashboard
  • Dual logging (human-readable + JSONL for SIEM)
  • Full WhatIf / dry-run support
  • Email reports with embedded HTML and full report attachment
  • Centralized XML configuration (perfect for scheduled tasks)

Prerequisites

  • PowerShell 5.1+ (PowerShell 7+ strongly recommended)
  • ActiveDirectory PowerShell module (RSAT)
  • Domain Admin or equivalent permissions
  • Target "Disabled Users" OU must already exist

Option 1 – Recommended: Automated Deployment (Installer)

The installer does everything: creates folders, copies the script, generates an XML config, and registers a Scheduled Task.

  1. Place both scripts in the same folder
  2. Open PowerShell as Administrator
  3. Execute the installer

It will guide you interactively, or you can run fully non-interactively (example with gMSA):

.\AD-UserMaintenance-Installer-v1.0.ps1 `
    -UseGMSA `
    -GMSAAccount "CONTOSO\ADMaint-GMSA$" `
    -ScriptADDomain "contoso.com" `
    -ScriptTargetOU "OU=Disabled Users,DC=contoso,DC=com" `
    -ScriptInactivityThreshold 90 `
    -ScriptSendEmailReport $true `
    -ScriptSMTPServer "smtp.contoso.com" `
    -ScriptEmailFrom "ad-automation@contoso.com" `
    -ScriptEmailTo @("admin@contoso.com","security@contoso.com")

Useful Installer Switches

Switch Purpose
-WhatIfMode Test installer – no files or tasks created
-ScriptWhatIfMode Task runs in dry-run mode (reports only)
-UseGMSA Use a Group Managed Service Account (recommended)
-InstallPathCustom install location (default: C:\Scripts\ADMaintenance)
-TaskNameCustom task name (default: AD-UserMaintenance-Daily)
-ScheduleTimeDaily run time (default: 02:00)

After installation you get:

  • Script copied to the install path
  • AD-UserMaintenance-Config.xml
  • INSTALLATION_CONFIG.txt (full documentation)
  • Daily Scheduled Task

Option 2 – Manual Deployment (No Installer)

  1. Copy AD-UserMaintenance-v2.0.ps1 to your desired location

    Example: C:\Scripts\ADMaintenance

  2. (Recommended) Create an XML configuration file:

$config = @{
    ADDomain                = "contoso.com"
    TargetOU                = "OU=Disabled Users,DC=contoso,DC=com"
    InactivityThreshold     = 90
    NewAccountThreshold     = 30
    RemoveGroupMemberships  = $true
    AddCommentsToObject     = $true
    ServiceAccountPrefixes  = @("svc_","app_")
    SendEmailReport         = $true
    SMTPServer              = "smtp.contoso.com"
    SMTPPort                = 25
    EmailUseSSL             = $false
    EmailFrom               = "ad-automation@contoso.com"
    EmailTo                 = @("admin@contoso.com")
    LogPath                 = "C:\Scripts\ADMaintenance\Logs"
    HTMLReportPath          = "C:\Scripts\ADMaintenance\Reports"
    VerboseLogging          = $true
    SaveHTMLReport          = $true
}
$config | Export-Clixml -Path "C:\Scripts\ADMaintenance\AD-UserMaintenance-Config.xml"
  1. (If using authenticated SMTP) Create encrypted credential file as the task account:
$cred = Get-Credential
$cred | Export-Clixml -Path "C:\SecureStore\smtp-cred.xml"
  1. Create the Scheduled Task (example using gMSA):
$action   = New-ScheduledTaskAction -Execute "powershell.exe" `
            -Argument "-NoProfile -ExecutionPolicy Bypass -File `"C:\Scripts\ADMaintenance\AD-UserMaintenance-v2.0.ps1`" -ConfigFile `"C:\Scripts\ADMaintenance\AD-UserMaintenance-Config.xml`""

$trigger  = New-ScheduledTaskTrigger -Daily -At "02:00"
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -ExecutionTimeLimit (New-TimeSpan -Hours 2)

Register-ScheduledTask -TaskName "AD-UserMaintenance-Daily" `
    -Action $action -Trigger $trigger -Settings $settings `
    -User "CONTOSO\ADMaint-GMSA$"

Testing & Validation

Always test in WhatIf mode first:

# With config file
.\AD-UserMaintenance-v2.0.ps1 -ConfigFile "C:\Scripts\ADMaintenance\AD-UserMaintenance-Config.xml" -WhatIfMode

# Or with direct parameters (add others as necessary)
.\AD-UserMaintenance-v2.0.ps1 -ADDomain "contoso.com" -TargetOU "OU=Disabled Users,DC=contoso,DC=com" -WhatIfMode

Review the generated HTML report – it shows exactly what would have happened.


Default Output Locations

Type Default Path
Logs C:\Scripts\ADMaintenance\Logs
HTML Reports C:\Scripts\ADMaintenance\Reports
Config File C:\Scripts\ADMaintenance\AD-UserMaintenance-Config.xml

Quick Commands

# Run task manually
Start-ScheduledTask -TaskName "AD-UserMaintenance-Daily"

# View last run result
(Get-ScheduledTaskInfo -TaskName "AD-UserMaintenance-Daily").LastTaskResult

Author: Kismet Agbasi GitHub | Email
AI Contributors: ClaudeAI, Grok
Version:

  • Main Script v2.0 (2025-11-15)
  • Installer v1.0 (2025-11-25)

Contributing

Pull requests are welcome! For major changes, please open an issue first.

License

MIT License

Enjoy a cleaner, more secure Active Directory


About

A quick script I put together to help me maintain user accounts in Active Directory in compliance with local security requirements.

Resources

Stars

Watchers

Forks

Packages

No packages published