Monitoring Active Directory users is an essential task for system administrators and IT security. In many organizations, Active Directory is the only way you can authenticate and gain authorization to access resources. Some resources are not so, yet some are highly sensitive. Using PowerShell, we can build a report that allows us to monitor Active Directory activity across our environment.

Adam Bertram

Adam Bertram is a 20-year IT veteran, Microsoft MVP, blogger, and trainer. Adam is the founder of the e-learning tech screencast platform TechSnips. Catch up on Adam’s articles at adamtheautomator.com, or follow TechSnips on Twitter at @techsnips_io.

To get started, let's first define what we mean by a "user activity report" because this could mean a few different things. For this article, I'm going to define this report as a way to find out the last time all Active Directory users logged in.

We first need to figure out merely how to pull the user login information for all users. One way to do this is to use the Active Directory module's Get-AdUser command. This command lets you query Active Directory users using different filtering methods. For this article, we'd like to query all Active Directory users who have logged in before. The LastLogonDate property is the best way to do this, but unfortunately, it does not replicate to all domain controllers (DCs). We'll need to pull this attribute from all of our DCs.

First, I'll query all DCs in my environment with Get-AdDomainController. The command below will return the fully qualified domain names (FQDNs) of every DC.

Next, I'll need to query each DC for every user who has a LastLogonDate. To do this, I'll use Get-AdUser and filter on users having a last logon date attribute.

Once I have all of the users with a last logon date, I can now build a report on this activity. I can create reports in PowerShell lots of different ways.

First, I can pipe the results of my query to the Out-GridView command. This returns an interactive GUI allowing you to sort, filter, and view results in many different ways.

Using Out-Gridview is nice, but it doesn't let you save the results. Another way to return this output is by creating a CSV file. We can output objects in PowerShell to a CSV file by using the Export-Csv command. Below I'm piping all the users I've queried to Export-Csv, which then creates a CSV file with each row containing the SamAccountName and LastLogonDate attributes for each user.

Finally, we can return these results to an HTML file. Since we're working with HTML, we have an infinite number of ways to do this, but I've chosen to use an example of creating an HTML table.

After running this code, you'll then get a nicely formatted HTML table.

The HTML report

The HTML report

Join the 4sysops PowerShell group!

Your question was not answered? Ask in the forum!

5+

Users who have LIKED this post:

  • avatar
  • avatar
  • avatar
Share
10 Comments
  1. Justin 7 months ago

    Put that script in Scheduled tasks, add a logo title, timestamp, CSS and you get something nice 🙂

     

    0

  2. Justin 7 months ago

    Adam, I think there may be an issue with your second code snippet. You've created a foreach loop but are not referencing the $dc variable in the subsequent command. Did you mean to use the -Server parameter with $dc as the argument in the Get-ADUser cmdlet?

    3+

    Users who have LIKED this comment:

    • avatar
    • avatar
    • Bruce 7 months ago

      The first code snippet actually doesn't pull all the domain controllers in the domain.  It only pulls one DC and more specifically the DC that the account used to run the script.  To pull multiple, you'd have to use the  "-filter" variable to pull in others.  Pulling in other DCs is really not needed though, as the AD Database is replicated to each, and you'd just pull in duplicate data into your report. 

      1+

      Users who have LIKED this comment:

      • avatar
    • Jerry 7 months ago

      Actually, it doesn't matter as Get-ADDomainController only returns a single DC.  To get all of them, then you would need to do use:

      (Get-ADForest).Domains | Foreach-Object { Get-ADDomainController -Filter * -Server $_ } | Select-Object -ExpandProperty HostName

      And then user -Server $DC with Get-ADUser.

      2+

      Users who have LIKED this comment:

      • avatar
  3. Alan 7 months ago

    Bruce, I'm afraid you are in error. This is one of the few properties that AD does not replicate.  The lastlogondate property is unique per DC and indicates when a user last authenticated to that specific DC.  To get a true last logon you would need to query all DCs and sort and then select the most recent date.  Further, you would need error checking to ensure all DCs returned data or you risk a faulty return. Finally, if the last DC (or only DC) a user last logged into is removed from the domain at some time for any reason, the last login data is lost. So you can end up with no last logon data but a non-zero LogonCount (this property is replicated).

    Another property you might consider that is far more simple to work with, and is replicated, is lastlogontimestamp.  Since it is replicated it cannot be lost with a DC leaving the domain and can be checked on from any DC without needing to check all DCs and sort and select.  There is a drawback to using this property however.  It only updates if it is more than 14 days off from the most current LastLogon property recorded across all DCs in the domain.  That means it can be up to two weeks off from the actual last logon event!

    Trying to write a script to query all of your DCs and collating the LastLogon data to get the most accurate report possible can get rather involved. And if you have a lot of users and/or a lot of domain controllers the query can take a very long time depending on how you write it.  If you aren't a powershell guru, or just don't have the time, there are tools available that can do this work for you. Personally I have used Hyena and ManageEngine to great effect to produce last login data for SOX audits where we needed to be able to verify a user account was not used to log in after a termination.

    In short, this article is very short sighted and incomplete, as well as misleading.  It barely scratches the surface on the requirements of actually building a complete and useful last logon report that is accurate.  However, it does do well to introduce some of the fundamental capabilities of HTML report generation within powershell.  It really is a powerful shell.  🙂

    3+

    • Luc Fullenwarth 7 months ago

      Code example to compare the lastlogon LastLogonDate and lastlogonTimestamp properties:

       

      1+

      Users who have LIKED this comment:

      • avatar
  4. Sudhir 7 months ago

    I think as well, the command for get-addomaincontroller does not return the list of all DC's i think, was trying to run and it does return on one, more information here:

    https://docs.microsoft.com/en-us/powershell/module/activedirectory/get-addomaincontroller?view=winserver2012-ps

    0

  5. Leos Marek 7 months ago

    Not that I want to advertise something, but Netwrix offers a free Active Directory auditing tool for that (plus other topics).

    https://www.netwrix.com/netwrix_change_notifier_for_active_directory.html

    1+

    Users who have LIKED this comment:

    • avatar
  6. Author
    Adam Bertram 7 months ago

    Sorry about the code error. I've got it updated.

    1+

  7. Raymond 7 months ago

    Get-ADDomainController -Filter *
    would pull all of them easily, you might then want to invoke this across the DCs themselves to get it all back faster.

    1+

Leave a reply to Jerry Click here to cancel the reply

Your email address will not be published. Required fields are marked *

*

© 4sysops 2006 - 2019

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account