One-Liner: My Take On Finding Stale User and Computer Accounts

Using PowerShell and information in Active Directory to identify 'stale' user or computer accounts is prone to inaccuracies. This is because there are many circumstances or technical nuances that can make the data unreliable. For example, think of a globe-trotting sales person, they (and their laptop) might not see the office for months, however, they both still remain company assets.

It's generally accepted that lastLogonTimeStamp and pwdLastSet are the best measures of 'staleness'. However, as intimated, further investigation should be performed on any information obtained using these attributes.

 

Stale Trails

Here's my preferred method of generating 'staleness' reports for user and computer accounts...

 First, set your threshold, i.e. the period after which an account is considered stale. Here, our threshold is > 90 days ago.

$DaysAgo=(Get-Date).AddDays(-90)

 

Next, create a report of stale computer accounts with a marvelous one-liner...

Get-ADComputer -Filter {(PwdLastSet -lt $DaysAgo) -or (LastLogonTimeSTamp -lt $DaysAgo)} -Properties PwdLastSet,LastLogonTimeStamp,Description,OperatingSystem |

Select-Object -Property DistinguishedName,Name,Enabled,Description,OperatingSystem, `

@{Name="PwdLastSet";Expression={[datetime]::FromFileTime($_.PwdLastSet)}}, `

@{Name="LastLogonTimeStamp";Expression={[datetime]::FromFileTime($_.LastLogonTimeStamp)}} |

Export-Csv -Path possible_stale_computers.csv -NoTypeInformation

 

What's going on here then?

First up, we apply a filter* to the Get-ADComputer cmdlet that retrieves accounts with either the pwdLastSet or lastLogonTimeStamp attribute set to a value that is greater than 90 days ago.

*Top-tip: always try and filter as far to the left of your one-liner as possible - this will help make processing more efficient.

 

We also ask for a number of additional properties / attributes to the default ones returned by the cmdlet:

  • pwdLastSet - for obvious reasons
  • lastLogonTimeStamp - for obvious reasons
  • description - the description might be useful in our further investigation - for example, a Cluster Name Object will have a description that refers to its status as a virtual account
  • operatingSystem - this may be useful for identifying non-Windows operating systems as these may not update the 'staleness' attributes in an expected manner

 

Now, we use Select-Object to shape the data for our report. Certain properties / attributes are selected and included 'as is'. The pwdLastSet and lastLogonTimeStamp properties are put into a hash table so their values can be converted to a human readable format.

 

Finally, we export this filtered information to a CSV file. Let's have a look at an example.

 

Now, create a report of stale user accounts with a similar one-liner...

Get-ADUser -Filter {(PwdLastSet -lt $DaysAgo) -or (LastLogonTimeSTamp -lt $DaysAgo)} -Properties PwdLastSet,LastLogonTimeStamp,Description |

Select-Object -Property DistinguishedName, SamAccountName, Enabled,Description, `

@{Name="PwdLastSet";Expression={[datetime]::FromFileTime($_.PwdLastSet)}}, `

@{Name="LastLogonTimeStamp";Expression={[datetime]::FromFileTime($_.LastLogonTimeStamp)}} |

Export-Csv -Path possible_stale_users.csv -NoTypeInformation

 

With your 'staleness' reports generated, the real work begins... assessing the accuracy of the collected data!