PowerShell脚本无法识别全部久未登录AD用户,求排查建议
排查AD清理脚本未识别全部离职用户的问题
我是MSP(托管服务提供商)员工,正在开发清理客户AD(活动目录)的脚本。很多客户不会主动告知员工离职信息,所以这个脚本用来保持AD整洁、消除安全隐患。当前测试版本脚本会把90天未登录的启用用户(排除管理员组)输出到文本文件,但现在发现无法识别所有应标记的用户——AD里确实存在已离职但仍启用的用户,求排查建议。
当前测试脚本
# Set the time threshold (in days) for inactive user accounts $inactiveDays = 90 # Get the domain name from the environment variable $domain = $env:USERDOMAIN # Set the distinguished name (DN) of the Disabled Users OU $disabledUsersOU = "OU=DisabledUsers,DC=$domain" # Update this with actual OU path # Get the current date and calculate the threshold date for inactive accounts $thresholdDate = (Get-Date).AddDays(-$inactiveDays) # Get inactive users based on the last logon date, excluding users in the Administrators group $inactiveUsers = Get-ADUser -Filter { LastLogonDate -lt $thresholdDate -and Enabled -eq $true -and MemberOf -notlike "*CN=Administrators,*" } -Properties LastLogonDate # Path to text file $filePath = "C:\testCleanup\inactives.txt" # Check if the folder exists, create it if not if (-not (Test-Path "C:\testCleanup" -PathType Container)) { New-Item -ItemType Directory -Path "C:\testCleanup" } # Prints DistinguishedName to file foreach ($user in $inactiveUsers) { $user.DistinguishedName | Out-File -FilePath $filePath -Append } # Display a message indicating that the operation is complete Write-Host "DistinguishedNames of inactive users (excluding Administrators) printed to $filePath"
排查建议
1. 修正LastLogonDate的局限性
LastLogonDate是AD跨DC复制后的属性,存在同步延迟,且无法反映用户在所有DC上的最新登录时间。如果用户在某台DC登录后未同步到脚本执行的DC,就会被漏判。建议遍历所有DC获取LastLogon属性(非复制属性,仅存储在用户登录的DC上),取最大值判断:
$inactiveDays = 90 $thresholdDate = (Get-Date).AddDays(-$inactiveDays) $allDCs = Get-ADDomainController -Filter * $inactiveUsers = @() $adminGroup = Get-ADGroup "Administrators" foreach ($dc in $allDCs) { # 获取当前DC上的启用用户,排除直接/间接属于管理员组的用户 $usersOnDC = Get-ADUser -Filter { Enabled -eq $true } -Properties LastLogon, MemberOf -Server $dc.Name | Where-Object { -not (Get-ADPrincipalGroupMembership $_ | Where-Object { $_.DistinguishedName -eq $adminGroup.DistinguishedName }) } foreach ($user in $usersOnDC) { if ($user.LastLogon -eq 0) { # 从未登录过的用户,直接判定为符合条件 if (-not ($inactiveUsers | Where-Object { $_.SamAccountName -eq $user.SamAccountName })) { $inactiveUsers += $user } } else { $lastLogonTime = [DateTime]::FromFileTime($user.LastLogon) if ($lastLogonTime -lt $thresholdDate) { if (-not ($inactiveUsers | Where-Object { $_.SamAccountName -eq $user.SamAccountName })) { $inactiveUsers += $user } } } } }
2. 修复管理员组过滤的漏洞
原脚本的MemberOf -notlike "*CN=Administrators,*"仅能排除直接属于管理员组的用户,无法识别通过嵌套组加入管理员组的用户。改用Get-ADPrincipalGroupMembership检查用户的所有组(包括嵌套):
$adminGroup = Get-ADGroup "Administrators" $inactiveUsers = Get-ADUser -Filter { LastLogonDate -lt $thresholdDate -and Enabled -eq $true } -Properties LastLogonDate | Where-Object { -not (Get-ADPrincipalGroupMembership $_ | Where-Object { $_.DistinguishedName -eq $adminGroup.DistinguishedName }) }
3. 补充其他判断维度
除了登录时间,可结合LastPasswordSet属性辅助判断——如果用户密码超过90天未修改且未登录,大概率是离职用户:
$inactiveUsers = Get-ADUser -Filter { LastLogonDate -lt $thresholdDate -and Enabled -eq $true -and LastPasswordSet -lt $thresholdDate } -Properties LastLogonDate, LastPasswordSet | Where-Object { -not (Get-ADPrincipalGroupMembership $_ | Where-Object { $_.DistinguishedName -eq $adminGroup.DistinguishedName }) }
4. 验证脚本执行权限
确保运行脚本的账号拥有读取所有AD用户属性的权限,部分客户可能对特定OU设置了权限限制,导致脚本无法读取该OU下用户的登录属性。
5. 手动校验目标用户属性
找到一个已知的漏判用户,执行以下命令查看其属性,确认是否符合脚本过滤条件:
Get-ADUser <用户名> -Properties LastLogonDate, LastLogon, Enabled, MemberOf, LastPasswordSet
重点检查:
Enabled是否为TrueLastLogonDate/LastLogon是否早于90天前- 是否属于管理员组(包括嵌套)
6. 检查域时间同步
确保域内所有DC的时间同步正常,时间偏差会导致thresholdDate计算不准确,进而误判用户的活跃状态。
内容的提问来源于stack exchange,提问作者Adam M
相关产品推荐
相关产品推荐

