Public/Permissions/Invoke-365TuneTestAzure.ps1
|
function Invoke-365TuneTestAzure { <# .SYNOPSIS Tests whether Azure Reader permissions are correctly assigned to the 365TUNE Enterprise App. .DESCRIPTION Checks for Reader role assignments at root scope "/" and AAD IAM scope "/providers/Microsoft.aadiam" for the 365TUNE Service Principal. Read-only - makes no changes. .EXAMPLE Invoke-365TuneTestAzure .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" Write-Host "`n======================================================" -ForegroundColor Cyan Write-Host " 365TUNE - Test Azure 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", "Az.Resources")) { if (-not (Get-Module -ListAvailable -Name $module)) { Install-Module -Name $module -Force -Scope CurrentUser } } Import-Module Az.Accounts, Az.Resources 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 - Resolve SP Write-Host "`n[3/4] Looking up 365TUNE Service Principal..." -ForegroundColor Cyan $graphToken = Get-AzAccessToken -ResourceUrl "https://graph.microsoft.com" -ErrorAction Stop $graphTokenStr = if ($graphToken.Token -is [System.Security.SecureString]) { [System.Net.NetworkCredential]::new("", $graphToken.Token).Password } else { $graphToken.Token } $graphHeaders = @{ Authorization = "Bearer $graphTokenStr"; "Content-Type" = "application/json" } $spFilter = [Uri]::EscapeDataString("displayName eq '$displayNameProd'") $spResponse = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/servicePrincipals?`$filter=$spFilter" -Headers $graphHeaders -Method GET $sp = $spResponse.value | Select-Object -First 1 if (-not $sp) { Write-Host " '$displayNameProd' not found - trying Beta..." -ForegroundColor Yellow $spFilter = [Uri]::EscapeDataString("displayName eq '$displayNameBeta'") $spResponse = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/servicePrincipals?`$filter=$spFilter" -Headers $graphHeaders -Method GET $sp = $spResponse.value | Select-Object -First 1 } if (-not $sp) { throw "Service Principal not found. Ensure the 365TUNE app has been consented to in this tenant." } $servicePrincipalId = $sp.id Write-Host " Display Name : $($sp.displayName)" Write-Host " Object ID : $servicePrincipalId" Write-Host " [OK] Service Principal found." -ForegroundColor Green # Step 4 - Check assignments Write-Host "`n[4/4] Checking Azure role assignments..." -ForegroundColor Cyan $rootAssignment = Get-AzRoleAssignment ` -ObjectId $servicePrincipalId ` -RoleDefinitionName "Reader" ` -Scope "/" ` -SkipClientSideScopeValidation ` -ErrorAction SilentlyContinue | Where-Object { $_.Scope -eq "/" } $aadIamAssignment = Get-AzRoleAssignment ` -ObjectId $servicePrincipalId ` -RoleDefinitionName "Reader" ` -Scope "/providers/Microsoft.aadiam" ` -SkipClientSideScopeValidation ` -ErrorAction SilentlyContinue | Where-Object { $_.Scope -eq "/providers/Microsoft.aadiam" } Write-Host "" if ($rootAssignment) { Write-Host " [OK] Reader at / ASSIGNED" -ForegroundColor Green } else { Write-Host " [FAIL] Reader at / MISSING" -ForegroundColor Red } if ($aadIamAssignment) { Write-Host " [OK] Reader at /providers/Microsoft.aadiam ASSIGNED" -ForegroundColor Green } else { Write-Host " [FAIL] Reader at /providers/Microsoft.aadiam MISSING" -ForegroundColor Red } $allOk = $rootAssignment -and $aadIamAssignment Write-Host "" Write-Host "======================================================" -ForegroundColor Cyan if ($allOk) { Write-Host " Azure permissions OK. [OK]" -ForegroundColor Green } else { Write-Host " Azure permissions INCOMPLETE. Run Invoke-365TuneConnectAzure." -ForegroundColor Red } Write-Host "======================================================`n" -ForegroundColor Cyan return $allOk } |