Skip to content

Commit

Permalink
Create Get-HawUserEntraSignInLog and modify Get-HawkUserAuthHistory t…
Browse files Browse the repository at this point in the history
…o Get-HawkUserUALSignInLog for clear distinction between functions.
  • Loading branch information
jonnybottles committed Jan 25, 2025
1 parent fb4dd4b commit 7fee0d3
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 120 deletions.
4 changes: 2 additions & 2 deletions Hawk/Hawk.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
'Get-HawkTenantConsentGrant',
'Get-HawkTenantRBACChange',
'Get-HawkTenantAzureAppAuditLog',
'Get-HawkUserAuthHistory',
'Get-HawkUserUALSignInLog',
'Get-HawkUserConfiguration',
'Get-HawkUserEmailForwarding',
'Get-HawkUserInboxRule',
Expand Down Expand Up @@ -89,7 +89,7 @@
'Get-HawkTenantDomainActivity',
'Get-HawkTenantEDiscoveryLog',
'Get-HawkUserSharePointSearchQuery',
'Get-HawkTenantEntraSignInLog'
'Get-HawkUserEntraSignInLog'

# Cmdlets to export from this module
# CmdletsToExport = ''
Expand Down
111 changes: 0 additions & 111 deletions Hawk/functions/Tenant/Get-HawkTenantEntraSignInLog.ps1

This file was deleted.

132 changes: 132 additions & 0 deletions Hawk/functions/User/Get-HawkUserEntraSignInLog.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
Function Get-HawkUserEntraSignInLog {
<#
.SYNOPSIS
Retrieves medium and high risk Microsoft Entra ID sign-in logs for a specific user using Microsoft Graph.
.DESCRIPTION
This function retrieves risky sign-in logs from Microsoft Entra ID (formerly Azure AD)
for specific users using the Microsoft Graph API. It collects sign-ins that were marked as
medium or high risk either during sign-in or after aggregated risk analysis.
The function:
- Filters for medium and high risk sign-ins at the API level
- Automatically handles pagination of large result sets
- Displays progress during data collection
- Exports data in both CSV and JSON formats
- Uses the configured Hawk date range
.PARAMETER UserPrincipalName
Single UPN of a user, comma-separated list of UPNs, or array of objects that contain UPNs.
.OUTPUTS
File: RiskySignInLog.csv/.json
Path: \<User>
Description: Medium and high risk sign-in logs for the specified user(s)
.EXAMPLE
Get-HawkUserEntraSignInLog -UserPrincipalName [email protected]
Retrieves risky sign-in logs for the specified user from the configured Hawk time window.
.EXAMPLE
Get-HawkUserEntraSignInLog -UserPrincipalName "[email protected]","[email protected]"
Retrieves risky sign-in logs for multiple users.
.NOTES
Requires Microsoft.Graph.Authentication module
Requires appropriate Microsoft Graph permissions (AuditLog.Read.All)
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[array]$UserPrincipalName
)

BEGIN {
if (Test-HawkGlobalObject) {
Initialize-HawkGlobalObject
}

$startTime = Get-Date
Out-LogFile "Gathering Microsoft Entra ID Sign-in Logs" -Action
Test-GraphConnection
Send-AIEvent -Event "CmdRun"
[array]$UserArray = Test-UserObject -ToTest $UserPrincipalName
}

PROCESS {
foreach ($Object in $UserArray) {
[string]$User = $Object.UserPrincipalName

try {
Out-LogFile ("Retrieving sign-in logs for " + $User) -Action

# Filter just on user - get all sign-ins
$filter = "userPrincipalName eq '$User'"

$processedCount = 0
$signInLogs = Get-MgAuditLogSignIn -Filter $filter -All -ErrorAction Stop

foreach ($log in $signInLogs) {
$processedCount++
if ($processedCount % 100 -eq 0) {
Write-Progress -Activity "Retrieving Entra Sign-in Logs" `
-Status "Processed $processedCount logs" `
-PercentComplete -1
}
}

Write-Progress -Activity "Retrieving Entra Sign-in Logs" -Completed

if ($signInLogs.Count -gt 0) {
Out-LogFile ("Retrieved " + $signInLogs.Count + " sign-in log entries for " + $User) -Information

# Write all logs to CSV/JSON
$signInLogs | Out-MultipleFileType -FilePrefix "EntraSignInLog_$User" -User $User -csv -json

# Check for risky sign-ins
$riskySignIns = $signInLogs | Where-Object {
$_.RiskLevelDuringSignIn -in @('high', 'medium') -or
$_.RiskLevelAggregated -in @('high', 'medium')
}

if ($riskySignIns.Count -gt 0) {
# Flag for investigation
Out-LogFile ("Found " + $riskySignIns.Count + " risky sign-ins for " + $User) -notice

# Group and report risk levels
$duringSignIn = $riskySignIns | Group-Object -Property RiskLevelDuringSignIn |
Where-Object {$_.Name -in @('high', 'medium')}
foreach ($risk in $duringSignIn) {
Out-LogFile ("Found " + $risk.Count + " sign-ins with risk level during sign-in: " + $risk.Name) -silentnotice
}

$aggregated = $riskySignIns | Group-Object -Property RiskLevelAggregated |
Where-Object {$_.Name -in @('high', 'medium')}
foreach ($risk in $aggregated) {
Out-LogFile ("Found " + $risk.Count + " sign-ins with aggregated risk level: " + $risk.Name) -silentnotice
}

Out-LogFile ("Review SignInLog.csv/json in the " + $User + " folder for complete details") -silentnotice
}
}
else {
Out-LogFile ("No sign-in logs found for " + $User + " in the specified time period") -Information
}
}
catch {
Out-LogFile ("Error retrieving sign-in logs for " + $User + " : " + $_.Exception.Message) -isError
Write-Error -ErrorRecord $_ -ErrorAction Continue
}
}
}

END {
Out-LogFile "Completed exporting Entra sign-in logs" -Information
$endTime = Get-Date
$duration = $endTime - $startTime
$formattedDuration = ("Total Runtime: {0:N0} minutes {1} seconds" -f [math]::Floor($duration.TotalMinutes), $duration.Seconds)
Out-LogFile $formattedDuration -Information
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Function Get-HawkUserAuthHistory {
Function Get-HawkUserUALSignInLog {
<#
.SYNOPSIS
Gathers ip addresses that logged into the user account
Expand All @@ -20,13 +20,13 @@
Description: All authentication activity for the user in a more readable form
.EXAMPLE
Get-HawkUserAuthHistory -UserPrincipalName [email protected] -ResolveIPLocations
Get-HawkUserUALSignInLog -UserPrincipalName [email protected] -ResolveIPLocations
Gathers authentication information for [email protected].
Attempts to resolve the IP locations for all authentication IPs found.
.EXAMPLE
Get-HawkUserAuthHistory -UserPrincipalName (get-mailbox -Filter {Customattribute1 -eq "C-level"}) -ResolveIPLocations
Get-HawkUserUALSignInLog -UserPrincipalName (get-mailbox -Filter {Customattribute1 -eq "C-level"}) -ResolveIPLocations
Gathers authentication information for all users that have "C-Level" set in CustomAttribute1
Attempts to resolve the IP locations for all authentication IPs found.
Expand Down
6 changes: 3 additions & 3 deletions Hawk/functions/User/Start-HawkUserInvestigation.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,9 @@
Get-HawkUserAutoReply -User $User
}

if ($PSCmdlet.ShouldProcess("Running Get-HawkUserAuthHistory for $User")) {
Out-LogFile "Running Get-HawkUserAuthHistory" -Action
Get-HawkUserAuthHistory -User $User -ResolveIPLocations
if ($PSCmdlet.ShouldProcess("Running Get-HawkUserUALSignInLog for $User")) {
Out-LogFile "Running Get-HawkUserUALSignInLog" -Action
Get-HawkUserUALSignInLog -User $User -ResolveIPLocations
}

if ($PSCmdlet.ShouldProcess("Running Get-HawkUserMailboxAuditing for $User")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,6 @@
Out-LogFile -string ("{0} = {1}" -f $prop.Name, $value) -Information
}

Out-LogFile "`Happy hunting! 🦅`n" -action
Out-LogFile "`Happy hunting! 🦅`n" -Information
}
}

0 comments on commit 7fee0d3

Please sign in to comment.