Public/Get-CustomSecurityAttributesReport.ps1
|
<# .SYNOPSIS Generates an interactive HTML report of custom security attributes across users, devices, and enterprise apps. Connect first with Connect-RKGraph; this cmdlet uses the existing connection. .DESCRIPTION Queries Microsoft Graph for custom security attributes assigned to users, devices, and service principals. Auto-discovers attribute sets or accepts a specific set. Generates an interactive report with: - Overview tab with coverage matrix (which entities have which attribute sets) - Dynamic tabs per attribute set with sub-sections for users, devices, and enterprise apps - DataTables with search, export (Excel/CSV/PDF), column visibility, and dark/light theme toggle .PARAMETER AttributeSet Specific attribute set to report on. If not specified, auto-discovers and reports on all attribute sets. .PARAMETER SendEmail Send the report as an email attachment via Microsoft Graph Mail.Send. .PARAMETER Recipient Email addresses to send the report to. Required when -SendEmail is used. .PARAMETER From Sender email address. If omitted, sends as the currently authenticated user. .PARAMETER ExportPath Full path for the HTML report file. Defaults to current directory. .PARAMETER DebugMode Enable verbose debug output. .EXAMPLE Get-CustomSecurityAttributesReport Auto-discovers all attribute sets and generates a full report. .EXAMPLE Get-CustomSecurityAttributesReport -AttributeSet "ComplianceData" Report on a specific attribute set only. .EXAMPLE Get-CustomSecurityAttributesReport -SendEmail -Recipient "admin@contoso.com" Generate report and email it. #> function Get-CustomSecurityAttributesReport { [CmdletBinding()] param( [Parameter(Mandatory = $false)] [string]$AttributeSet, [Parameter(Mandatory = $false)] [switch]$SendEmail, [Parameter(Mandatory = $false)] [string[]]$Recipient, [Parameter(Mandatory = $false)] [string]$From, [Parameter(Mandatory = $false)] [string]$ExportPath, [Parameter(Mandatory = $false)] [switch]$DebugMode ) $ErrorActionPreference = 'Stop' try { $ctx = Get-MgContext -ErrorAction SilentlyContinue if (-not $ctx) { throw 'Not connected to Microsoft Graph. Run Connect-RKGraph first.' } # Get tenant information $tenantInfo = Invoke-MgGraphRequest -Uri 'v1.0/organization' -Method Get -OutputType PSObject $tenantName = $tenantInfo.value[0].displayName # Fetch attribute data across all entity types $dataParams = @{ DebugMode = $DebugMode } if ($AttributeSet) { $dataParams['AttributeSet'] = $AttributeSet } $reportData = Get-CustomSecurityAttributeData @dataParams $totalEntities = $reportData.Counts.Users + $reportData.Counts.Devices + $reportData.Counts.Apps if ($totalEntities -eq 0) { Write-Host 'No entities found with custom security attributes.' -ForegroundColor Yellow return } Write-Host "Found $($reportData.Counts.Users) user(s), $($reportData.Counts.Devices) device(s), $($reportData.Counts.Apps) app(s) with attributes." -ForegroundColor Green # Generate HTML report $htmlPath = New-CustomSecurityAttributesHTMLReport -TenantName $tenantName -ReportData $reportData -ExportPath $ExportPath # Send email if requested if ($SendEmail -and $Recipient) { $subject = "$tenantName - Custom Security Attributes Report" $bodyHtml = @" <html><body style="font-family: 'Source Serif 4', Georgia, serif;"> <h2>Custom Security Attributes Report</h2> <p>Attached is the latest Custom Security Attributes report for <strong>$tenantName</strong>.</p> <p>Open the attached HTML in a browser for the interactive dashboard.</p> <p style='color:#787468;'>Generated by RKSolutions - please do not reply.</p> </body></html> "@ $emailSent = Send-EmailWithAttachment -Recipient $Recipient -AttachmentPath $htmlPath -From $From -Subject $subject -BodyHtml $bodyHtml if ($emailSent) { Write-Host 'INFO: Email sent successfully.' -ForegroundColor Green } else { Write-Host 'ERROR: Failed to send email.' -ForegroundColor Red } } if ($SendEmail -and (Test-Path -Path $htmlPath)) { Remove-Item -Path $htmlPath -Force Write-Host 'INFO: Temporary report file deleted.' -ForegroundColor Green } } catch { Write-Error "Error: $_"; throw $_ } } |