Skip to main content

Reporting & Artifacts

Generate and customize HTML scan reports.

What Is the HTML Report?

The HTML report is a comprehensive, standalone document of a complete scan. Unlike emails/webhooks (which summarize changes), the report shows all detected activity with deep detail.

Contents:

  • Severity breakdown with counts
  • All detected changes organized by workload and severity
  • Before/after diffs for each change
  • Tenant metadata and scan timestamp
  • Git commit SHA (if available)
  • Dark mode compatible
  • Responsive mobile-friendly design

Quick Setup

  1. Set REPORT_ARTIFACT=true in pipeline variables
  2. Run the pipeline
  3. Download scan-report.html from pipeline artifacts
  4. Open in browser

Enabling Reports

Azure DevOps

  1. PipelinesPIM MonitorEditVariables
  2. Click + Variable
  3. Name: REPORT_ARTIFACT
  4. Value: true (case-sensitive)
  5. Save
  6. Next scan will generate report

GitHub Actions

  1. SettingsSecrets and variablesActionsVariables
  2. Click New repository variable
  3. Name: REPORT_ARTIFACT
  4. Value: true
  5. Create variable
  6. Next scan will generate report

Accessing Reports

Azure DevOps

  1. Go to PipelinesPIM Monitor[latest run]
  2. Scroll to Artifacts section
  3. Click Download for scan-report.html
  4. Save and open in browser

GitHub Actions

  1. Go to ActionsPIM Change Scan[latest run]
  2. Scroll to Artifacts section
  3. Click scan-report.html
  4. Download and open in browser

Report Structure

Brand, title, tenant name, scan timestamp:

PIM MONITOR
Scan Report — 2026-04-27 18:42:15 UTC
Tenant: Contoso Inc.

Summary Section

High-level counts of detected changes:

Total changes: 5

High ████████████████░░░░░░░░░░░░░░░░░░ 2 (40%)
Medium ░░░░░░░░░░░░░░░░░░████████░░░░░░░░░░░░░░░ 2 (40%)
Low ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░█░░░░░░░░ 1 (20%)

Changes by Workload

Organized sections for each scanned entity type:

Directory Roles

  • Role name
  • Changes (policy, assignments, definition)
  • Severity badges
  • Diff details

PIM Groups

  • Group name
  • Changes (policy, assignments, definition)
  • Severity badges
  • Diff details

Authentication Contexts

  • Context name
  • Properties changed
  • Severity

Administrative Units

  • Unit name
  • Properties changed
  • Severity

Diff Details

For each change:

OLD → NEW
[red] - oldValue
[green] + newValue

Links to Entra portal (if role/group)

Metadata and generation details:

Scan complete: 2026-04-27T18:42:15Z
Repository: github.com/contoso/PIM-Monitor
Commit: a3cd69c
Generated by: PIM Monitor v1.0

Customizing Reports

Change Report Title

Edit Export-ScanReport in src/notifications.ps1 (line ~691):

$pageTitle = "[PIM Monitor] Scan Report"

Change to:

$pageTitle = "Azure Identity Governance Scan"

Customize Report Colors

Edit the CSS variables in Format-ScanReportHtml (src/notifications.ps1, lines ~350-380):

--color-high: #dc2626; /* Red */
--color-medium: #ea580c; /* Orange */
--color-low: #eab308; /* Yellow */
--color-bg: #fafafa; /* Light background */

Change to your brand colors:

--color-high: #1e40af; /* Blue */
--color-medium: #7c3aed; /* Purple */
--color-low: #059669; /* Green */

Add Custom Branding

Edit the header section to add logo or organizational branding:

<div style="display: flex; align-items: center; margin-bottom: 20px;">
<img src="https://example.com/logo.png" alt="Logo" style="height: 40px; margin-right: 20px;">
<h1>Your Organization PIM Report</h1>
</div>

Include Additional Metadata

Add tenant ID, region, or custom fields to the footer:

# In Export-ScanReport, before closing HTML:
$footer = @"
<div style="margin-top: 30px; padding-top: 20px; border-top: 1px solid #e5e5e5;">
<p><strong>Tenant ID:</strong> $TenantId</p>
<p><strong>Region:</strong> North America</p>
<p><strong>Classification:</strong> Internal Use Only</p>
</div>
"@

Change Severity Label Names

Edit Format-ScanReportHtml to change "High", "Medium", "Low", "Informational" to custom labels:

# Change:
$severityLabel = $severity # "High", "Medium", etc.

# To:
$severityLabel = switch ($severity) {
"High" { "Critical"; break }
"Medium" { "Important" }
"Low" { "Minor" }
"Informational" { "FYI" }
}

Remove Sections

To exclude certain workloads or severity levels, edit the section generation logic.

Example: Skip Informational changes:

if ($change.severity -eq "Informational") {
continue # Skip informational changes in report
}

Report Privacy & Retention

Storage Location

Azure DevOps:

  • Stored in Build Artifacts storage
  • Retention policy: Default is 30 days, configurable per project
  • Accessible to anyone with project access

GitHub Actions:

  • Stored in Actions artifacts storage
  • Retention policy: Default is 90 days, configurable per repository
  • Accessible to anyone with repository access

Security Considerations

The report includes:

  • Display names of roles, groups, administrative units
  • Property values that changed (e.g., MFA settings)
  • Commit links and timestamps

Recommendations:

  • Store reports in private repositories (GitHub) or secure project (Azure DevOps)
  • If sharing reports, redact sensitive display names
  • Set artifact retention to match your compliance policy
  • Review access permissions regularly

Archival & Compliance

To keep historical reports:

Option 1: Configure extended retention

  • Azure DevOps: Project SettingsPipelinesArtifact retention
  • GitHub Actions: SettingsActionsArtifacts and logsRetention policy

Option 2: Manually download and store

  • Download reports to secure storage (OneDrive, SharePoint, etc.)
  • Tag with date and tenant
  • Implement archival workflow

Troubleshooting

Report not generated

Check:

  1. Is REPORT_ARTIFACT=true set in variables?
  2. Were changes detected? Reports only generate on changes
  3. Check pipeline logs: Export-ScanReport should appear
  4. Verify BUILD_ARTIFACTSTAGINGDIRECTORY is available (Azure DevOps)

Report looks corrupted or incomplete

Check:

  1. Is HTML file fully downloaded? Incomplete file → browser error
  2. Try opening in different browser (Chrome, Firefox, Edge)
  3. Check pipeline logs for errors during report generation
  4. Ensure HTML has valid encoding (UTF-8)

Report file too large

Check:

  1. How many changes were detected? Many changes = larger file
  2. Disable report for scans with no changes (already does this)
  3. Implement filtering by severity level (before report generation)

Styling looks wrong in browser

Check:

  1. Browser supports CSS custom properties? (Modern browsers OK)
  2. Dark mode toggle? Some browsers have dark mode that conflicts
  3. Try incognito/private browsing (skips extensions that might affect styling)
  4. Check console for errors (F12 → Console tab)

Comparing Report vs. Email/Webhook

AspectReportEmailWebhook
TriggerAlways (if enabled)Only on changesOnly on changes
Detail levelVery high (all data)Summary (top issues)Summary
FormatHTML (browser)Email (multi-client)JSON/Slack/Teams
Deep linkingYes (Entra portal)YesLimited
AccessibilityRequires downloadImmediate deliveryImmediate delivery
ArchivalArtifact storageEmail archiveWebhook logs
Mobile friendlyYesResponsivePlatform-dependent

Best practice: Use both:

  • Email/webhook for immediate alerts (urgent issues)
  • Report artifact for detailed review and compliance archival