Private/Orchestration/Invoke-AccessPackageDocumentorCore.ps1
|
function Invoke-AccessPackageDocumentorCore { <#! .SYNOPSIS Core workflow for Access Package Documentor reporting. .DESCRIPTION Connects to Microsoft Graph (read-only), retrieves access packages with policies/resources/custom extensions, converts to a documentation graph, and emits an interactive HTML report. .PARAMETER OutputPath Directory where the HTML report will be saved. .PARAMETER HtmlReportPath Optional explicit HTML file path. If not provided, one is generated in OutputPath. .PARAMETER Theme Preferred theme: Auto, Light, Dark. .PARAMETER Quiet Suppress console chatter. .PARAMETER NoAutoOpen Do not open the HTML automatically after generation. #> [CmdletBinding()] param( [string]$OutputPath, [string]$HtmlReportPath, [ValidateSet('Auto','Light','Dark')][string]$Theme = 'Auto', [bool]$IncludeBeta = $true, [string]$TenantId, [string]$ClientId, [switch]$Quiet, [switch]$NoAutoOpen, [switch]$ExportCsv ) if ($PSVersionTable.PSVersion -lt [version]'7.0') { throw 'PowerShell 7.0+ is required.' } if (-not $OutputPath) { $OutputPath = 'C:\Reports\M365AccessPackages\' } if (-not (Test-Path $OutputPath)) { New-Item -ItemType Directory -Force -Path $OutputPath | Out-Null } if (-not $HtmlReportPath) { $ts = Get-Date -Format 'yyyyMMdd_HHmmss' $HtmlReportPath = Join-Path $OutputPath "AccessPackages_$ts.html" } $reportPath = $null try { $data = Get-AccessPackageGraphData -QuietMode:$Quiet -IncludeBeta:$IncludeBeta -TenantId:$TenantId -ClientId:$ClientId $graphData = Convert-AccessPackageDocumentorData -AccessPackageData $data $reportPath = New-AccessPackageDocumentorHtml -Data $graphData -OutputPath $HtmlReportPath -Theme $Theme Write-ModuleLog -Message "Access Package Documentor report generated: $reportPath" -Level Success # Export to CSV if requested if ($ExportCsv) { $ts = Get-Date -Format 'yyyyMMdd_HHmmss' $csvBasePath = Join-Path $OutputPath "AccessPackages_$ts" # Export access packages $packagesPath = "${csvBasePath}_Packages.csv" $data.AccessPackages | Select-Object Id, DisplayName, Description, @{N='CatalogName';E={$_.Catalog.DisplayName}}, @{N='CatalogId';E={$_.Catalog.Id}}, CreatedDateTime, ModifiedDateTime | Export-Csv -Path $packagesPath -NoTypeInformation -Encoding UTF8 if (-not $Quiet) { Write-Host " ✓ Exported packages to: $packagesPath" -ForegroundColor DarkGreen } # Export policies $policiesPath = "${csvBasePath}_Policies.csv" $policies = $data.AccessPackages | ForEach-Object { $pkg = $_ $pkg.AssignmentPolicies | ForEach-Object { [PSCustomObject]@{ PolicyId = $_.Id PolicyName = $_.DisplayName Description = $_.Description PackageName = $pkg.DisplayName PackageId = $pkg.Id AllowedTargetScope = $_.AllowedTargetScope DurationInDays = $_.DurationInDays CreatedDateTime = $_.CreatedDateTime ModifiedDateTime = $_.ModifiedDateTime } } } $policies | Export-Csv -Path $policiesPath -NoTypeInformation -Encoding UTF8 if (-not $Quiet) { Write-Host " ✓ Exported policies to: $policiesPath" -ForegroundColor DarkGreen } # Export resources $resourcesPath = "${csvBasePath}_Resources.csv" $resources = $data.AccessPackages | ForEach-Object { $pkg = $_ $_.accessPackageResourceRoleScopes | ForEach-Object { $rrs = $_ [PSCustomObject]@{ ResourceId = $rrs.id ResourceName = $rrs.role.resource.displayName ResourceType = $rrs.role.resource.resourceType OriginSystem = $rrs.role.resource.originSystem OriginId = $rrs.role.resource.originId RoleName = $rrs.role.displayName RoleId = $rrs.role.id ScopeName = $rrs.scope.displayName PackageName = $pkg.DisplayName PackageId = $pkg.Id } } } $resources | Export-Csv -Path $resourcesPath -NoTypeInformation -Encoding UTF8 if (-not $Quiet) { Write-Host " ✓ Exported resources to: $resourcesPath" -ForegroundColor DarkGreen } } if (-not $NoAutoOpen) { try { Start-Process $reportPath | Out-Null } catch { Write-ModuleLog -Message "Failed to auto-open report: $($_.Exception.Message)" -Level Warning } } return $reportPath } finally { try { if ($script:graphConnected -and $script:graphDisconnectOnExit -and (Get-MgContext -ErrorAction SilentlyContinue)) { Disconnect-MgGraph -ErrorAction SilentlyContinue | Out-Null if (-not $Quiet) { Write-Host ' ✓ Disconnected Microsoft Graph session' -ForegroundColor DarkGray } } } catch { Write-ModuleLog -Message "Graph disconnect warning: $($_.Exception.Message)" -Level Warning } } } |