Modules/Public/PublicFunctions/Test-AZTIPermissions.ps1
|
<#
.SYNOPSIS Pre-flight permission checker for Azure Scout. .DESCRIPTION Validates that the current identity has sufficient ARM and/or Microsoft Graph permissions before the main inventory extraction runs. Returns a structured result object with per-check status, messages, and remediation guidance. This function delegates to Invoke-AZSCPermissionAudit to avoid duplicating permission-check logic. It maps the richer audit result back to the simpler shape that existing callers expect. This function never blocks execution — callers should inspect the result and display warnings for any failed or degraded checks. .PARAMETER TenantID Target Azure AD tenant ID. .PARAMETER SubscriptionID One or more subscription IDs to validate ARM access against. If omitted, the function enumerates subscriptions from the tenant. .PARAMETER Scope Controls which permission categories to check. All (default) — ARM + Graph, ArmOnly — ARM only, EntraOnly — Graph only. .OUTPUTS [PSCustomObject] with properties: ArmAccess [bool] — $true if core ARM checks passed GraphAccess [bool] — $true if core Graph checks passed Details [array] — Per-check objects: Check, Status (Pass/Warn/Fail), Message, Remediation .EXAMPLE $result = Test-AZSCPermissions -TenantID '00000000-0000-0000-0000-000000000000' $result.Details | Format-Table -AutoSize .LINK https://github.com/thisismydemo/azure-scout .COMPONENT This PowerShell Module is part of Azure Scout (AZSC) .NOTES Version: 1.0.0 Authors: Claudio Merola, thisismydemo Refactored (20.4.1): delegates to Invoke-AZSCPermissionAudit to avoid duplicate logic. #> function Test-AZSCPermissions { [CmdletBinding()] param( [string]$TenantID, # SubscriptionID scopes the audit to specific subscriptions instead of checking all. [string[]]$SubscriptionID, [ValidateSet('All', 'ArmOnly', 'EntraOnly')] [string]$Scope = 'All' ) # ── Delegate to Invoke-AZSCPermissionAudit ─────────────────────────────── # Map the -Scope parameter to Invoke-AZSCPermissionAudit's -IncludeEntraPermissions switch. # The full audit function performs a strict superset of the checks this function used to do. $includeEntra = $Scope -in 'All', 'EntraOnly' $auditParams = @{ OutputFormat = 'Console' } if ($TenantID) { $auditParams['TenantID'] = $TenantID } if ($SubscriptionID) { $auditParams['SubscriptionID'] = $SubscriptionID } if ($includeEntra) { $auditParams['IncludeEntraPermissions'] = $true } $auditResult = Invoke-AZSCPermissionAudit @auditParams if (-not $auditResult) { # Invoke-AZSCPermissionAudit returned $null — no auth context available return [PSCustomObject]@{ ArmAccess = $false GraphAccess = $false Details = @([PSCustomObject]@{ Check = 'Azure Authentication' Status = 'Fail' Message = 'No Azure authentication context found. Run Connect-AzAccount first.' Remediation = 'Connect-AzAccount -TenantId <tenantId>' }) } } # ── Map richer result to simplified shape expected by existing callers ──── # Combine ARM + provider + Graph details into the single Details array. $allDetails = [System.Collections.Generic.List[PSCustomObject]]::new() foreach ($d in $auditResult.ArmDetails) { $allDetails.Add($d) } foreach ($p in $auditResult.ProviderResults) { $allDetails.Add([PSCustomObject]@{ Check = "Provider: $($p.Provider)" Status = $p.Status Message = "$($p.Purpose) — $($p.RegistrationState)" Remediation = if ($p.Status -ne 'Pass') { "Register-AzResourceProvider -ProviderNamespace '$($p.Provider)'" } else { $null } }) } foreach ($g in $auditResult.GraphDetails) { $allDetails.Add($g) } # For EntraOnly scope suppress ARM details from the returned Details array. if ($Scope -eq 'EntraOnly') { $allDetails = [System.Collections.Generic.List[PSCustomObject]]($allDetails | Where-Object { $_.Check -like 'Graph:*' }) } return [PSCustomObject]@{ ArmAccess = $auditResult.ArmAccess GraphAccess = if ($Scope -eq 'ArmOnly') { $null } else { $auditResult.GraphAccess } Details = $allDetails.ToArray() } } |