Dargslan.WinUserMgmt.psm1
|
<# .SYNOPSIS Windows local user and group management toolkit — user audit, password policy, admin group check, account lockout, stale account detection .DESCRIPTION Part of the Dargslan Windows Admin Toolkit collection. More tools and resources at https://dargslan.com Free Cheat Sheets: https://dargslan.com/cheat-sheets Windows & DevOps Books: https://dargslan.com/books .LINK https://dargslan.com .LINK https://github.com/Dargslan/powershell-admin-scripts #> function Get-UserSecurityAudit { <# .SYNOPSIS Comprehensive local user account security audit .DESCRIPTION Audits all local user accounts for security issues: admin membership, password policy, disabled accounts, never-expiring passwords, and stale accounts. Part of Dargslan.WinUserMgmt — https://dargslan.com #> [CmdletBinding()] param([int]$StaleDays = 90, [switch]$Json) $users = Get-LocalUser $admins = Get-LocalGroupMember -Group "Administrators" -ErrorAction SilentlyContinue $report = [ordered]@{ Summary = [PSCustomObject]@{ TotalUsers = ($users | Measure-Object).Count Enabled = ($users | Where-Object Enabled | Measure-Object).Count Disabled = ($users | Where-Object { -not $_.Enabled } | Measure-Object).Count Admins = ($admins | Measure-Object).Count NeverExpire = ($users | Where-Object { $_.PasswordExpires -eq $null -and $_.Enabled } | Measure-Object).Count NoPasswordRequired = ($users | Where-Object { $_.PasswordRequired -eq $false } | Measure-Object).Count } Users = $users | ForEach-Object { $isAdmin = $admins.Name -contains "$env:COMPUTERNAME\$($_.Name)" [PSCustomObject]@{ Name = $_.Name; Enabled = $_.Enabled; IsAdmin = $isAdmin LastLogon = $_.LastLogon; PasswordLastSet = $_.PasswordLastSet PasswordExpires = $_.PasswordExpires; PasswordRequired = $_.PasswordRequired IsStale = ($_.LastLogon -and $_.LastLogon -lt (Get-Date).AddDays(-$StaleDays)) } } StaleAccounts = $users | Where-Object { $_.Enabled -and $_.LastLogon -and $_.LastLogon -lt (Get-Date).AddDays(-$StaleDays) } | Select-Object Name, LastLogon Administrators = $admins | Select-Object Name, ObjectClass, PrincipalSource } if ($Json) { return $report | ConvertTo-Json -Depth 3 } Write-Host "`n [User Security Audit]" -ForegroundColor Cyan $report.Summary | Format-List Write-Host " Administrators:" -ForegroundColor Yellow $report.Administrators | Format-Table -AutoSize if ($report.StaleAccounts) { Write-Host " Stale Accounts (>$StaleDays days):" -ForegroundColor Red; $report.StaleAccounts | Format-Table } return $report } function Get-PasswordPolicy { <# .SYNOPSIS Get local password policy settings .DESCRIPTION Retrieves password complexity, length, history, and lockout policy settings. Part of Dargslan.WinUserMgmt — https://dargslan.com #> [CmdletBinding()] param([switch]$Json) $netAccounts = net accounts 2>&1 $policy = [PSCustomObject]@{} foreach ($line in $netAccounts) { if ($line -match "Minimum password length:\s+(.+)") { $policy | Add-Member -NotePropertyName "MinLength" -NotePropertyValue $Matches[1].Trim() } if ($line -match "Maximum password age.*:\s+(.+)") { $policy | Add-Member -NotePropertyName "MaxAge" -NotePropertyValue $Matches[1].Trim() } if ($line -match "Minimum password age.*:\s+(.+)") { $policy | Add-Member -NotePropertyName "MinAge" -NotePropertyValue $Matches[1].Trim() } if ($line -match "Password history.*:\s+(.+)") { $policy | Add-Member -NotePropertyName "History" -NotePropertyValue $Matches[1].Trim() } if ($line -match "Lockout threshold:\s+(.+)") { $policy | Add-Member -NotePropertyName "LockoutThreshold" -NotePropertyValue $Matches[1].Trim() } if ($line -match "Lockout duration.*:\s+(.+)") { $policy | Add-Member -NotePropertyName "LockoutDuration" -NotePropertyValue $Matches[1].Trim() } } if ($Json) { return $policy | ConvertTo-Json } Write-Host "`n [Password Policy]" -ForegroundColor Cyan $policy | Format-List return $policy } Export-ModuleMember -Function * |