Search code examples
windowsrestpowershellevent-logwindows-server

Having issues parsing an event log (ID 4725) and outputting the target username field using Powershell


Basically, I am trying to write some code that will run off of a scheduled task any time the event ID 4725 is triggered. This specific event states that a particular user had their AD account disabled (Windows Server 2016).

What I need to do is take the username from this event ID and output it as a variable #UserName to be used in the restmethod URI.

# Variables
$params = @{"action"="move";"destination"="/Shared/IT/Archived User Data/"}
$json = $params|ConvertTo-Json
$eventRecordId = 4725
$eventChannel = "Security"

# Gets the latest "disabled user account" event log and outputs the disabled user's name to a variable called $UserName


Get-EventLog –Log Security -InstanceId 4725 -Newest 1 | $UserName = ?{Group-Object -Property "TargetUserName"}

Echo $UserName 

# Calls the Egnyte API to move the disabled user's home folder to the archive folder
Invoke-RestMethod `
    -Method Post `
    -body $json `
    -Uri 'https://xxxxxx.egnyte.com/pubapi/v1/fs/private/"$UserName"' `
    -Headers @{Authorization = "Bearer xxxxxxxxxxxxxxxxxxxxxxx"
               Contenttype = "application/json"}

Expected results: Take the username from the target-username field in the security event-log ID 4725, output it to variable "#UserName", and then input it into the rest-method API.

Actual results: The variable is not being created.


Solution

  • OK Lets take a look at this Event 4725 template

    (Get-WinEvent -ListProvider * -ErrorAction Ignore).Events |
            Where-Object {$_.Id -eq 4725} |
            select * | 
            Format-List
    

    We can see there is a TargetUserName

    <data name="TargetUserName" inType="win:UnicodeString" outType="xs:string"/>
    

    So lets parse that Message into XML, Get-EventLog returns a type System.Diagnostics.EventLogEntry

    So first we need to change that object into a System.Diagnostics.Eventing.Reader.EventLogRecord so we can convert to XML

    We can ether Make a new call using Get-WinEvent which will return the type System.Diagnostics.Eventing.Reader.EventLogRecord which has a method for turning data into XML

    Or We can get the Index from the current record and call Get-WinEvent looking for the EventRecordID.

    Below is a function i wrote that will parse the message field and make a new psobject with property ParsedMessage

    function Parse-WindowsEvents(){
        param(
            [Parameter(Position=1, ValueFromPipeline)]
            #[System.Diagnostics.Eventing.Reader.EventRecord[]]$Events
            [object[]]$Events
        )
        process{
            $ArrayList = New-Object System.Collections.ArrayList
            $Events  | %{
                $EventObj = $_
                $EventObjFullName = $_.GetType().FullName
                if($EventObjFullName -like "System.Diagnostics.EventLogEntry"){   
                    $EventObj = Get-WinEvent -LogName security -FilterXPath "*[System[EventRecordID=$($_.get_Index())]]"
                }elseif($EventObjFullName -like "System.Diagnostics.Eventing.Reader.EventLogRecord"){
    
                }else{
                    throw "Not An Event System.Diagnostics.Eventing.Reader.EventLogRecord or System.Diagnostics.EventLogEntry"
                }
                $PsObject =  New-Object psobject
                $EventObj.psobject.properties | %{
                    $PsObject | Add-Member -MemberType NoteProperty -Name $_.Name -Value $_.Value
                }
                $XML = [xml]$EventObj.toXml()
                $PsObject2 = New-Object psobject
                $XML.Event.EventData.Data | %{
                    $PsObject2 | Add-Member -MemberType NoteProperty -Name $_.Name -Value $_."#text"
                }
                $PsObject | Add-Member -MemberType NoteProperty -Name ParsedMessage -Value $PsObject2
                $ArrayList.add($PsObject) | out-null
            }
            return $ArrayList
        }
    }
    
    $Username = Get-EventLog –Log Security -InstanceId 4725 -Newest 1 | Parse-WindowsEvents | select -ExpandProperty ParsedMessage | select TargetUserName
    $Username.TargetUserName
    #or
    $Username = (Get-EventLog –Log Security -InstanceId 4725 -Newest 1 | Parse-WindowsEvents | select -ExpandProperty ParsedMessage).TargetUserName
    $Username