Solved

Need help with logic for AD Powershell Audit <30 / 30-60 / >90 days inactive users

Posted on 2013-12-03
6
3,032 Views
Last Modified: 2013-12-05
So I have this script I've been playing with... the goal is to do some basic AD auditing.  I'm using both Microsoft AD cmd-lets and the Quest cmd-lets (I find both have their place).

What I really need to make sure of is my logic for finding users that are inactive for 30 days, then inactive form 30-60 days, then inactive over 90 days.

The script will output:

- New accounts created in last seven days
- Groups modified in last seven days
- 30/30-60/90 and over inactive users
- Report user accounts that have never logged on to their account
- Send an email

Yeah, I know the attach as a text file is somewhat kludgy, but it works for these purposes.

Can someone take a look at the <30 / 30-60 / >90 logic strings and tell me what would work better, I'm not sure my results are accurate or my logic is correct.

# Prepare loading required modules

import-module activedirectory
Add-PSSnapin Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue

# Prepare and output file for mailing

$OutputfilePath = "C:\ADUserAudit-"+([datetime]::Now).tostring("yyyyMMdd")+".txt"


# Accounts created this week

$When = ((Get-Date).AddDays(-7)).Date
 
$UsersCreatedLastWeek = (Get-ADUser -Filter {whenCreated -ge $When} -Properties whenCreated) | select samaccountname,name,distinguishedname
$UsersCreatedLastWeekTable = ($UsersCreatedLastWeek | format-table) 

# Groups Modified this week

$When = ((Get-Date).AddDays(-7)).Date
 
$GroupsModifiedLastWeek = (Get-ADGroup -Filter {whenChanged -ge $When} -Properties whenChanged) | select samaccountname,name,distinguishedname 
$GroupsModifiedLastWeekTable =  ($GroupsModifiedLastWeek | format-table)


# List all users in that have not logged on within 
# XXX days in "Active Directory" 
#  
# Get the Current Date 
#  
$CURRENTDATE=GET-DATE 
# 
# Number of Days to check back.   
#  
$NumberDays=30 
# 
# Organizational Units to search 
# 

$OUList = "OU=Users,OU=company,DC=com","OU=Users2,OU=company,DC=com"

# Prepare arrays for totals

$30Days = @()
$60Days = @()
$90Days = @()

ForEach ($OU in $OUList) 
    {

    #LastLogon.AddDays() adds x number of days making the users lastlogon x number of days into the future (e.g. Sep 28th somes October 27th...)

    $30Days += (GET-QADUSER -SearchRoot $OU | where { $_.LastLogon.AddDays(30) -lt $CURRENTDATE}) | select samaccountname,Name,DN

    $60Days += (GET-QADUSER -SearchRoot $OU | where { ($_.LastLogon.AddDays(60) -lt $CURRENTDATE -and $_.LastLogon.AddDays(60) -lt ($CURRENTDATE.AddDays(-30))) }) | select samaccountname,Name,DN

    $90Days += (GET-QADUSER -SearchRoot $OU | where { ($_.LastLogon.AddDays(90) -lt $CURRENTDATE -and $_.LastLogon.AddDays(90) -lt ($CURRENTDATE.AddDays(-30))) }) | select samaccountname,Name,DN
    
 
    }

$30DaysTable = ($30Days | format-table)
$60DaysTable = ($60Days | format-table)
$90DaysTable = ($90Days | format-table)

# Get users that have never logged in, but use Windows AD Powershell cmdlets as it should look at all domain controllers. Not restricted to OU:

$NeverBeenKissed = get-aduser -f {-not ( lastlogontimestamp -like "*") -and (enabled -eq $true)} | select samaccountname,name,distinguishedname

$NeverBeenKissedTable = $NeverBeenKissed | format-table
 
# Write to a file

Out-File $OutputfilePath

Add-Content -Path $OutputfilePath "Users Created in the Last Week:"
Add-Content -Path $OutputfilePath " "
$UsersCreatedLastWeekTable | Out-File $OutputfilePath -append
Add-Content -Path $OutputfilePath "Groups Modified in the Last Week:"
Add-Content -Path $OutputfilePath " "
$GroupsModifiedLastWeekTable | Out-File $OutputfilePath -append
Add-Content -Path $OutputfilePath "Users not logged in for 30 days:"
Add-Content -Path $OutputfilePath " "
$30DaysTable | Out-File $OutputfilePath -append
Add-Content -Path $OutputfilePath "Users not logged in for 60-90 days:"
Add-Content -Path $OutputfilePath " "
$60DaysTable | Out-File $OutputfilePath -append
Add-Content -Path $OutputfilePath "Users not logged in for over 90 days:"
Add-Content -Path $OutputfilePath " "
$90DaysTable | Out-File $OutputfilePath -append
Add-Content -Path $OutputfilePath "Users who have NEVER logged in!:"
Add-Content -Path $OutputfilePath " "
$NeverBeenKissedTable | Out-File $OutputfilePath -append

# Send it in email as an attachment, since it's not as simple to port it into an email yet.

$smtpServer = “hub.company.com”

Send-MailMessage -To "person@company.com” -Subject “AD User Audit 30/60/90” -From “PowerShellAudit@company.com” -Body “Current AD User Audit is attached.” -Priority High -SmtpServer $smtpServer -Attachments $OutputfilePath

Open in new window

0
Comment
Question by:gerhardub
  • 3
  • 2
6 Comments
 
LVL 40

Expert Comment

by:Subsun
Comment Utility
You can try with Search-ADAccount to search the inactive accounts.. for example..

$30  = Search-ADAccount -UsersOnly -AccountInactive -TimeSpan 30
$3060 = Search-ADAccount -UsersOnly -AccountInactive -TimeSpan 60 | ?{($30 | Select -ExpandProperty Samaccountname) -notcontains $_.Samaccountname}
$90 = Search-ADAccount -UsersOnly -AccountInactive -TimeSpan 90

Open in new window

0
 
LVL 39

Accepted Solution

by:
footech earned 500 total points
Comment Utility
What I really need to make sure of is my logic for finding users that are inactive for 30 days, then inactive form 30-60 days, then inactive over 90 days
This says to me - find the users;
 - who haven't logged in in the last 30 days, so last logon date must be greater than 30
 - whose last logon was between 30 and 60 days ago
 - whose last logon was greater than 90 days ago

The first two are pretty much the same, the second just has an additional limit placed on it.  And what about last logon between 60 and 90 days ago?

Your script logic is pretty convoluted (and a little different than my understanding of what you want).  The first will get users whose last logon was greater then 30 days ago.  The second will get users whose last logon was between 30 and 60 days ago.  The third will get users whose last logon was between 30 (I think you meant 60 here) and 90 days ago.

In addition to Search-ADAccount you could also do something like the following:
$lt30 = @()
$30Days = @()
$60Days = @()
$90Days = @()

$now = Get-Date
ForEach ($OU in $OUList) 
{
        Get-ADUser -filter * -Properties LastLogonDate -SearchBase $OU | ForEach `
    {
        If ( $_.LastLogonDate -gt $now.AddDays(-30) )
        { $lt30 += $_ | Select samaccountname,Name,DistinguishedName }
        ElseIf ( $_.LastLogonDate -lt $now.AddDays(-30) -and $_.LastLogonDate -gt $now.AddDays(-60) )
        { #another way to do the same thing
          $30Days += New-Object PsObject -Property @{ samaccountname = $_.samaccountname; Name = $_.name; DN = $_.DistinguishedName }
        }
        ElseIf ( $_.LastLogonDate -lt $now.AddDays(-60) -and $_.LastLogonDate -gt $now.AddDays(-90) )
        { $60Days += $_ | Select samaccountname,Name,DistinguishedName }
        ElseIf ( $_.LastLogonDate -lt $now.AddDays(-90) )
        { $90Days += $_ | Select samaccountname,Name,DistinguishedName }
    }
}

Open in new window

0
 
LVL 1

Author Comment

by:gerhardub
Comment Utility
Folks ,

You rock.... Let me plug these in and play in the AM... I'll get back to you tomorrow!
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 1

Author Comment

by:gerhardub
Comment Utility
Interestingly, the Search-ADAccount cmdlet gave me false results.  It was odd... $30 and $90 were exactly the same, $60 had zero results.... which makes sense in hindsight.


FooTech: Your understanding of what I really needed worked great.  The arrays literally break out the users from time as I needed, and then allowed me to break it out in a text based report that ended with 7/7/30/60/90 and "never been kissed." -grin-

Thanks for that... you've just saved me a ton of time, and I learned something from both of you.  I need to brush up on my Powershell logic... and revisit the cmdlets.

I'll open another ticket if either of your want 500 points toward figuring out how to format it in HTML and send that in an email! Let me know!

GB
0
 
LVL 1

Author Closing Comment

by:gerhardub
Comment Utility
Fantastic level of help... I can't thank you enough... and I'm a hardass.
0
 
LVL 39

Expert Comment

by:footech
Comment Utility
Glad I could help.

One thing to keep in mind if you want to explore the use of Search-ADAccount, when specifying a timespan to indicate days you should enclose the number in quotes.  So
Search-ADAccount -UsersOnly -AccountInactive -TimeSpan 30
would have a timespan of 30 ticks, and
Search-ADAccount -UsersOnly -AccountInactive -TimeSpan "30"
would have a timespan of 30 days.  You could also write it like
Search-ADAccount -UsersOnly -AccountInactive -TimeSpan 30.0:0
When written like this the quotes are optional.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Resolve DNS query failed errors for Exchange
This article will help you understand what HashTables are and how to use them in PowerShell.
This tutorial will walk an individual through configuring a drive on a Windows Server 2008 to perform shadow copies in order to quickly recover deleted files and folders. Click on Start and then select Computer to view the available drives on the se…
This tutorial will show how to configure a new Backup Exec 2012 server and move an existing database to that server with the use of the BEUtility. Install Backup Exec 2012 on the new server and apply all of the latest hotfixes and service packs. The…

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

7 Experts available now in Live!

Get 1:1 Help Now