User/Get-HawkUserAuthHistory.ps1
# TODO: Filter out successful logons and report those seperate from full list # With that possibily include a "expected region" to do more filtering? # Maybe a seperate function for that? Function Get-HawkUserAuthHistory { param ( [Parameter(Mandatory = $true)] [array]$UserPrincipalName, [switch]$ResolveIPLocations ) Test-EXOConnection # Verify our UPN input [array]$UserArray = Test-UserObject -ToTest $UserPrincipalName foreach ($Object in $UserArray) { [string]$User = $Object.UserPrincipalName # Make sure our array is null [array]$UserLogonLogs = $null Out-LogFile ("Retrieving Logon History for " + $User) -action # Get back the account logon logs for the user $UserLogonLogs = Get-AllUnifiedAuditLogEntry -UnifiedSearch ("Search-UnifiedAuditLog -ObjectIds " + $User + " -RecordType AzureActiveDirectoryAccountLogon") # Expand out the AuditData and convert from JSON $ExpandedUserLogonLogs = $UserLogonLogs | Select-object -ExpandProperty AuditData | ConvertFrom-Json # Get only the unique IP addresses and report them [array]$LogonIPs = $ExpandedUserLogonLogs | Select-Object -Unique -Property ClientIP Out-LogFile ("Found " + $LogonIPs.count + " Unique IPs connecting to this user") $LogonIPs | Out-MultipleFileType -fileprefix "Logon_IPAddresses" -User $user -csv # Make sure we have some logons before we process them if ($null -eq $LogonIPs) { Out-LogFile ("No logons found") } # If we do then process the logon objects further else { # Set our Output array to null [array]$Output = $Null # if we have the resolve ip locations switch then we need to resolve the ip address to the location if ($ResolveIPLocations) { # Make sure our arrays are null [array]$IPLocations = $null $i = 0 $EstimatedLookupTime = [int]($LogonIPs.Count * 1.5) # Loop thru each connection and get the location Foreach ($connection in $ExpandedUserLogonLogs) { Write-Progress -Activity "Looking Up Ip Address Locations" -CurrentOperation $connection.ClientIP -PercentComplete (($i / $ExpandedUserLogonLogs.count) * 100) -Status ("Approximate Max Run time " + $EstimatedLookupTime + " seconds") # Get the location information for this IP address $Location = Get-IPGeolocation -ipaddress $connection.clientip # Add all of the locations for this user to an array of locations [array]$IPLocations += $Location # Combine the connection object and the location object so that we have a single output ready $Output += $connection | Select-Object -Property *, @{Name = "CountryName"; Expression = {$Location.CountryName}}, @{Name = "RegionCode"; Expression = {$Location.RegionCode}}, @{Name = "RegionName"; Expression = {$Location.RegionName}}, @{Name = "City"; Expression = {$Location.City}}, @{Name = "ZipCode"; Expression = {$Location.ZipCode}}, @{Name = "KnownMicrosoftIP"; Expression = {$Location.KnownMicrosoftIP}} # increment our counter for the progress bar $i++ } Write-Progress -Completed -Activity "Looking Up Ip Address Locations" -Status " " Out-LogFile "Writing Logon sessions with IP Locations" $Output | Out-MultipleFileType -fileprefix "Logon_Events_With_Locations" -User $User -csv -xml $Output | Where-Object {$_.LoginStatus -eq '0'} | Out-MultipleFileType -FilePrefix "Successful_Logon_Events_With_Locations" -User $User -csv -xml Out-LogFile "Writing List of unique logon locations" Select-UniqueObject -ObjectArray $IPLocations -Property ip | Out-MultipleFileType -fileprefix "Logon_Locations" -user $user -csv -txt $Global:IPlocationCache | Out-MultipleFileType -FilePrefix "All_Logon_Locations" -csv } # if we don't have the lookup ip address switch then ouput just = our existing data else { $Output = $ExpandedUserLogonLogs Out-LogFile "Writing Logon Session" $Output | Out-MultipleFileType -fileprefix "Logon_Events" -User $user -csv -xml $Output | Where-Object {$_.LoginStatus -eq '0'} | Out-MultipleFileType -FilePrefix "Successful_Logon_Events" -User $User -csv -xml } } } <# .SYNOPSIS Gathers ip addresses that logged onto the user account .DESCRIPTION Pulls AzureActiveDirectoryAccountLogon events from the unified audit log for the provided user. If used with -ResolveIPLocations: Attempts to resolve the IP location using freegeoip.net Will flag ip addresses that are known to be owned by Microsoft using the XML from: https://support.office.com/en-us/article/URLs-and-IP-address-ranges-for-Office-365-operated-by-21Vianet-5C47C07D-F9B6-4B78-A329-BFDC1B6DA7A0 .PARAMETER UserPrincipalName Single UPN of a user, commans seperated list of UPNs, or array of objects that contain UPNs. .OUTPUTS File: Logon_IPAddresses.csv Path: \<User> Description: All unique logon IP addresses for this user. File: Logon_IPAddresses.txt Path: \<User> Description: All unique logon IP addresses for this user. File: Logon_IPAddresses.txt Path: \<User> Description: All unique logon IP addresses for this user. ==== If -ResolveIPLocations is specified. ==== File: Logon_Events_With_Locations.csv Path: \<User> Description: List of all logon events with the location discovered for the IP and if it is a Microsoft IP. File: Logon_Events_With_Locations.xml Path: \<User>\XML Description: List of all logon events with the location discovered for the IP and if it is a Microsoft IP in CLI XML. File: Successful_Logon_Events_With_Locations.csv Path: \<User> Description: List of all logon events that had LoginStatus = 0. Includes the location discovered for the IP and if it is a Microsoft IP. File: Successful_Logon_Events_With_Locations.xml Path: \<User>\XML Description: List of all logon events that had LoginStatus = 0. Includes the location discovered for the IP and if it is a Microsoft IP in CLI XML. File: All_Logon_Locations.csv Path: \ Description: All ip addresses and their resolved locations for all users investigated. File: All_Logon_Locations.txt Path: \ Description: All ip addresses and their resolved locations for all users investigated. ==== If -ResolveIPLocations is NOT specified. ==== File: Logon_Events.csv Path: \<User> Description: All logon events that were found. File: Logon_Events.xml Path: \<User>\XML Description: All logon events that were found in CLI XML. File: Successful_Logon_Events.csv Path: \<User> Description: All logon events that had LoginStatus = 0. File: Successful_Logon_Events.xml Path: \<User>\XML Description: All logon events that had LoginStatus = 0 in CLI XML. .EXAMPLE Get-HawkUserAuthHistory -UserPrincipalName user@contoso.com -ResolveIPLocations Gathers authenication information for user@contoso.com. Attempts to resolve the IP locations for all authetnication IPs found. .EXAMPLE Get-HawkUserAuthHistory -UserPrincipalName (get-mailbox -Filter {Customattribute1 -eq "C-level"}) -ResolveIPLocations Gathers authenication information for all users that have "C-Level" set in CustomAttribute1 Attempts to resolve the IP locations for all authetnication IPs found. #> } |