playbooks/AzHunter.Playbook.LogonAnalyser.ps1

Function Start-AzHunterPlaybook {
    <#
    .SYNOPSIS
        A PowerShell function to run a hunting playbook
  
    .DESCRIPTION
        This playbook will analyze UserLoggedIn Operations.
  
    .PARAMETER Records
        An array of records to apply different data transformations to. Each individual record needs to be of type [AzHunterBase]
 
    .NOTES
        Please use this with care and for legitimate purposes. The author does not take responsibility on any damage performed as a result of employing this script.
    #>


    [CmdletBinding(
        SupportsShouldProcess=$False
    )]
    Param (
        [Parameter( 
            Mandatory=$False,
            ValueFromPipeline=$False,
            ValueFromPipelineByPropertyName=$False,
            Position=0,
            HelpMessage='AzureHunter Records'
        )]
        [ValidateNotNullOrEmpty()]
        $Records,

        [Parameter( 
            Mandatory=$False,
            ValueFromPipeline=$False,
            ValueFromPipelineByPropertyName=$False,
            Position=2,
            HelpMessage='Whether we want records returned back to the console'
        )]
        [ValidateNotNullOrEmpty()]
        [switch]$PassThru
    )

    BEGIN {
        # *** BEGIN: GENERAL *** #
        # *** Getting a handle to the running script path so that we can refer to it *** #
        if ($PSScriptRoot) {
            $ScriptPath = [System.IO.DirectoryInfo]::new($PSScriptRoot)
            if($ScriptPath.FullName -match "source"){
                $ScriptPath = $ScriptPath.Parent.Parent
            }
        } 
        else {
            $ScriptPath = [System.IO.DirectoryInfo]::new($pwd)
        }

        $PlaybookName = 'AzHunter.Playbook.LogonAnalyser'

        # Initialize Logger
        if(!$Global:Logger){ $Logger = [Logger]::New() }
        $Logger.LogMessage("[$PlaybookName] Loading Playbook", "INFO", $null, $null)
        # *** END: GENERAL *** #

        # Configure Output File
        $strTimeNow = (Get-Date).ToUniversalTime().ToString("yyMMdd-HHmmss")
        if($Global:Logger) {
            $ExportFileNameBaseDir = ([System.IO.FileInfo]::new($Global:Logger.LogFileJSON)).Directory.FullName
            $ExportFileName = "$ExportFileNameBaseDir\$($env:COMPUTERNAME)-azhunter-logonanalyser-$strTimeNow.csv"
        }
        else {
            $ExportFileName = "$($ScriptPath.Parent.FullName)\$($env:COMPUTERNAME)-azhunter-logonanalyser-$strTimeNow.csv"
        }
        
        $Logger.LogMessage("[$PlaybookName] Export File Name set to: $ExportFileName", "INFO", $null, $null)
    }

    PROCESS {
        $AzUserLoggedInRecords = $Records | Where-Object -Property Operations -eq "UserLoggedIn" | Select-Object -ExpandProperty AuditData | ConvertFrom-Json
        # Define Log Record Schema
        $UserLoggedInLogRecord = [Ordered]@{
            "ResultStatus"                  = ""
            "UserKey"                       = ""
            "UserType"                      = ""
            "Version"                       = ""
            "Workload"                      = ""
            "ClientIP"                      = ""
            "ObjectId"                      = ""
            "UserId"                        = ""
            "UserAgent"                     = ""
            "UserAuthenticationMethod"      = ""
            "AzureActiveDirectoryEventType" = ""
            "Target"                        = ""
            "TargetContextId"               = ""
            "ApplicationId"                 = ""
            "DevicePropertiesId"            = ""
            "DevicePropertiesDisplayName"   = ""
            "DevicePropertiesOS"            = ""
            "DevicePropertiesBrowserType"   = ""
            "ErrorNumber"                   = ""
        }

        [System.Collections.ArrayList]$AzUserLoggedInRecordsFlattened = @()
        ForEach($Entry in $AzUserLoggedInRecords) {

            $UserLoggedInLogRecord.ResultStatus = $Entry.ResultStatus
            $UserLoggedInLogRecord.UserKey = $Entry.UserKey
            $UserLoggedInLogRecord.UserType = $Entry.UserType
            $UserLoggedInLogRecord.Version = $Entry.Version
            $UserLoggedInLogRecord.Workload = $Entry.Workload
            $UserLoggedInLogRecord.ClientIP = $Entry.ClientIP
            $UserLoggedInLogRecord.ObjectId = $Entry.ObjectId
            $UserLoggedInLogRecord.UserId = $Entry.UserId
            $UserLoggedInLogRecord.UserAgent = $Entry.ExtendedProperties | Where-Object Name -eq UserAgent | Select-Object -ExpandProperty Value
            $UserLoggedInLogRecord.UserAuthenticationMethod = $Entry.ExtendedProperties | Where-Object Name -eq UserAuthenticationMethod | Select-Object -ExpandProperty Value
            $UserLoggedInLogRecord.AzureActiveDirectoryEventType = $Entry.AzureActiveDirectoryEventType
            $UserLoggedInLogRecord.Target = $Entry.Target.ID
            $UserLoggedInLogRecord.TargetContextId = $Entry.TargetContextId
            $UserLoggedInLogRecord.ApplicationId = $Entry.ApplicationId
            $UserLoggedInLogRecord.DevicePropertiesId = $Entry.DeviceProperties | Where-Object Name -eq Id | Select-Object -ExpandProperty Value
            $UserLoggedInLogRecord.DevicePropertiesDisplayName = $Entry.DeviceProperties | Where-Object Name -eq DisplayName | Select-Object -ExpandProperty Value
            $UserLoggedInLogRecord.DevicePropertiesOS = $Entry.DeviceProperties | Where-Object Name -eq OS | Select-Object -ExpandProperty Value
            $UserLoggedInLogRecord.DevicePropertiesBrowserType = $Entry.DeviceProperties | Where-Object Name -eq BrowserType | Select-Object -ExpandProperty Value
            $UserLoggedInLogRecord.ErrorNumber = $Entry.ErrorNumber

            $TempObj = New-Object -TypeName PSObject -Property $UserLoggedInLogRecord
            $AzUserLoggedInRecordsFlattened.Add($TempObj) | Out-Null

        }

        $Logger.LogMessage("[$PlaybookName] Exporting records to file $ExportFileName", "INFO", $null, $null)
        $AzUserLoggedInRecordsFlattened | Export-Csv $ExportFileName -NoTypeInformation -NoClobber -Append
    }

    END {
        $Logger.LogMessage("[$PlaybookName] Finished running playbook", "INFO", $null, $null)
        if($PassThru) {
            return $AzUserLoggedInRecordsFlattened
        }
        
    }

}