diff --git a/Azure/Export-CAPolicies.ps1 b/Azure/Export-CAPolicies.ps1 new file mode 100644 index 0000000..a8a357f --- /dev/null +++ b/Azure/Export-CAPolicies.ps1 @@ -0,0 +1,56 @@ +<# + .SYNOPSIS + Export-CAPolicies.ps1 + + .DESCRIPTION + Export Conditional Access policies to JSON files for backup purposes. + + .LINK + www.alitajran.com/export-conditional-access-policies/ + + .NOTES + Written by: ALI TAJRAN + Website: www.alitajran.com + LinkedIn: linkedin.com/in/alitajran + + .CHANGELOG + V1.00, 11/16/2023 - Initial version + V1.10, 03/23/2026 - Skip Microsoft-managed policies on export +#> + +# Connect to Microsoft Graph API +Connect-MgGraph -Scopes 'Policy.Read.All' -NoWelcome + +# Export path for CA policies +$ExportPath = "C:\temp" + +try { + # Retrieve all conditional access policies from Microsoft Graph API + $AllPolicies = Get-MgIdentityConditionalAccessPolicy -All + + if ($AllPolicies.Count -eq 0) { + Write-Host "There are no CA policies found to export." -ForegroundColor Yellow + } + else { + # Iterate through each policy + foreach ($Policy in $AllPolicies) { + try { + # Skip Microsoft-managed policies + if ($Policy.DisplayName -like 'Microsoft-managed:*') { + Write-Host "Skipped Microsoft-managed policy: $($Policy.DisplayName)" -ForegroundColor Cyan + continue + } + $PolicyName = $Policy.DisplayName -replace '[\\/:*?"<>|]', '' + $PolicyJSON = $Policy | ConvertTo-Json -Depth 6 + $PolicyJSON | Out-File "$ExportPath\$PolicyName.json" -Force + Write-Host "Successfully backed up CA policy: $($Policy.DisplayName)" -ForegroundColor Green + } + catch { + Write-Host "Error occurred while backing up CA policy: $($Policy.DisplayName). $($_.Exception.Message)" -ForegroundColor Red + } + } + } +} +catch { + Write-Host "Error occurred: $($_.Exception.Message)" -ForegroundColor Red +} \ No newline at end of file diff --git a/Azure/Get-MFAReport.ps1 b/Azure/Get-MFAReport.ps1 new file mode 100644 index 0000000..a496018 --- /dev/null +++ b/Azure/Get-MFAReport.ps1 @@ -0,0 +1,122 @@ +<# + .SYNOPSIS + Get-MFAReport.ps1 + + .DESCRIPTION + Export Microsoft 365 per-user MFA report with Micrososoft Graph PowerShell. + + .LINK + www.alitajran.com/export-office-365-users-mfa-status-with-powershell/ + + .NOTES + Written by: ALI TAJRAN + Website: www.alitajran.com + LinkedIn: linkedin.com/in/alitajran + + .CHANGELOG + V1.00, 04/04/2021 - Initial version + V2.00, 08/04/2024 - Rewritten for Microsoft Graph PowerShell +#> + +# Connect to Microsoft Graph with the required scopes +Connect-MgGraph -Scopes "User.Read.All", "Policy.ReadWrite.AuthenticationMethod", "UserAuthenticationMethod.Read.All" + +# CSV export file path +$CSVfile = "C:\temp\MFAUsers.csv" + +# Get properties +$Properties = @( + 'Id', + 'DisplayName', + 'UserPrincipalName', + 'UserType', + 'Mail', + 'ProxyAddresses', + 'AccountEnabled', + 'CreatedDateTime' +) + +# Get all users +[array]$Users = Get-MgUser -All -Property $Properties | Select-Object $Properties + +# Initialize the report list +$Report = [System.Collections.Generic.List[Object]]::new() + +# Check if any users were retrieved +if (-not $Users) { + Write-Host "No users found. Exiting script." -ForegroundColor Red + return +} + +# Initialize progress counter +$counter = 0 +$totalUsers = $Users.Count + +# Loop through each user and get their MFA settings +foreach ($User in $Users) { + $counter++ + + # Calculate percentage completion + $percentComplete = [math]::Round(($counter / $totalUsers) * 100) + + # Define progress bar parameters with user principal name + $progressParams = @{ + Activity = "Processing Users" + Status = "User $($counter) of $totalUsers - $($User.UserPrincipalName) - $percentComplete% Complete" + PercentComplete = $percentComplete + } + + Write-Progress @progressParams + + # Get MFA settings + $MFAStateUri = "https://graph.microsoft.com/beta/users/$($User.Id)/authentication/requirements" + $Data = Invoke-MgGraphRequest -Uri $MFAStateUri -Method GET + + # Get the default MFA method + $DefaultMFAUri = "https://graph.microsoft.com/beta/users/$($User.Id)/authentication/signInPreferences" + $DefaultMFAMethod = Invoke-MgGraphRequest -Uri $DefaultMFAUri -Method GET + + # Determine the MFA default method + if ($DefaultMFAMethod.userPreferredMethodForSecondaryAuthentication) { + $MFAMethod = $DefaultMFAMethod.userPreferredMethodForSecondaryAuthentication + Switch ($MFAMethod) { + "push" { $MFAMethod = "Microsoft authenticator app" } + "oath" { $MFAMethod = "Authenticator app or hardware token" } + "voiceMobile" { $MFAMethod = "Mobile phone" } + "voiceAlternateMobile" { $MFAMethod = "Alternate mobile phone" } + "voiceOffice" { $MFAMethod = "Office phone" } + "sms" { $MFAMethod = "SMS" } + Default { $MFAMethod = "Unknown method" } + } + } + else { + $MFAMethod = "Not Enabled" + } + + # Filter only the aliases + $Aliases = ($User.ProxyAddresses | Where-Object { $_ -clike "smtp*" } | ForEach-Object { $_ -replace "smtp:", "" }) -join ', ' + + # Create a report line for each user + $ReportLine = [PSCustomObject][ordered]@{ + UserPrincipalName = $User.UserPrincipalName + DisplayName = $User.DisplayName + MFAState = $Data.PerUserMfaState + MFADefaultMethod = $MFAMethod + PrimarySMTP = $User.Mail + Aliases = $Aliases + UserType = $User.UserType + AccountEnabled = $User.AccountEnabled + CreatedDateTime = $User.CreatedDateTime + } + $Report.Add($ReportLine) +} + +# Complete the progress bar +Write-Progress -Activity "Processing Users" -Completed + +# Display the report in a grid view +$Report | Out-GridView -Title "Microsoft 365 per-user MFA Report" + +# Export the report to a CSV file +$Report | Export-Csv -Path $CSVfile -NoTypeInformation -Encoding utf8 +Write-Host "Microsoft 365 per-user MFA Report is in $CSVfile" -ForegroundColor Cyan \ No newline at end of file