Introduction
On this article, we’ll stroll by means of the best way to discover and analyze Conditional Entry knowledge in Microsoft Entra utilizing the Developer Instruments in your browser. The aim of this walkthrough is to exhibit how one can establish and extract the required Microsoft Graph API calls immediately from the Entra portal, offering a basis for automating this course of with PowerShell.
We’ll begin by analyzing the Conditional Entry Coverage Abstract dashboard and the “See all unprotected sign-ins” function to grasp how these sign-ins are logged. By leveraging Developer Mode, we’ll hint the underlying API calls, dissect the filters used, and perceive how these requests are structured. This data permits us to recreate these calls utilizing Microsoft Graph API and automate them with PowerShell.
This information is right for IT directors and PowerShell fans who need to streamline tenant monitoring, automate their duties, and dive deeper into how Entra operates behind the scenes. Let’s get began!
Clicking by means of the tenant
Whereas exploring my Entra Take a look at Tenant, I stumbled upon an fascinating function within the Conditional Entry Coverage Abstract dashboard: a hyperlink labeled “See all unprotected sign-ins”. Naturally, I wished to dive in and discover additional.
After I clicked the hyperlink, I initially didn’t see any entries for interactive person sign-ins—which, relying on the way you take a look at it, might be both or a foul factor. Nevertheless, switching to non-interactive sign-ins revealed an inventory of entries!
Significance of Monitoring Signal-In Habits
-
Safety Posture: Figuring out potential safety dangers by understanding how customers entry sources helps defend in opposition to unauthorized entry.
-
Coverage Compliance: Guaranteeing that Conditional Entry insurance policies are enforced and detecting non-compliance points.
-
Anomaly Detection: Recognizing uncommon exercise, corresponding to logins from sudden areas, can point out account compromise.
🤩 Our Wonderful Sponsors 👇
-
Useful resource Utilization: Understanding the distribution of interactive vs. non-interactive sign-ins informs selections about useful resource allocation and person expertise.
Distinction Between Interactive and Non-Interactive Signal-Ins
-
Interactive Signal-Ins: Happen when a person actively logs in through a person interface (e.g., coming into credentials). This means person engagement.
-
Non-Interactive Signal-Ins: Occur mechanically, usually by means of scripts or providers with out person enter. They’re important for background processes requiring useful resource entry.
Monitoring each sign-in sorts supplies a complete view of person habits and entry patterns, enhancing safety and compliance administration.
On this weblog put up, I will take you thru my journey of analyzing the net interface, extracting the required info, and changing it into native Microsoft Graph API calls. We’ll then automate this course of utilizing PowerShell to extract the outcomes as objects.
Discovering the Information Supply
The primary query I requested myself was: The place can I discover the supply of the data I am in search of? A easy search engine question may work, however since I used to be already within the Entra portal, I made a decision to discover the info immediately from the portal itself.
To do that, I opened the Developer Instruments in my browser, switched to the Community tab, and filtered on ‘Fetch/XHR’.
After organising the Developer Instruments, I clicked on ‘Consumer sign-ins (interactive)’ once more. Regardless that no outcomes appeared, I may nonetheless see the requests made within the background. Amid all of the telemetry and token requests, there was one particular request that caught my consideration.
Analyzing the Request
Within the Headers part of the request, I found that it known as the endpoint:
https://graph.microsoft.com/beta/auditLogs/signalIns
Good. This gave us a stable place to begin. Moreover, I may see which filters had been utilized, which is crucial for our use case. Nevertheless, as URLs are sometimes encoded and onerous to learn, I switched to the Payload tab. This offered a extra readable model of the filter:
(createdDateTime ge 2024-10-10T22:00:00.000Z and createdDateTime lt 2024-10-17T22:00:00.000Z and (standing/errorCode eq 0 or (standing/errorCode ne 16000 and standing/errorCode ne 16001 and standing/errorCode ne 16003 and standing/errorCode ne 29200 and standing/errorCode ne 50019 and standing/errorCode ne 50055 and standing/errorCode ne 50058 and standing/errorCode ne 50059 and standing/errorCode ne 50072 and standing/errorCode ne 50074 and standing/errorCode ne 50076 and standing/errorCode ne 50097 and standing/errorCode ne 50125 and standing/errorCode ne 50127 and standing/errorCode ne 50129 and standing/errorCode ne 50140 and standing/errorCode ne 50143 and standing/errorCode ne 50144 and standing/errorCode ne 50158 and standing/errorCode ne 50209 and standing/errorCode ne 51006 and standing/errorCode ne 52004 and standing/errorCode ne 65001 and standing/errorCode ne 81010 and standing/errorCode ne 81012 and standing/errorCode ne 81014 and standing/errorCode ne 165100 and standing/errorCode ne 502031 and standing/errorCode ne 50203 and standing/errorCode ne 9002341)) and conditionalAccessStatus eq microsoft.graph.conditionalAccessStatus'notApplied')
This filter ignores sure error codes and focuses on a selected conditionalAccessStatus: 'notApplied'
. With this info, I knew we may construct a local PowerShell name. Virtually there—however not fairly!
Investigating Non-Interactive Signal-Ins
We additionally want to collect knowledge on non-interactive sign-ins. Clicking on the corresponding possibility within the portal once more revealed a special request:
https:
Although it appeared comparable, that is truly the Azure AD Graph endpoint (graph.home windows.web
), which is deprecated. Microsoft recommends utilizing the Microsoft Graph API, as detailed of their migration information right here.
Constructing the Microsoft Graph Question
To change over to Microsoft Graph for non-interactive sign-ins, we have to tweak our filter. Luckily, I encountered the same state of affairs beforehand after I wanted to export sign-in logs for enterprise functions. Right here’s the filter that targets non-interactive sign-ins:
signInEventTypes/any(t: t ne 'interactiveUser')
Now, we are able to mix this extra filter with our present question:
(createdDateTime ge 2024-10-10T22:00:00.000Z and createdDateTime lt 2024-10-17T22:00:00.000Z and (standing/errorCode eq 0 or (standing/errorCode ne 16000 and standing/errorCode ne 16001 and standing/errorCode ne 16003 and standing/errorCode ne 29200 and standing/errorCode ne 50019 and standing/errorCode ne 50055 and standing/errorCode ne 50058 and standing/errorCode ne 50059 and standing/errorCode ne 50072 and standing/errorCode ne 50074 and standing/errorCode ne 50076 and standing/errorCode ne 50097 and standing/errorCode ne 50125 and standing/errorCode ne 50127 and standing/errorCode ne 50129 and standing/errorCode ne 50140 and standing/errorCode ne 50143 and standing/errorCode ne 50144 and standing/errorCode ne 50158 and standing/errorCode ne 50209 and standing/errorCode ne 51006 and standing/errorCode ne 52004 and standing/errorCode ne 65001 and standing/errorCode ne 81010 and standing/errorCode ne 81012 and standing/errorCode ne 81014 and standing/errorCode ne 165100 and standing/errorCode ne 502031 and standing/errorCode ne 50203 and standing/errorCode ne 9002341)) and conditionalAccessStatus eq microsoft.graph.conditionalAccessStatus'notApplied' and signInEventTypes/any(t: t ne 'interactiveUser'))
Automating the Course of with PowerShell
With all this info at hand, we are able to now create a dynamic PowerShell operate. The operate ought to permit:
- Deciding on interactive and non-interactive sign-ins.
- Specifying the date vary.
- Utilizing concise itemizing for error codes to maintain the script readable.
- Deciding on unprotected or protected sign-ins.
Right here’s the ultimate PowerShell operate:
present on Github
In Motion
Get-ConditionalAccessSignIn -StartDate $((Get-Date).AddDays(-30)) -EndDate $(Get-Date) -SignInType non-Interactive -Unprotected | choose UserDisplayname,appDisplayname,CreatedDatetime, @{n="ErrorCode";e={$_.Standing.errorCode}},@{n="Purpose";e={$_.Standing.failureReason}},signInEventTypes,ConditionalAccessStatus
The Code
operate Get-ConditionalAccessSignIn {
[CmdletBinding()]
param (
[switch] $Unprotected,
[Parameter(Mandatory=$true)]
[datetime] $StartDate,
[Parameter(Mandatory=$true)]
[datetime] $EndDate,
[ValidateSet("Interactive", "Non-Interactive")]
[string[]] $SignInType = "Interactive"
)
start {
if($Unprotected){
$ConditionalAccessStatus = "NotApplied"
}else{
$ConditionalAccessStatus = "Success"
}
if($EndDate -lt $StartDate.AddDays(1)){
throw "Finish date should be no less than 1 day after startdate"
return
}
$IgnorableUnprotectedStatusErrorCodes = @(
9002341, 502031, 50209,
50203, 52004, 51006,
50158, 50144, 50143,
50140, 50129, 50127,
50125, 50097, 50076,
50074, 50072, 50059,
50058, 50055, 50019,
29200, 165100, 16003,
16001, 16000, 81014,
81012, 81010, 65001
)
}
course of {
$returnObject = foreach($SignInTypeObject in @($SignInType)){
$Filter = "(createdDateTime ge $($StartDate.ToString("yyyy-MM-dd"))T22:00:00.000Z and createdDateTime lt $($EndDate.ToString("yyyy-MM-dd"))T22:00:00.000Z)"
$Filter += " and (standing/errorCode eq 0 or ($($IgnorableUnprotectedStatusErrorCodes.ForEach({
"standing/errorCode ne $_"
})-join " and ")))"
if($SignInTypeObject -eq 'Non-Interactive'){
$Filter += " and (signInEventTypes/any(t: t ne 'interactiveUser'))"
}else {
$Filter += " and (signInEventTypes/any(t: t eq 'interactiveUser')"
}
$Filter += " and (conditionalAccessStatus eq '$ConditionalAccessStatus')"
Invoke-MgGraphRequest -Technique Get -Uri ("https://graph.microsoft.com/beta/auditLogs/signIns?`$Filter=$Filter") -OutputType PSObject
Write-Verbose "Path: https://graph.microsoft.com/beta/auditLogs/signIns"
Write-Verbose "Filter: $Filter"
}
}
finish {
return $returnObject.Worth
}
}
This operate streamlines the method, permitting you to drag detailed sign-in knowledge immediately by means of Microsoft Graph without having to navigate the portal manually. That is particularly helpful for large-scale tenant monitoring or automation duties!
Conclusion
Exploring and automating tenant monitoring with PowerShell and Microsoft Graph opens up numerous alternatives. By digging into the net interface and changing the queries into native API calls, we not solely save time but additionally achieve extra flexibility and energy over our knowledge.
Joyful scripting!
Christian Ritter