đ Entra ID User Inspector đ”️♂️đđŸ
đ Description
This script simplifies the process of managing Entra ID (Azure AD) users with PowerShell. It allows you to select users by name, check their sign-in logs, review Conditional Access policies, and generate a detailed HTML report—all in a step-by-step, interactive menu!
đ Features
- Search and select Entra ID users (including external guests) by name
- Retrieve and display recent sign-in logs with location and IP details
- View applicable Conditional Access policies for the selected user
- Generate a formatted HTML report saved to your desktop
- Step-by-step process ensuring all required actions are completed in order
đ ️ Prerequisites
- PowerShell installed
- Microsoft Graph PowerShell module installed (
Install-Module -Name Microsoft.Graph -Scope CurrentUser
)
# Requires the Microsoft.Graph module to be installed
# Install with: Install-Module -Name Microsoft.Graph -Scope CurrentUser
# Import the module and connect to Microsoft Graph
Import-Module Microsoft.Graph.Users
Connect-MgGraph -Scopes "User.Read.All", "AuditLog.Read.All", "Policy.Read.All"
# Function to show the menu
function Show-Menu {
Clear-Host
Write-Host "=== Entra ID Management Tool ==="
Write-Host "1. Select Entra User"
Write-Host "2. Check Logs for Selected User"
Write-Host "3. Check Conditional Access for Selected User"
Write-Host "4. Generate HTML Report"
Write-Host "5. Exit"
Write-Host "============================="
}
# Variables to track progress and selected user
$selectedUser = $null
$stepCompleted = 0 # Tracks which steps have been completed (0 = none, 1 = step 1, 2 = step 2, etc.)
# Main loop for the menu
do {
Show-Menu
$choice = Read-Host "Select an option (1-5)"
switch ($choice) {
"1" {
# Select Entra User by name (including external/guest users)
$nameInput = Read-Host "Enter the user's name (e.g., Anna)"
$users = Get-MgUser -Filter "startswith(displayName, '$nameInput')" -All -Property Id, DisplayName, UserPrincipalName, UserType |
Where-Object { $_.DisplayName -like "*$nameInput*" }
if ($users) {
Write-Host "Found the following users matching '$nameInput':"
$index = 1
$userList = @() # Temporary array to store users
foreach ($user in $users) {
$userType = if ($user.UserType -eq "Guest") { "(External Guest)" } else { "(Internal)" }
Write-Host "$index. $($user.DisplayName) - $($user.UserPrincipalName) $userType"
$userList += $user # Add user object to array
$index++
}
$userChoice = Read-Host "Select a user by number (1-$($users.Count)) or press Enter to cancel"
if ($userChoice -match '^\d+$' -and [int]$userChoice -ge 1 -and [int]$userChoice -le $users.Count) {
$selectedUser = $userList[[int]$userChoice - 1]
Write-Host "User selected: $($selectedUser.DisplayName) ($($selectedUser.UserPrincipalName))"
$stepCompleted = 1 # Mark step 1 as completed
} elseif ([string]::IsNullOrEmpty($userChoice)) {
Write-Host "Selection cancelled."
$selectedUser = $null
$stepCompleted = 0
} else {
Write-Host "Invalid selection. Please enter a number between 1 and $($users.Count)."
$selectedUser = $null
$stepCompleted = 0
}
} else {
Write-Host "No users found with a name matching '$nameInput'."
$selectedUser = $null
$stepCompleted = 0
}
Pause
}
"2" {
# Check logs for selected user
if ($stepCompleted -ge 1 -and $selectedUser) {
Write-Host "Fetching sign-in logs for $($selectedUser.DisplayName)..."
$logs = Get-MgAuditLogSignIn -Filter "UserId eq '$($selectedUser.Id)'" -Top 10
if ($logs) {
foreach ($log in $logs) {
Write-Host "Time: $($log.CreatedDateTime), Location: $($log.Location.City), $($log.Location.CountryOrRegion), IP: $($log.IpAddress)"
}
$stepCompleted = 2 # Mark step 2 as completed
} else {
Write-Host "No logs found for this user."
$stepCompleted = 2 # Still mark as completed even if no logs
}
} elseif ($stepCompleted -lt 1) {
Write-Host "You must complete option 1 (Select Entra User) before proceeding to this step."
} else {
Write-Host "No user selected. Please complete option 1 first."
}
Pause
}
"3" {
# Check Conditional Access for selected user
if ($stepCompleted -ge 2 -and $selectedUser) {
Write-Host "Fetching Conditional Access information for $($selectedUser.DisplayName)..."
$policies = Get-MgIdentityConditionalAccessPolicy
Write-Host "Applicable Conditional Access policies:"
foreach ($policy in $policies) {
if ($policy.Conditions.Users.IncludeUsers -contains $selectedUser.Id -or $policy.Conditions.Users.IncludeUsers -contains "All") {
Write-Host "Policy: $($policy.DisplayName), Status: $($policy.State)"
}
}
$stepCompleted = 3 # Mark step 3 as completed
} elseif ($stepCompleted -lt 2) {
Write-Host "You must complete option 2 (Check Logs) before proceeding to this step."
} else {
Write-Host "No user selected. Please complete option 1 first."
}
Pause
}
"4" {
if ($stepCompleted -ge 3 -and $selectedUser) {
# Build a proper HTML structure and generate a report saved to the desktop
$htmlReport = @"
<!DOCTYPE html>
<html lang="sv">
<head>
<meta charset="UTF-8">
<title>Rapport för $($selectedUser.DisplayName)</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
h1, h2 { color: #2e6c80; }
table { border-collapse: collapse; width: 80%; margin: 20px 0; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
</style>
</head>
<body>
<h1>Rapport för $($selectedUser.DisplayName)</h1>
<h2>AnvÀndarinformation</h2>
<p><strong>Namn:</strong> $($selectedUser.DisplayName)</p>
<p><strong>E-post:</strong> $($selectedUser.UserPrincipalName)</p>
<h2>Inloggningsloggar</h2>
<table>
<tr>
<th>Tid</th>
<th>Plats</th>
<th>IP-adress</th>
</tr>
"@
# Fetch and add logs
$logs = Get-MgAuditLogSignIn -Filter "UserId eq '$($selectedUser.Id)'" -Top 10
if ($logs) {
foreach ($log in $logs) {
$htmlReport += @"
<tr>
<td>$($log.CreatedDateTime)</td>
<td>$($log.Location.City), $($log.Location.CountryOrRegion)</td>
<td>$($log.IpAddress)</td>
</tr>
"@
}
} else {
$htmlReport += @"
<tr>
<td colspan="3">Inga loggar hittades.</td>
</tr>
"@
}
$htmlReport += @"
</table>
<h2>Villkorliga Ätkomstpolicyer</h2>
<table>
<tr>
<th>Policynamn</th>
<th>Status</th>
</tr>
"@
# Fetch and add policies
$policies = Get-MgIdentityConditionalAccessPolicy
$policyFound = $false
foreach ($policy in $policies) {
if ($policy.Conditions.Users.IncludeUsers -contains $selectedUser.Id -or $policy.Conditions.Users.IncludeUsers -contains "All") {
$htmlReport += @"
<tr>
<td>$($policy.DisplayName)</td>
<td>$($policy.State)</td>
</tr>
"@
$policyFound = $true
}
}
if (-not $policyFound) {
$htmlReport += @"
<tr>
<td colspan="2">Inga tillÀmpliga policyer hittades.</td>
</tr>
"@
}
# Close HTML document
$htmlReport += @"
</table>
</body>
</html>
"@
# Save report to desktop
$desktopPath = [Environment]::GetFolderPath("Desktop")
$fileName = "$desktopPath\Report_$($selectedUser.UserPrincipalName)_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"
$htmlReport | Out-File $fileName -Encoding UTF8
Write-Host "Rapport genererad pÄ skrivbordet: $fileName"
$stepCompleted = 4
} elseif ($stepCompleted -lt 3) {
Write-Host "Du mÄste slutföra alternativ 3 (Kontrollera villkorlig Ätkomst) innan du kan gÄ vidare till detta steg."
} else {
Write-Host "Ingen anvÀndare vald. Slutför alternativ 1 först."
}
Pause
}
"5" {
Write-Host "Exiting..."
Disconnect-MgGraph
return
}
default {
Write-Host "Invalid choice, please try again."
Pause
}
}
} while ($true)
đ How to Use
Copy the script above, save it as a .ps1
file (e.g., EntraIDTool.ps1
), and run it in PowerShell. Follow the menu to select a user, check logs, review policies, and generate a report. The HTML report will be saved to your desktop with a clean, formatted layout including user details, sign-in logs, and applicable Conditional Access policies—all styled with tables and a professional look!
Kommentarer
Skicka en kommentar