🌟 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

  1. PowerShell installed
  2. Microsoft Graph PowerShell module installed (Install-Module -Name Microsoft.Graph -Scope CurrentUser)

PowerShell Script

# 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

PopulÀra inlÀgg i den hÀr bloggen

🚀 IntuneWin – Deploying Win32 Apps via Intune 🎯

Block Personal devices to acces to Desktop apps like teams, Onedrive etc and how to troubleshooting the issue.

🔧 Microsoft 365 Apps Admin Center: Tips & Tricks