Public/Permissions/Invoke-365TuneTestExchange.ps1
|
function Invoke-365TuneTestExchange { <# .SYNOPSIS Tests whether Exchange Online permissions are correctly assigned to the 365TUNE Enterprise App. .DESCRIPTION Checks that the 365TUNE Service Principal is registered in Exchange Online and has the View-Only Configuration management role assigned. Read-only - makes no changes. .EXAMPLE Invoke-365TuneTestExchange .NOTES Author : Metawise Consulting LLC Module : 365TUNE Version : 2.2.7 #> [CmdletBinding()] param( [switch]$SkipAuth ) $displayNameProd = "365TUNE - Security and Compliance" $displayNameBeta = "365TUNE - Security and Compliance - Beta" $roleName = "View-Only Configuration" Write-Host "`n======================================================" -ForegroundColor Cyan Write-Host " 365TUNE - Test Exchange Online Permissions" -ForegroundColor Cyan Write-Host "======================================================`n" -ForegroundColor Cyan # Step 1 - Modules Write-Host "[1/4] Checking required modules..." -ForegroundColor Cyan foreach ($module in @("Az.Accounts", "ExchangeOnlineManagement")) { if (-not (Get-Module -ListAvailable -Name $module)) { Install-Module -Name $module -Force -Scope CurrentUser } } Import-Module Az.Accounts, ExchangeOnlineManagement Write-Host " [OK] Modules ready." -ForegroundColor Green # Step 2 - Authenticate Write-Host "`n[2/4] Authenticating..." -ForegroundColor Cyan if (-not $SkipAuth) { $inCloudShell = ($env:ACC_CLOUD -eq "PROD") -or ($env:POWERSHELL_DISTRIBUTION_CHANNEL -like "*CloudShell*") -or ($env:AZUREPS_HOST_ENVIRONMENT -like "*cloud-shell*") if ($inCloudShell) { Connect-AzAccount -Identity -WarningAction SilentlyContinue | Out-Null } else { Disconnect-AzAccount -ErrorAction SilentlyContinue | Out-Null Connect-AzAccount -WarningAction SilentlyContinue | Out-Null } } $context = Get-AzContext if (-not $context) { throw "Not authenticated." } Write-Host " Tenant : $($context.Tenant.Id)" -ForegroundColor Gray Write-Host " Account : $($context.Account.Id)" -ForegroundColor Gray Write-Host " [OK] Authenticated." -ForegroundColor Green # Step 3 - Connect Exchange Write-Host "`n[3/4] Connecting to Exchange Online..." -ForegroundColor Cyan Connect-ExchangeOnline -ShowBanner:$false Start-Sleep -Milliseconds 500 Write-Host " [OK] Connected." -ForegroundColor Green # Step 4 - Check Write-Host "`n[4/4] Checking Exchange permissions..." -ForegroundColor Cyan $spRegistered = $null try { $spRegistered = Get-ServicePrincipal -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -eq $displayNameProd -or $_.DisplayName -eq $displayNameBeta } | Select-Object -First 1 } catch {} $roleAssigned = $null if ($spRegistered) { try { $roleAssigned = Get-ManagementRoleAssignment -ErrorAction SilentlyContinue | Where-Object { $_.RoleAssigneeName -eq $spRegistered.DisplayName -and $_.Role -eq $roleName } | Select-Object -First 1 } catch {} } Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue Start-Sleep -Milliseconds 500 Write-Host "" if ($spRegistered) { Write-Host " [OK] Service Principal registered in Exchange ASSIGNED" -ForegroundColor Green Write-Host " Display Name : $($spRegistered.DisplayName)" } else { Write-Host " [FAIL] Service Principal registered in Exchange MISSING" -ForegroundColor Red } if ($roleAssigned) { Write-Host " [OK] $roleName role ASSIGNED" -ForegroundColor Green } else { Write-Host " [FAIL] $roleName role MISSING" -ForegroundColor Red } $allOk = $spRegistered -and $roleAssigned Write-Host "" Write-Host "======================================================" -ForegroundColor Cyan if ($allOk) { Write-Host " Exchange permissions OK. [OK]" -ForegroundColor Green } else { Write-Host " Exchange permissions INCOMPLETE. Run Invoke-365TuneConnectExchange." -ForegroundColor Red } Write-Host "======================================================`n" -ForegroundColor Cyan return $allOk } |