The following script will read through your current Active Directory and filter for user accounts with the following specific conditions:
- Lockedout users – please read below for further information about this
- all users that are lockedout
- must be an enabled user
- that is not expired
- disabled users
- all users that have been disabled
- expired users
- must be an enabled user
- the expiration date is set and past the current date
- users with password never expires set
- must be an enabled user
This will give you a pure counter output per channel in an for PRTG Extended script sensor XML result.
But there is a theoretical flaw in one of the methods – the locked out users. Now, user accounts get locked out in Active Directory due to too many logon attempts with an invalid password. This causes Active Directory to set the lockedout bit in the object properties. The issue here is that this bit will not be set back to 0 after the defined lockout duration (GPO) is past, the property will only be set back to 0 once the lockout duration is passed and he successfully logged on.
This means, the counter might give you more results then currently true, it might count users that have been locked out but the lockout-duration passed – but they did not yet logon successfully. This is somehow a false positive, while not totally false. In any case, you need to be aware of this.
The script could be more efficient as well in the way it filters a few things, so far I optimized it as far as I could – the LockedOut value can not be set as a -Filter, in theory it might be possible to speed it up with a -Filter to the UserAccountControl (if that is even possible – not tested) – but I am not certain this would work. If you really want to speed it up you would need to work with -LDAPFilter – but this actually needs to completely replace the internal filter capabilities of Get-ADUser – you can’t use both – it is one or the other.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | Import-Module ActiveDirectory #you could add - filters, a OU limitation or a server against whom this would be executed.. see Get-ADUser options for more details #$Server = "" #$OU = "" #Get-ADUser -Server $Server -Filter #Get-ADUser -SearchBase $OU -Filter #all locked users that aren't disabled or expired $LockedOutUsers=Get-ADUser -Filter {Enabled -eq $True -and objectCategory -eq "person" -and objectClass -eq "user"} -Properties sAMAccountName,DisplayName,LockedOut,LockoutTime,Enabled,AccountExpirationDate | where {$_.lockedout -eq $True -and (($_.AccountExpirationDate -gt (Get-Date) -or ($_.AccountExpirationDate -eq $null)))} #all users that are disabled - this is a manual action in Active Directory $DisabledUsers=Get-ADUser -Filter {Enabled -eq $False -and objectCategory -eq "person" -and objectClass -eq "user"} -Properties sAMAccountName,DisplayName,LockedOut,LockoutTime,Enabled,AccountExpirationDate #all users that are not disabled but expired already $ExpiredUsers=Get-ADUser -Filter {Enabled -eq $True -and objectCategory -eq "person" -and objectClass -eq "user"} -Properties sAMAccountName,DisplayName,LockedOut,LockoutTime,Enabled,AccountExpirationDate | where {(($_.AccountExpirationDate -lt (Get-Date) -and ($_.AccountExpirationDate -ne $null)))} #users with not expiring passwords and are enabled and not expired $NotExpiringPWD=Get-ADUser -Filter {Enabled -eq $True -and PasswordNeverExpires -eq $True -and objectCategory -eq "person" -and objectClass -eq "user"} -Properties sAMAccountName,DisplayName,LockedOut,LockoutTime,Enabled,AccountExpirationDate If ($LockedOutUsers.count -eq $null -and $LockedOutUsers -eq $null){ $cntLockedOutUsers=0 }Elseif ($LockedOutUsers.count -eq $null -and $LockedOutUsers -ne $null){ $cntLockedOutUsers=1 }Else{ $cntLockedOutUsers=@($LockedOutUsers.count) } If ($DisabledUsers.count -eq $null -and $DisabledUsers -eq $null){ $cntDisabledUsers=0 }Elseif ($DisabledUsers.count -eq $null -and $DisabledUsers -ne $null){ $cntDisabledUsers=1 }Else{ $cntDisabledUsers=@($DisabledUsers.count) } If ($ExpiredUsers.count -eq $null -and $ExpiredUsers -eq $null){ $cntExpiredUsers=0 }Elseif ($ExpiredUsers.count -eq $null -and $ExpiredUsers -ne $null){ $cntExpiredUsers=1 }Else{ $cntExpiredUsers=@($ExpiredUsers.count) } If ($NotExpiringPWD.count -eq $null -and $NotExpiringPWD -eq $null){ $cntNotExpiringPWD=0 }Elseif ($NotExpiringPWD.count -eq $null -and $NotExpiringPWD -ne $null){ $cntNotExpiringPWD=1 }Else{ $cntNotExpiringPWD=@($NotExpiringPWD.count) } $XML += "<prtg>" $XML += "<result>" $XML += "<channel>Locked Out Users</channel>" $XML += "<value>$cntLockedOutUsers</value>" $XML += "</result>" $XML += "<result>" $XML += "<channel>Disabled Users</channel>" $XML += "<value>$cntDisabledUsers</value>" $XML += "</result>" $XML += "<result>" $XML += "<channel>Expired Users - not disabled</channel>" $XML += "<value>$cntExpiredUsers</value>" $XML += "</result>" $XML += "<result>" $XML += "<channel>Users with password never expires</channel>" $XML += "<value>$cntNotExpiringPWD</value>" $XML += "</result>" $XML += "</prtg>" Function WriteXmlToScreen ([xml]$xml) { $StringWriter = New-Object System.IO.StringWriter; $XmlWriter = New-Object System.Xml.XmlTextWriter $StringWriter; $XmlWriter.Formatting = "indented"; $xml.WriteTo($XmlWriter); $XmlWriter.Flush(); $StringWriter.Flush(); Write-Output $StringWriter.ToString(); } WriteXmlToScreen $XML |
This script updated with a corrected version as of February 2019 and was also posted in the PRTG knowledge base here.