Advanced โฑ 150 min ๐Ÿ“‹ 10 Steps

Build an Identity Security Posture Dashboard

Create comprehensive identity security dashboards tracking MFA adoption, Conditional Access coverage, legacy authentication usage, risk remediation rates, and Identity Secure Score. Establish KPIs and design an identity maturity roadmap.

๐Ÿ“‹ Overview

About This Lab

An Identity Security Posture dashboard provides executive visibility into your organisation''s identity risk landscape. By combining Entra ID Protection metrics, Conditional Access coverage, MFA adoption rates, and Secure Score identity controls, you create a single pane of glass for identity security health and maturity tracking.

๐Ÿข Enterprise Use Case

The CISO requests a monthly identity security report showing: percentage of users with MFA, number of risky users remediated, Conditional Access policy coverage, legacy authentication usage, and progress toward passwordless authentication. The identity team must build a comprehensive dashboard that tracks these metrics and demonstrates measurable improvement.

๐ŸŽฏ What You Will Learn

  1. Review Identity Secure Score recommendations
  2. Assess MFA registration and adoption coverage
  3. Audit Conditional Access policy coverage gaps
  4. Identify legacy authentication protocol usage
  5. Track risky user remediation rates and trends
  6. Configure identity health workbooks in Sentinel
  7. Build KQL dashboards for identity posture metrics
  8. Create automated identity posture reports
  9. Establish identity security KPIs and baselines
  10. Design an identity maturity roadmap

๐Ÿ”‘ Why This Matters

You cannot improve what you don''t measure. Without an identity security posture dashboard, security teams cannot demonstrate the value of identity investments, identify coverage gaps, or track progress toward maturity goals. Executive stakeholders need quantifiable metrics to justify budget and prioritise initiatives.

✅ Prerequisites

  • Entra ID P2 license - required for Identity Protection dashboards, risk detection data, and the Identity Secure Score identity controls
  • Microsoft Sentinel workspace with the Azure Active Directory data connector enabled (for Sentinel workbook deployment)
  • Defender XDR Advanced Hunting access - Security Reader role minimum for KQL queries
  • Microsoft Graph PowerShell SDK installed with Reports.Read.All, Policy.Read.All, User.Read.All, and AuditLog.Read.All scopes
  • Azure Monitor access for dashboard pinning and workbook customisation (Monitoring Reader role minimum)
  • Completed Labs 02 and 03 - risk-based CA policies and investigation workflows should be in place before measuring their effectiveness
💡 Pro Tip: For the best dashboard experience, ensure sign-in logs are streaming to both Defender XDR (for Advanced Hunting KQL) and Microsoft Sentinel (for workbooks and Azure dashboards). The data retention in Defender XDR is 30 days by default; Sentinel offers longer retention for trend analysis.

Step 1 ยท Review Identity Secure Score

  1. Navigate to Secure Score in the Defender XDR portal
  2. Filter by Category: Identity
  3. Review top identity recommendations: MFA, CA policies, admin role protections
  4. Document current score and target improvement goals
  5. Map each recommendation to an implementation timeline

Step 2 ยท Assess MFA Adoption Coverage

MFA adoption is your most critical identity security KPI. Microsoft reports that MFA prevents 99.9% of automated identity attacks. But “MFA enabled” is not the same as “MFA used” - you need to measure both registration coverage (how many users can use MFA) and actual usage (how many sign-ins required MFA). The query below provides both metrics plus a breakdown by authentication method type.

  1. Navigate to Entra ID > Users > Per-user MFA
  2. Review the Authentication methods > Activity report for method registration counts
  3. Calculate MFA adoption rate: users with MFA registered / total users
  4. Identify users without MFA registration and target for outreach campaigns
  5. Track passwordless method adoption (FIDO2, Windows Hello, Authenticator phone sign-in)
// WHAT: MFA coverage analysis - registration rate, usage rate, and method breakdown
// WHY: Measures three critical MFA dimensions:
//   1. Registration rate: % of users who HAVE MFA registered (can they use it?)
//   2. Usage rate: % of sign-ins that REQUIRED MFA (are policies enforcing it?)
//   3. Method breakdown: which MFA methods are most used (passwordless maturity)
// TABLES: AADSignInEventsBeta, IdentityInfo
// OUTPUT: Overall MFA coverage metrics for dashboard tiles
// --- Tile 1: MFA Usage Rate (last 30 days) ---
let mfaSignIns = AADSignInEventsBeta
    | where Timestamp > ago(30d)
    | where ErrorCode == 0  // successful sign-ins only
    | where AuthenticationRequirement == "multiFactorAuthentication"
    | summarize MFACount = count();
let totalSignIns = AADSignInEventsBeta
    | where Timestamp > ago(30d)
    | where ErrorCode == 0
    | summarize TotalCount = count();
print MFAUsageRate = round(todouble(toscalar(mfaSignIns)) / todouble(toscalar(totalSignIns)) * 100, 2)
// WHAT: MFA method distribution - which authentication methods are users actually using
// WHY: Tracks passwordless maturity. The goal is to shift from SMS/phone call
//      (weakest MFA) to Authenticator push notifications to FIDO2/Windows Hello
//      (strongest, phishing-resistant). This breakdown shows your current state.
// TABLE: AADSignInEventsBeta
// KEY FIELD: AuthenticationMethodsUsed - array of methods used during sign-in
//   Common values: "Mobile app notification", "Mobile app verification code",
//   "FIDO2 security key", "Windows Hello for Business", "SMS", "Phone call"
// OUTPUT: Method popularity ranking with user counts
AADSignInEventsBeta
| where Timestamp > ago(30d)
| where ErrorCode == 0
| where AuthenticationRequirement == "multiFactorAuthentication"
| mv-expand Method = parse_json(AuthenticationMethodsUsed)
| extend MethodName = tostring(Method)
| where isnotempty(MethodName)
| summarize UsageCount = count(), UniqueUsers = dcount(AccountUpn) by MethodName
| extend MethodStrength = case(
    MethodName in ("FIDO2 security key", "Windows Hello for Business"), "Phishing-Resistant",
    MethodName == "Mobile app notification", "Strong",
    MethodName == "Mobile app verification code", "Standard",
    MethodName in ("SMS", "Phone call"), "Weak",
    "Other")
| order by UsageCount desc
💡 Pro Tip: SMS and phone call MFA are vulnerable to SIM-swapping and SS7 attacks. Set a target to migrate users from SMS/phone to Microsoft Authenticator (push notifications) as a first step, then to FIDO2 security keys or Windows Hello for phishing-resistant authentication. Track the method distribution weekly to measure progress.

Step 3 ยท Audit Conditional Access Coverage

Conditional Access policies are only effective if they evaluate every sign-in. Coverage gaps - users, apps, or scenarios not covered by any CA policy - leave attack surfaces unprotected. This audit identifies exactly where those gaps exist so you can extend policy scope.

  1. Navigate to Conditional Access > Overview
  2. Review the coverage summary: how many sign-ins are evaluated by CA policies
  3. Identify gaps: users or apps not covered by any CA policy
  4. Check for policies in Report-only mode that should be enabled
  5. Document CA policy inventory with scope, conditions, and grant controls
// WHAT: Conditional Access coverage gap analysis
// WHY: Identifies sign-ins that were NOT evaluated by any CA policy.
//      These represent unprotected sign-ins where no MFA, device compliance,
//      or risk-based controls were applied.
// TABLE: AADSignInEventsBeta
// HOW: Parses the ConditionalAccessPolicies JSON to find sign-ins where
//      every policy result was "notApplied" (no policy matched)
// OUTPUT: Top 20 apps with the most unprotected sign-ins
AADSignInEventsBeta
| where Timestamp > ago(7d)
| where ErrorCode == 0  // successful sign-ins only
| extend CAPolicies = parse_json(ConditionalAccessPolicies)
| extend PolicyCount = array_length(CAPolicies)
| extend AppliedPolicies = countof(tostring(CAPolicies), '"success"')
            + countof(tostring(CAPolicies), '"failure"')
| where AppliedPolicies == 0  // no policy applied (all "notApplied" or empty)
| summarize UncoveredSignIns = count(), UniqueUsers = dcount(AccountUpn)
    by Application
| order by UncoveredSignIns desc
| take 20
💡 Pro Tip: Target 100% CA policy coverage for all sign-ins. The most common gaps are: service accounts using legacy auth (not covered by modern-auth-only policies), third-party SaaS apps not in the CA policy scope, and guest/B2B accounts excluded from user-targeted policies. Address each gap with a dedicated CA policy.

Step 4 ยท Identify Legacy Authentication Usage

// WHAT: Identify sign-ins using legacy authentication protocols over the past 30 days
// WHY: Legacy auth protocols (POP3, IMAP, SMTP, ActiveSync, MAPI) do NOT support MFA,
//      making them a prime target for password spray and brute force attacks.
//      Identifying these helps plan migration to modern auth before blocking.
// TABLE: AADSignInEventsBeta - Entra ID sign-in logs
// KEY FIELD: ClientAppUsed - the authentication client/protocol used:
//   "Browser"                     = modern auth (web browser)
//   "Mobile Apps and Desktop clients" = modern auth (rich client)
//   "Exchange ActiveSync"         = legacy protocol (mobile email)
//   "IMAP4" / "POP3" / "SMTP"     = legacy protocols (email clients)
//   "Other clients" / "MAPI"      = legacy protocols
// OUTPUT: Count of legacy sign-ins and unique users per protocol type
AADSignInEventsBeta
| where Timestamp > ago(30d)
| where ClientAppUsed !in ("Browser", "Mobile Apps and Desktop clients")
| summarize LegacySignIns = count(), UniqueUsers = dcount(AccountUpn) by ClientAppUsed
| order by LegacySignIns desc
  1. Review legacy protocol usage: ActiveSync, POP3, IMAP, SMTP, MAPI
  2. Identify users and applications dependent on legacy protocols
  3. Create a migration plan to move users to modern authentication
  4. Create a CA policy to block legacy authentication for users ready to migrate

Step 5 ยท Track Risk Remediation Metrics

Risk remediation velocity is a key indicator of your identity security program’s maturity. Automated remediation via Conditional Access policies should handle the majority of risky users without SOC intervention. Track trends over time to measure whether your auto-remediation rate is improving and mean time to remediate (MTTR) is decreasing.

  1. Navigate to Identity Protection > Risky users
  2. Review confirmed compromised, dismissed, and remediated counts over time
  3. Calculate mean time to remediate (MTTR): time from risk detection to remediation
  4. Track auto-remediated vs. manually-remediated users
  5. Goal: 95%+ auto-remediation rate via CA policies
// WHAT: Risky user trends over 30 days - daily risk detections and unique users affected
// WHY: Tracks whether your identity risk landscape is improving or deteriorating.
//      A decreasing trend indicates effective CA policies and security training.
//      An increasing trend may indicate a targeted campaign against your tenant.
// TABLE: AADSignInEventsBeta
// KEY FIELDS:
//   RiskLevelDuringSignIn - real-time risk: none | low | medium | high
//   RiskLevelAggregated - overall user risk at time of sign-in
// OUTPUT: Daily risk detection counts by severity for trend charting
AADSignInEventsBeta
| where Timestamp > ago(30d)
| where RiskLevelDuringSignIn in ("low", "medium", "high")
| summarize
    TotalRiskySignIns = count(),
    HighRisk = countif(RiskLevelDuringSignIn == "high"),
    MediumRisk = countif(RiskLevelDuringSignIn == "medium"),
    LowRisk = countif(RiskLevelDuringSignIn == "low"),
    UniqueUsersAffected = dcount(AccountUpn)
    by bin(Timestamp, 1d)
| order by Timestamp asc
// WHAT: Auto-remediation effectiveness - CA policy remediation vs. manual admin action
// WHY: Measures what percentage of risky sign-ins are handled automatically by
//      CA policies (MFA challenge, block, password change) vs. requiring manual
//      admin investigation. Target: 95%+ auto-remediation.
// TABLE: AADSignInEventsBeta
// HOW: Sign-ins where CA policy fired (success or failure) = auto-handled.
//      Risk detections with no CA policy match = manual intervention needed.
// OUTPUT: Auto vs. manual remediation ratio
AADSignInEventsBeta
| where Timestamp > ago(30d)
| where RiskLevelDuringSignIn in ("medium", "high")
| extend AutoRemediated = iff(ConditionalAccessStatus in ("success", "failure"), true, false)
| summarize
    Total = count(),
    AutoHandled = countif(AutoRemediated),
    ManualRequired = countif(not(AutoRemediated))
    by bin(Timestamp, 1w)
| extend AutoRemediationRate = round(todouble(AutoHandled) / todouble(Total) * 100, 1)
| order by Timestamp desc
💡 Pro Tip: If your auto-remediation rate is below 80%, the most common cause is missing CA policy coverage. Users without risk-based CA policies will generate risk detections that require manual investigation. Review the coverage gap analysis from Step 3 and extend risk-based policies to all users.

Step 6 ยท Configure Identity Workbooks in Sentinel

Microsoft Sentinel workbooks provide interactive, customisable dashboards that visualise your identity security data over extended time periods. The built-in Identity Protection and Sign-in logs workbooks provide a strong starting point, but you should customise them with your organisation’s KPIs and thresholds. Use the KQL query below to build a Conditional Access effectiveness tile for your custom workbook.

  1. In Microsoft Sentinel, navigate to Workbooks > Templates
  2. Deploy the Azure AD Sign-in Logs workbook
  3. Deploy the Azure AD Identity Protection workbook
  4. Customise the workbooks with your organisation's KPIs and thresholds
  5. Pin critical charts to an Azure dashboard for executive visibility
// WHAT: Conditional Access effectiveness metrics for Sentinel workbook tile
// WHY: Provides a single dashboard view of CA policy performance:
//   - Total sign-ins evaluated by CA vs. not evaluated
//   - Block rate for high-risk sign-ins (should be ~100%)
//   - MFA challenge rate for medium-risk sign-ins
//   - Pass-through rate (sign-ins allowed without any control)
// TABLE: SigninLogs (Sentinel) or AADSignInEventsBeta (Defender XDR)
// NOTE: Use SigninLogs table if running in Sentinel workbook context
// OUTPUT: Weekly CA effectiveness summary for dashboard tile
AADSignInEventsBeta
| where Timestamp > ago(30d)
| where ErrorCode == 0 or ConditionalAccessStatus == "failure"  // include blocked sign-ins
| extend CAOutcome = case(
    ConditionalAccessStatus == "failure", "Blocked by CA",
    ConditionalAccessStatus == "success" and AuthenticationRequirement == "multiFactorAuthentication", "MFA Required",
    ConditionalAccessStatus == "success", "Allowed (controls met)",
    ConditionalAccessStatus == "notApplied", "No CA Policy",
    "Unknown")
| summarize Count = count() by CAOutcome, bin(Timestamp, 1w)
| order by Timestamp desc, Count desc
// WHAT: Legacy authentication block effectiveness - are legacy auth block policies working?
// WHY: Legacy auth protocols (IMAP, POP3, SMTP) cannot use MFA. Your CA policy
//      should be blocking 100% of legacy auth attempts. If any succeed, you have
//      a coverage gap that attackers can exploit for password spray attacks.
// OUTPUT: Legacy auth attempts that SUCCEEDED (these are the gaps to close)
AADSignInEventsBeta
| where Timestamp > ago(7d)
| where ClientAppUsed !in ("Browser", "Mobile Apps and Desktop clients")
| where ErrorCode == 0  // only successful (not blocked) legacy auth
| summarize SuccessfulLegacyAuth = count(), UniqueUsers = dcount(AccountUpn)
    by ClientAppUsed, Application
| order by SuccessfulLegacyAuth desc
💡 Pro Tip: When customising Sentinel workbooks, add conditional formatting to KPI tiles: green for targets met (e.g., MFA > 99%), yellow for near-miss (95–99%), red for below threshold (< 95%). This makes it easy for executives to spot problem areas at a glance in the Azure dashboard.

Step 7 ยท Build KQL Identity Posture Queries

// WHAT: Calculate the percentage of users authenticating with MFA
// WHY: MFA adoption rate is a critical identity security KPI.
//      Target: 99%+ of users should be using MFA regularly.
// HOW: Counts users whose sign-ins required MFA vs total user population
// KEY FIELD: AuthenticationRequirement - values:
//   "singleFactorAuthentication"    = password only (no MFA)
//   "multiFactorAuthentication"     = MFA was required and completed
// NOTE: This is a simplified calculation; some users may have MFA registered
//       but not triggered in the last 7 days. Check MFA registration separately.
let mfaUsers = AADSignInEventsBeta | where Timestamp > ago(7d) | where AuthenticationRequirement == "multiFactorAuthentication" | distinct AccountObjectId | count;
let totalUsers = IdentityInfo | distinct AccountObjectId | count;
print MFACoverage = todouble(mfaUsers) / todouble(totalUsers) * 100

Step 8 ยท Create Automated Posture Reports

Automated reporting eliminates manual data collection and ensures stakeholders receive consistent, accurate identity security metrics on a regular schedule. The PowerShell script below uses Microsoft Graph API to pull key identity posture metrics and generate a structured HTML report that can be emailed to the identity team weekly and to leadership monthly.

  1. Use Microsoft Graph API to pull identity security metrics programmatically
  2. Automate report generation with PowerShell, Power Automate, or Azure Functions
  3. Schedule weekly reports to the identity team and monthly reports to leadership
  4. Include: MFA coverage, CA coverage, risky users, legacy auth usage, Secure Score
# WHAT: Automated Identity Security Posture Report via Microsoft Graph PowerShell
# WHY: Generates a comprehensive HTML report with key identity KPIs:
#   - Total users and MFA-registered users (coverage %)
#   - Conditional Access policy inventory and status
#   - Current risky user count by risk level
#   - Identity Secure Score (current vs. max)
# SCHEDULE: Run weekly via Azure Automation or Task Scheduler
# SCOPES REQUIRED: Reports.Read.All, Policy.Read.All, IdentityRiskyUser.Read.All,
#                  SecurityEvents.Read.All, User.Read.All
# OUTPUT: HTML report saved to disk and optionally emailed

#Requires -Modules Microsoft.Graph.Reports, Microsoft.Graph.Identity.SignIns, Microsoft.Graph.Users

param(
    [string]$OutputPath = ".\IdentityPostureReport_$(Get-Date -Format 'yyyyMMdd').html",
    [string]$TenantName = "Contoso"
)

Connect-MgGraph -Scopes "Reports.Read.All","Policy.Read.All","IdentityRiskyUser.Read.All","User.Read.All" -NoWelcome

Write-Host "[1/5] Gathering user and MFA data..." -ForegroundColor Cyan
$allUsers = Get-MgUser -All -Property Id,UserPrincipalName,AccountEnabled |
    Where-Object { $_.AccountEnabled -eq $true }
$totalUsers = $allUsers.Count

# Get users with registered authentication methods (MFA-capable)
$mfaUsers = 0
foreach ($user in $allUsers | Select-Object -First 100) {  # Sample first 100 for performance
    $methods = Get-MgUserAuthenticationMethod -UserId $user.Id -ErrorAction SilentlyContinue
    if ($methods.Count -gt 1) { $mfaUsers++ }  # >1 means MFA method registered beyond password
}
$mfaRate = [math]::Round(($mfaUsers / [math]::Min(100, $totalUsers)) * 100, 1)

Write-Host "[2/5] Gathering Conditional Access policies..." -ForegroundColor Cyan
$caPolicies = Get-MgIdentityConditionalAccessPolicy -All
$caEnabled = ($caPolicies | Where-Object { $_.State -eq "enabled" }).Count
$caReportOnly = ($caPolicies | Where-Object { $_.State -eq "enabledForReportingButNotEnforced" }).Count
$caDisabled = ($caPolicies | Where-Object { $_.State -eq "disabled" }).Count

Write-Host "[3/5] Gathering risky user data..." -ForegroundColor Cyan
$riskyUsers = Get-MgRiskyUser -All
$highRisk = ($riskyUsers | Where-Object { $_.RiskLevel -eq "high" }).Count
$mediumRisk = ($riskyUsers | Where-Object { $_.RiskLevel -eq "medium" }).Count
$lowRisk = ($riskyUsers | Where-Object { $_.RiskLevel -eq "low" }).Count

Write-Host "[4/5] Building HTML report..." -ForegroundColor Cyan
$reportDate = Get-Date -Format "MMMM dd, yyyy"
$html = @"
<html><head><style>
  body { font-family: Segoe UI, sans-serif; max-width: 800px; margin: 2rem auto; }
  h1 { color: #2563eb; } h2 { color: #475569; border-bottom: 1px solid #e2e8f0; padding-bottom: .5rem; }
  .kpi { display: inline-block; padding: 1rem 2rem; margin: .5rem; border-radius: 8px; text-align: center; }
  .kpi-value { font-size: 2rem; font-weight: 700; } .kpi-label { font-size: .85rem; color: #64748b; }
  .green { background: #f0fdf4; color: #16a34a; } .red { background: #fef2f2; color: #dc2626; }
  .blue { background: #eff6ff; color: #2563eb; } .orange { background: #fff7ed; color: #ea580c; }
  table { width: 100%; border-collapse: collapse; margin-top: 1rem; }
  th, td { padding: .5rem; text-align: left; border-bottom: 1px solid #e2e8f0; }
</style></head><body>
<h1>Identity Security Posture Report</h1>
<p>$TenantName | Generated: $reportDate</p>
<h2>Key Metrics</h2>
<div class="kpi green"><div class="kpi-value">${mfaRate}%</div><div class="kpi-label">MFA Coverage (sampled)</div></div>
<div class="kpi blue"><div class="kpi-value">$totalUsers</div><div class="kpi-label">Active Users</div></div>
<div class="kpi red"><div class="kpi-value">$highRisk</div><div class="kpi-label">High Risk Users</div></div>
<div class="kpi orange"><div class="kpi-value">$mediumRisk</div><div class="kpi-label">Medium Risk Users</div></div>
<h2>Conditional Access Policies</h2>
<table><tr><th>Status</th><th>Count</th></tr>
<tr><td>Enabled</td><td>$caEnabled</td></tr>
<tr><td>Report-only</td><td>$caReportOnly</td></tr>
<tr><td>Disabled</td><td>$caDisabled</td></tr></table>
<h2>Risky Users by Level</h2>
<table><tr><th>Risk Level</th><th>Count</th></tr>
<tr><td>High</td><td>$highRisk</td></tr>
<tr><td>Medium</td><td>$mediumRisk</td></tr>
<tr><td>Low</td><td>$lowRisk</td></tr></table>
</body></html>
"@

Write-Host "[5/5] Saving report to: $OutputPath" -ForegroundColor Green
$html | Out-File -FilePath $OutputPath -Encoding UTF8
Write-Host "Report generated successfully. Open in a browser to view." -ForegroundColor Green
💡 Pro Tip: For production deployments, run this script as an Azure Automation runbook with a managed identity. Use Send-MgUserMail to automatically email the HTML report to stakeholders on a schedule. Store historical reports in Azure Blob Storage to track trends month-over-month.

Step 9 ยท Establish Identity Security KPIs

  • MFA adoption rate: target 99%+
  • CA policy coverage: target 100% of sign-ins evaluated
  • Legacy auth usage: target 0%
  • Risk remediation MTTR: target less than 1 hour
  • Passwordless adoption: target 50%+ of users
  • Identity Secure Score: target 80%+

Step 10 ยท Design an Identity Maturity Roadmap

An identity maturity roadmap provides a clear, staged path from basic identity hygiene to Zero Trust identity. Each level builds on the previous one, with measurable criteria for advancement. The KQL query below creates an executive dashboard summary tile that visualises your current posture across all key metrics in a single view.

  • Level 1 (Basic): MFA enabled, basic CA policies, Entra ID Protection enabled
  • Level 2 (Standard): Risk-based CA, legacy auth blocked, named locations, admin protection
  • Level 3 (Advanced): Passwordless authentication, continuous access evaluation, identity governance
  • Level 4 (Optimal): Zero Trust identity, automated posture management, identity threat hunting
// WHAT: Executive dashboard summary tile - all identity KPIs in one query
// WHY: Provides a single-pane-of-glass view for executive presentations.
//      Shows current values for every key identity security metric alongside
//      target thresholds, making it easy to identify gaps at a glance.
// TABLES: AADSignInEventsBeta, IdentityInfo
// OUTPUT: Single-row summary with all KPI values and RAG status
// --- Calculate all KPIs ---
let period = 7d;
let totalSignIns = toscalar(AADSignInEventsBeta | where Timestamp > ago(period) | where ErrorCode == 0 | count);
let mfaSignIns = toscalar(AADSignInEventsBeta | where Timestamp > ago(period) | where ErrorCode == 0 | where AuthenticationRequirement == "multiFactorAuthentication" | count);
let riskySignIns = toscalar(AADSignInEventsBeta | where Timestamp > ago(period) | where RiskLevelDuringSignIn in ("medium","high") | count);
let blockedByCA = toscalar(AADSignInEventsBeta | where Timestamp > ago(period) | where ConditionalAccessStatus == "failure" | count);
let legacyAuth = toscalar(AADSignInEventsBeta | where Timestamp > ago(period) | where ErrorCode == 0 | where ClientAppUsed !in ("Browser","Mobile Apps and Desktop clients") | count);
let totalUsers = toscalar(IdentityInfo | distinct AccountObjectId | count);
let riskyUsers = toscalar(AADSignInEventsBeta | where Timestamp > ago(period) | where RiskLevelDuringSignIn in ("medium","high") | distinct AccountObjectId | count);
// --- Build summary ---
print
    MFA_Usage_Rate = strcat(round(todouble(mfaSignIns) / todouble(totalSignIns) * 100, 1), "%"),
    MFA_Target = "99%+",
    Legacy_Auth_SignIns = legacyAuth,
    Legacy_Auth_Target = "0",
    Risky_SignIns_7d = riskySignIns,
    CA_Blocks_7d = blockedByCA,
    Risky_Users_Active = riskyUsers,
    Total_Users = totalUsers,
    Risk_Exposure = strcat(round(todouble(riskyUsers) / todouble(totalUsers) * 100, 2), "%")
💡 Pro Tip: Import this executive summary query into a Sentinel workbook with tile visualisation. Use the print output to populate KPI tiles with conditional formatting (green/yellow/red based on thresholds). This becomes the “identity health scorecard” that the CISO reviews monthly.

Summary

What You Accomplished

  • Reviewed Identity Secure Score and created improvement plans
  • Assessed MFA adoption, CA coverage, and legacy auth usage
  • Built KQL dashboards and Sentinel workbooks for identity posture
  • Established identity security KPIs with measurable targets
  • Designed an identity maturity roadmap from basic to optimal

Next Steps

  • Deploy passwordless authentication methods (FIDO2, Windows Hello)
  • Implement Entra ID Governance for access reviews and entitlement management
  • Integrate identity posture data with Compliance Manager for regulatory reporting

📚 Documentation Resources

ResourceDescription
Sign-in Logs ReferenceDetailed schema and field descriptions for Entra ID sign-in logs
Authentication Methods ActivityMFA registration and usage reporting in Entra ID
CA Insights & ReportingConditional Access workbook for policy impact analysis
Sentinel: Entra ID ConnectorStream Entra ID sign-in and audit logs to Sentinel for workbooks
Graph API: Security DefaultsProgrammatic access to identity security configuration
Identity Secure ScoreTrack and improve identity security posture with actionable recommendations
โ† Previous Lab All Labs โ†’