Public/Test-ArgusPrerequisite.ps1
|
function Test-ArgusPrerequisite { <# .SYNOPSIS Reports whether the prerequisites for an ARGUS run are met. .DESCRIPTION Inspects the current environment and connections and reports: - required and optional modules (Microsoft.Graph.Authentication, ExchangeOnlineManagement, PnP.PowerShell, MSCommerce) and their versions; - active connections (Graph, Exchange Online, SharePoint Online) and the account or app used; - granted Graph scopes / app roles compared with the ones required by the selected checks; - detected licences relevant to the checks (Entra ID P1 / P2); - which checks would be Skipped and why. The cmdlet is read-only and does not run any check. .PARAMETER Area Restrict the evaluation to checks of these areas. .PARAMETER Id Restrict the evaluation to these check IDs (for example ARG.ENT.001). .PARAMETER Tag Restrict the evaluation to checks with at least one of these tags. .PARAMETER CustomCheckPath Additional folder(s) containing custom check files to include in the evaluation. .EXAMPLE Test-ArgusPrerequisite Evaluates prerequisites for the whole catalogue. .EXAMPLE Test-ArgusPrerequisite -Area Exchange, SharePoint Shows which Exchange and SharePoint checks would be skipped with the current connections. .OUTPUTS PSCustomObject describing modules, connections, permissions, licences and per-check readiness. .LINK Connect-Argus .LINK Get-ArgusRequiredPermission #> [CmdletBinding()] [OutputType([pscustomobject])] param( [Parameter()] [ValidateSet('EntraID', 'Applications', 'Licensing', 'GroupsTeams', 'SharePoint', 'Exchange', 'Copilot')] [string[]] $Area, [Parameter()] [ValidatePattern('^ARG\.[A-Z]{3}\.\d{3}$')] [string[]] $Id, [Parameter()] [string[]] $Tag, [Parameter()] [string[]] $CustomCheckPath ) $environment = Get-ArgusEnvironment $modules = @(Get-ArgusModuleInfo) foreach ($module in $modules | Where-Object { -not $_.Installed }) { $level = if ($module.Required) { 'required' } else { 'optional' } Write-Warning "Module $($module.Name) ($level) is not installed: $($module.Purpose)." } $connected = 'Graph' -in $environment.ConnectedServices if (-not $connected) { Write-Warning 'Not connected to Microsoft Graph. Run Connect-Argus first.' } # Permissions requested at sign-in vs. granted $required = @((Get-ArgusRequiredPermission -Aggregate).GraphPermissions) [string[]] $missing = @() if ($null -ne $environment.GrantedScopes) { $missing = @($required | Where-Object { $_ -notin $environment.GrantedScopes -and ($_ -replace '\.Read\.', '.ReadWrite.') -notin $environment.GrantedScopes }) } if ($missing.Count -gt 0) { Write-Warning "Permissions not granted: $($missing -join ', ')." } # Directory roles of the signed-in user (delegated only; direct assignments) $roles = $null if ($connected -and $environment.AuthMode -like 'Interactive*') { try { $me = Invoke-ArgusGraphRequest -Uri '/me?$select=id' $assignments = @(Invoke-ArgusGraphRequest -Uri ("/roleManagement/directory/roleAssignments?`$filter=principalId eq '{0}'&`$expand=roleDefinition(`$select=displayName)" -f $me.id) -All) $roles = [string[]]@($assignments | ForEach-Object { $_.roleDefinition.displayName } | Sort-Object -Unique) $lacking = @($script:ArgusRecommendedRoles | Where-Object { $_ -notin $roles }) $isAdmin = 'Global Administrator' -in $roles if ($lacking.Count -gt 0 -and -not $isAdmin) { Write-Warning ("The signed-in account does not hold {0} (direct assignment). With delegated sign-in, ARGUS can only read what your own roles allow; some checks may be Skipped or return errors." -f ($lacking -join ' and ')) } } catch { Write-Verbose "Role assignments of the signed-in user could not be read: $($_.Exception.Message)" } } # Per-check readiness $config = Get-ArgusConfig $catalog = @(Get-ArgusCheckCatalog -CustomCheckPath $CustomCheckPath) $checks = foreach ($check in $catalog) { if ($Area -and $check.Area -notin $Area) { continue } if ($Id -and $check.Id -notin $Id) { continue } if ($Tag -and -not ($check.Tags | Where-Object { $_ -in $Tag })) { continue } $setting = Resolve-ArgusCheckSetting -Check $check -Config $config -WarningAction SilentlyContinue $reasons = @(Test-ArgusRequirement -Check $check -Environment $environment) [pscustomobject]@{ Id = $check.Id Title = $check.Title Ready = $setting.Enabled -and $reasons.Count -eq 0 Reason = if (-not $setting.Enabled) { 'Disabled in configuration.' } elseif ($reasons.Count) { ($reasons -join '; ') + '.' } else { '' } } } $checks = @($checks) [pscustomobject]@{ PSTypeName = 'Argus.Prerequisite' Connected = [string[]]@($environment.ConnectedServices) Account = $environment.Account AuthMode = $environment.AuthMode Tenant = if ($environment.TenantName) { $environment.TenantName } else { $environment.TenantId } Modules = $modules MissingPermissions = [string[]]$missing SignedInUserRoles = $roles RecommendedRoles = [string[]]$script:ArgusRecommendedRoles Licenses = $environment.Licenses ConcealedReportNames = $environment.ConcealedReportNames ChecksReady = @($checks | Where-Object Ready).Count ChecksSkipped = @($checks | Where-Object { -not $_.Ready }).Count Checks = $checks } } |