PowerShell Script to Bulk Reset Active Directory Passwords for All Users in an OU


7 views

When managing large Active Directory environments, administrators occasionally need to perform bulk operations like password resets. The challenge becomes particularly complex when dealing with Organizational Units (OUs) containing thousands of users. This guide will walk through a PowerShell solution that's efficient, secure, and compliant with Active Directory best practices.

  • Active Directory Module for PowerShell installed
  • Appropriate permissions (at least "Reset Password" rights)
  • Knowledge of the target OU's Distinguished Name (DN)

Here's the fundamental script that will reset passwords for all users in a specified OU:


Import-Module ActiveDirectory

$TargetOU = "OU=Users,DC=domain,DC=com"
$NewPassword = ConvertTo-SecureString "P@ssw0rd123!" -AsPlainText -Force

Get-ADUser -Filter * -SearchBase $TargetOU | ForEach-Object {
    Set-ADAccountPassword -Identity $_ -NewPassword $NewPassword -Reset
    Set-ADUser -Identity $_ -ChangePasswordAtLogon $true
}

For production environments, consider this more robust version:


try {
    Import-Module ActiveDirectory -ErrorAction Stop
    
    $TargetOU = "OU=Employees,DC=corp,DC=example,DC=com"
    $LogFile = "C:\Temp\PasswordResetLog_$(Get-Date -Format 'yyyyMMdd').csv"
    $NewPassword = ConvertTo-SecureString "TempP@ss123" -AsPlainText -Force
    
    $Users = Get-ADUser -Filter * -SearchBase $TargetOU -Properties Enabled
    
    foreach ($User in $Users) {
        if ($User.Enabled) {
            try {
                Set-ADAccountPassword -Identity $User -NewPassword $NewPassword -Reset -ErrorAction Stop
                Set-ADUser -Identity $User -ChangePasswordAtLogon $true
                "$($User.SamAccountName),Success" | Out-File $LogFile -Append
            }
            catch {
                "$($User.SamAccountName),Failed - $($_.Exception.Message)" | Out-File $LogFile -Append
            }
        }
    }
}
catch {
    Write-Error "Critical error: $_"
    exit 1
}

For enhanced security, you might want to generate unique temporary passwords:


function Generate-TemporaryPassword {
    $Chars = [char[]]"ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789!@#$%^&*"
    return -join (1..12 | ForEach-Object { $Chars | Get-Random })
}

Get-ADUser -Filter * -SearchBase $TargetOU | ForEach-Object {
    $TempPassword = ConvertTo-SecureString (Generate-TemporaryPassword) -AsPlainText -Force
    Set-ADAccountPassword -Identity $_ -NewPassword $TempPassword -Reset
}
  • Always run such scripts in a test environment first
  • Consider temporarily disabling password complexity requirements if you're using a common temporary password
  • Ensure the script runs with minimum necessary privileges
  • Secure the log files containing password reset information

When dealing with 10,000+ users, consider these optimizations:


$BatchSize = 1000
$Users = Get-ADUser -Filter * -SearchBase $TargetOU -ResultSetSize $BatchSize

for ($i=0; $i -lt $Users.Count; $i+=$BatchSize) {
    $Batch = $Users[$i..($i+$BatchSize-1)]
    $Batch | ForEach-Object -Parallel {
        $Password = ConvertTo-SecureString "TempP@ss_$($using:i)" -AsPlainText -Force
        Set-ADAccountPassword -Identity $_ -NewPassword $Password -Reset
    } -ThrottleLimit 10
}

When you need to reset passwords for multiple users in an Active Directory Organizational Unit (OU), PowerShell provides the most efficient solution. The TechNet article you referenced contains the core cmdlet (Set-ADAccountPassword), but let's break down how to implement this properly.

  • Active Directory module for PowerShell installed (RSAT or on domain controller)
  • Sufficient AD permissions to reset passwords
  • Proper OU distinguished name

Here's a complete script that will reset passwords for all users in a specified OU:

# Import Active Directory module
Import-Module ActiveDirectory

# Define OU and new password
$targetOU = "OU=Users,DC=domain,DC=com"
$newPassword = ConvertTo-SecureString "TempP@ss123" -AsPlainText -Force

# Get all users in the OU and reset passwords
Get-ADUser -Filter * -SearchBase $targetOU | ForEach-Object {
    Set-ADAccountPassword -Identity $_ -NewPassword $newPassword -Reset
    Set-ADUser -Identity $_ -ChangePasswordAtLogon $true
    
    Write-Output "Reset password for $($_.SamAccountName)"
}

For better security and logging, consider this enhanced version:

# Parameters
$targetOU = "OU=Sales,OU=Departments,DC=company,DC=com"
$logFile = "C:\logs\PasswordReset_$(Get-Date -Format 'yyyyMMdd').log"

# Generate random passwords
function Generate-RandomPassword {
    $chars = [char[]]"ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789!@#$%"
    return -join (1..12 | ForEach-Object { $chars | Get-Random })
}

# Main execution
try {
    $users = Get-ADUser -Filter * -SearchBase $targetOU -Properties mail
    
    foreach ($user in $users) {
        $tempPassword = Generate-RandomPassword
        $securePassword = ConvertTo-SecureString $tempPassword -AsPlainText -Force
        
        Set-ADAccountPassword -Identity $user -NewPassword $securePassword -Reset
        Set-ADUser -Identity $user -ChangePasswordAtLogon $true
        
        # Log the action
        "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Reset password for $($user.SamAccountName) (Email: $($user.mail))" | Out-File $logFile -Append
        
        # Optional: Email notification would go here
    }
    
    Write-Output "Successfully processed $($users.Count) users."
}
catch {
    Write-Error "Error occurred: $_"
    $_ | Out-File $logFile -Append
}
  • Password policies: Ensure temporary passwords comply with your domain's complexity requirements
  • Account lockout policies: Bulk operations might trigger lockout detection systems
  • User communication: Plan how users will receive their temporary credentials
  • Testing: Always test with a small OU first

For very large OUs (10k+ users), consider batching the operations:

$batchSize = 500
$users = Get-ADUser -Filter * -SearchBase $targetOU
$totalUsers = $users.Count

for ($i = 0; $i -lt $totalUsers; $i += $batchSize) {
    $batch = $users | Select-Object -First $batchSize -Skip $i
    
    $batch | ForEach-Object {
        # Reset password logic here
    }
    
    Write-Progress -Activity "Processing users" -Status "$i of $totalUsers completed" -PercentComplete ($i/$totalUsers*100)
    Start-Sleep -Seconds 5  # Brief pause between batches
}