0

I'm trying to make a powershell script that essentially automates the account lockout tools. ideally I'll be able to get a fairly efficient query that can identify recently locked out accounts then retrieve that data from our DC's and probably send an email letting us know who was locked out and a copy of the "message" from the security log.

here's what I have so far: I read that to use Get-WinEvent we have to use a hashtable so i created a hashtable object and expanded by datetime variables into the hashtable and they appear correct, and if I run something like $hash.starttime | gm , I can confirm that it's still a system.datetime object.

$LockedOut = Get-ADUser -Properties AccountLockoutTime,LastBadPasswordAttempt,BadPwdCount,LockedOut  -Filter * | ?{$_.AccountLockOutTime -ge (Get-Date).AddHours(-3)}
$LockedOut | ft name,samaccountname,LockedOut,AccountLockoutTime,BadPwdCount,LastBadPasswordAttempt
$DomainControllers = Get-ADDomainController -Filter *   

ForEach($lockeduser in $LockedOut)
{
$lockeduser.Name
ForEach($DC in $DomainControllers.name)
    {
    $before = ($lockeduser.AccountLockoutTime.AddMinutes(1)).date
    $after = ($lockeduser.AccountLockoutTime.AddMinutes(-1)).date
    $hash = $null
    $hash =  @{}
    $hash.Add("Logname", "security")
    $hash.Add("Starttime", $after)
    $hash.Add("Endtime", $before)
    $DC
    $messagecriteria = $lockeduser.Name
    $message = Get-WinEvent -ComputerName $DC -FilterHashtable $hash  | ?{$_.Message -like "*$messagecriteria*"}
    $message
    }
    "----------------------------------------------------------------------------------------------------------"
}

But when I run the query I only get back

Get-WinEvent : No events were found that match the specified selection criteria.
At line:19 char:20
+         $message = Get-WinEvent -ComputerName $DC -FilterHashtable $hash  | ?{$_ ...
+                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : ObjectNotFound: (:) [Get-WinEvent], Exception
+ FullyQualifiedErrorId : NoMatchingEventsFound,Microsoft.PowerShell.Commands.GetWinEventCommand
4
  • 1
    At the risk of stating the obvious, do you actually have any users locked out at the moment? Oct 13, 2014 at 21:50
  • 1
    I just tested a similar example using mostly your code (I did it locally on my machine, looking for a different event, but built the hash the same way). It works for me, the only issues I had were when, like @Katherine suggests above, there aren't any security events in your 2 minute time period. Oct 13, 2014 at 22:15
  • using event viewer with a filter applied does actually show the events, and the initial $lockedout query actually determines if any users have been locked out in the last 3 hours, and echos it, and I'm getting results echoed. Oct 13, 2014 at 23:56
  • I think I got it working Oct 14, 2014 at 16:47

1 Answer 1

0

I seem to have gotten it to work. I think some variable properties were sticking in memory and it was causing the query to supply the wrong timeframes.

here's the finished product for anyone interested, query has been tightened up to only pull 2 sec worth of logs to parse, and only looking back the last 10 min. There's also an segment for writing the results to a custom PSobject which is useful for exporting to CSV or HTML.

the only thing left is I'll insert and HTML header and have this write to a table that will come across in an email.

$LockedOut = Get-ADUser -Properties AccountLockoutTime,LastBadPasswordAttempt,BadPwdCount,LockedOut  -Filter * | ?{$_.AccountLockOutTime -ge (Get-Date).AddMinutes(-10)}
$LockedOut | ft name,samaccountname,LockedOut,AccountLockoutTime,BadPwdCount,LastBadPasswordAttempt
$DomainControllers = Get-ADDomainController -Filter *   
$results = $null 
ForEach($lockeduser in $LockedOut)
{
$lockedusername = $lockeduser.name
ForEach($DC in $DomainControllers.name)
    {

    $starttime = $lockeduser.AccountLockoutTime.AddSeconds(-1)
    $endtime = $lockeduser.AccountLockoutTime.AddSeconds(1)
    $hash = $null
    $hash =  @{}
    $hash.Add("Logname", "security")
    $hash.Add("Starttime", $starttime)
    $hash.Add("Endtime", $endtime)
    "$lockedusername -  Locating Events between $starttime and $endtime on $DC..."
    $messagecriteria = $lockeduser.Name
    $message = Get-WinEvent -ComputerName $DC -FilterHashtable $hash  | ?{$_.Message -like "*$messagecriteria*"}
    $message |ft @{Expression={$ExecutionContext.InvokeCommand.ExpandString($lockeduser.Name)};Label="Name"}, `
    @{Expression={$ExecutionContext.InvokeCommand.ExpandString($lockeduser.SamAccountName)};Label="SAMID"},machinename,TimeCreated,ID,message
    $hash.Clear()
    $TC = $message.timecreated
    $ID = $message.id
    $messagetext = $message.message
    IF($message -ne $null)
        {
        ForEach($line in $message)
        {
        $obj = New-Object -TypeName PSObject
                $obj | Add-Member -NotePropertyName "Name" -NotePropertyValue $LockedUser.name
                $obj | Add-Member -NotePropertyName "SamID" -NotePropertyValue $LockedUser.SamAccountName
                $obj | Add-Member -NotePropertyName "DC" -NotePropertyValue $DC
                $obj | Add-Member -NotePropertyName "TimeCreated" -NotePropertyValue $line.TimeCreated
                $obj | Add-Member -NotePropertyName "Event ID" -NotePropertyValue $line.ID
                $obj | Add-Member -NotePropertyName "Message" -NotePropertyValue $line.message
                [Array]$results += $obj
        }

        }
    }
    "----------------------------------------------------------------------------------------------------------"

}

"Table of results"
$results | ft
1
  • Do you know about Search-ADAccount -LockedOut? It seems like that would be a better than your first line.
    – jbsmith
    Oct 15, 2014 at 16:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .