Skip to content

Commit 4ad6187

Browse files
authored
feat(issue-177): Add Format parameter to Show-PIMReport for Azure Aut… (#178)
* feat(issue-177): Add Format parameter to Show-PIMReport for Azure Automation compatibility - Add Format parameter with HTML/CSV/JSON options (HTML is default) - CSV format skips HTML generation and auto-opening (fixes runbook issues) - JSON format provides structured data for programmatic use - Maintain backward compatibility with existing HTML behavior - Update comprehensive help documentation with examples - Addresses GitHub issue #177 for non-interactive environments * enhance(issue-177): Add Path parameter for custom export location control - Add -Path parameter to Show-PIMReport for CSV/JSON formats - Auto-creates directories if they don't exist - Auto-adds file extensions (.csv/.json) if not provided - Supports absolute paths, relative paths, and network shares - Fallback to temp directory with timestamp when Path not specified - Updated comprehensive help with 5+ examples including network shares - Enhanced flexibility for Azure Automation and enterprise scenarios * resolve pest * chore(version): bump EasyPIM core to v2.0.27 for issue #177 enhancements
1 parent d1cef78 commit 4ad6187

4 files changed

Lines changed: 134 additions & 15 deletions

File tree

EasyPIM.Orchestrator/internal/functions/invoke-graph.ps1

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,27 +36,27 @@ function invoke-graph {
3636

3737
try {
3838
Write-Verbose "Making Graph API call: $Method $uri"
39-
39+
4040
# Only include -Body parameter if we actually have body content
4141
# This prevents PS5.1 from sending empty body with GET requests
4242
if ($body) {
4343
$response = Invoke-MgGraphRequest -Uri $uri -Method $Method -Body $body -ErrorAction Stop
4444
} else {
4545
$response = Invoke-MgGraphRequest -Uri $uri -Method $Method -ErrorAction Stop
4646
}
47-
47+
4848
Write-Verbose "Graph API call successful"
4949
return $response
5050
} catch {
5151
$errorMessage = $_.Exception.Message
5252
Write-Verbose "Graph API call failed: $errorMessage"
53-
53+
5454
# Preserve the original exception for proper error handling upstream
5555
if ($_.Exception.Response) {
5656
Write-Debug "HTTP Status: $($_.Exception.Response.StatusCode)"
5757
Write-Debug "HTTP Status Description: $($_.Exception.Response.StatusDescription)"
5858
}
59-
59+
6060
# Re-throw the original exception to maintain compatibility
6161
throw
6262
}

EasyPIM/EasyPIM.psd1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
RootModule = 'EasyPIM.psm1'
77

88
# Version number of this module.
9-
ModuleVersion = '2.0.26'
9+
ModuleVersion = '2.0.27'
1010

1111
# Supported PSEditions
1212
# CompatiblePSEditions = @()

EasyPIM/functions/Show-PIMReport.ps1

Lines changed: 111 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,51 @@
11
<#
22
.SYNOPSIS
3-
Visualize PIM activities.
3+
Visualize PIM activities in multiple formats (HTML, CSV, JSON).
44
55
.DESCRIPTION
6-
Retrieves PIM-related audit events from Microsoft Graph and returns a summarized object array. Can optionally filter by user UPN. Also computes top categories and actors for HTML visualization.
6+
Retrieves PIM-related audit events from Microsoft Graph and returns a summarized object array. Can optionally filter by user UPN.
7+
Supports multiple output formats:
8+
- HTML: Interactive report with charts (default, opens in browser)
9+
- CSV: Automation-friendly format for Azure runbooks and scripts
10+
- JSON: Structured data for APIs and programmatic use
711
812
.EXAMPLE
913
Show-PIMReport -tenantID $tenantID
10-
Returns recent PIM activity entries for the tenant with useful derived fields.
14+
Generates interactive HTML report with charts and opens in browser (default behavior).
15+
16+
.EXAMPLE
17+
Show-PIMReport -tenantID $tenantID -Format CSV
18+
Exports PIM activity data to CSV file in temp directory for Azure Automation runbooks. Returns object with Data and FilePath properties.
19+
20+
.EXAMPLE
21+
Show-PIMReport -tenantID $tenantID -Format CSV -Path "C:\Reports\PIM-Activity.csv"
22+
Exports PIM activity data to specific CSV file path. Creates directory if it doesn't exist.
23+
24+
.EXAMPLE
25+
Show-PIMReport -tenantID $tenantID -Format JSON -Path "\\server\share\reports\PIM-$(Get-Date -Format 'yyyyMMdd')"
26+
Exports to network share with custom filename (extension automatically added).
27+
28+
.EXAMPLE
29+
Show-PIMReport -tenantID $tenantID -Format JSON
30+
Exports PIM activity data to JSON file in temp directory for API integration. Returns object with Data and FilePath properties.
31+
32+
.EXAMPLE
33+
Show-PIMReport -tenantID $tenantID -upn "user@domain.com" -Format CSV -Path "./user-activity.csv"
34+
Filters PIM activities for specific user and exports to relative path in current directory.
1135
1236
.PARAMETER tenantID
1337
The Entra tenant ID to query.
1438
1539
.PARAMETER upn
1640
Optional UPN filter to return only activities initiated by a specific user.
1741
42+
.PARAMETER Format
43+
Output format: 'HTML' for interactive reports (default), 'CSV' for automation scenarios, 'JSON' for programmatic use.
44+
45+
.PARAMETER Path
46+
Custom file path for CSV/JSON export. If not specified, uses temp directory with timestamp.
47+
Directory will be created if it doesn't exist. File extension (.csv/.json) is added automatically if not provided.
48+
1849
.NOTES
1950
Author: Loïc MICHEL
2051
Homepage: https://github.com/kayasax/EasyPIM
@@ -28,12 +59,19 @@ function Show-PIMReport {
2859
[System.String]
2960
# Tenant ID
3061
$tenantID,
31-
[Parameter(Position = 1, Mandatory = $false)]
32-
[System.String]
33-
# upn of the user
34-
$upn
35-
36-
)
62+
[Parameter(Position = 1, Mandatory = $false)]
63+
[System.String]
64+
# upn of the user
65+
$upn,
66+
[Parameter()]
67+
[ValidateSet('HTML', 'CSV', 'JSON')]
68+
[String]
69+
# Output format: HTML (interactive report), CSV (automation-friendly), JSON (programmatic use)
70+
$Format = 'HTML',
71+
[Parameter()]
72+
[String]
73+
# Custom file path for CSV/JSON export. If not specified, uses temp directory with timestamp
74+
$Path )
3775
try {
3876
$Script:tenantID = $tenantID
3977

@@ -117,7 +155,70 @@ function Show-PIMReport {
117155
}
118156
$Myoutput += New-Object PSObject -Property $props
119157
}
120-
$Myoutput
158+
159+
# Handle different output formats
160+
switch ($Format) {
161+
'CSV' {
162+
# Generate CSV file for Azure Automation and non-interactive scenarios
163+
if ($Path) {
164+
$csvPath = $Path
165+
# Ensure .csv extension if not provided
166+
if (-not $csvPath.EndsWith('.csv', [System.StringComparison]::OrdinalIgnoreCase)) {
167+
$csvPath += '.csv'
168+
}
169+
} else {
170+
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
171+
$csvPath = "$env:temp\PIMReport-$timestamp.csv"
172+
}
173+
174+
# Ensure directory exists
175+
$directory = Split-Path -Path $csvPath -Parent
176+
if ($directory -and -not (Test-Path -Path $directory)) {
177+
New-Item -Path $directory -ItemType Directory -Force | Out-Null
178+
}
179+
180+
$Myoutput | Export-Csv -Path $csvPath -NoTypeInformation -Force
181+
Write-Verbose "CSV report generated: $csvPath"
182+
return @{
183+
Data = $Myoutput
184+
FilePath = $csvPath
185+
Format = 'CSV'
186+
}
187+
}
188+
'JSON' {
189+
# Generate JSON file for programmatic use and APIs
190+
if ($Path) {
191+
$jsonPath = $Path
192+
# Ensure .json extension if not provided
193+
if (-not $jsonPath.EndsWith('.json', [System.StringComparison]::OrdinalIgnoreCase)) {
194+
$jsonPath += '.json'
195+
}
196+
} else {
197+
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
198+
$jsonPath = "$env:temp\PIMReport-$timestamp.json"
199+
}
200+
201+
# Ensure directory exists
202+
$directory = Split-Path -Path $jsonPath -Parent
203+
if ($directory -and -not (Test-Path -Path $directory)) {
204+
New-Item -Path $directory -ItemType Directory -Force | Out-Null
205+
}
206+
207+
$Myoutput | ConvertTo-Json -Depth 10 | Out-File -FilePath $jsonPath -Force
208+
Write-Verbose "JSON report generated: $jsonPath"
209+
return @{
210+
Data = $Myoutput
211+
FilePath = $jsonPath
212+
Format = 'JSON'
213+
}
214+
}
215+
'HTML' {
216+
# Continue with existing HTML generation logic (default behavior)
217+
# Path parameter ignored for HTML format (uses temp directory)
218+
# Return the data array for backward compatibility, HTML generated below
219+
$Myoutput
220+
}
221+
}
121222

122223
#Data for the HTML report
123224

fix_emojis.ps1

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Simple script to fix problematic emojis in README
2+
$content = Get-Content -Path "README.md" -Raw -Encoding UTF8
3+
4+
# Replace the most problematic emoji combinations
5+
$content = $content -replace "🛡️", "🛡"
6+
$content = $content -replace "🏗️", "🏗"
7+
$content = $content -replace "🛠️", "🛠"
8+
$content = $content -replace "🖥️", "🖥"
9+
$content = $content -replace "❤️", ""
10+
11+
# Fix any remaining variation selector issues
12+
$content = $content -replace "�️", "🔧" # Fix the production-tested emoji
13+
$content = $content -replace "", "🏢" # Fix enterprise ready emoji
14+
15+
# Write back with UTF8 encoding
16+
Set-Content -Path "README.md" -Value $content -Encoding UTF8 -NoNewline
17+
18+
Write-Host "✅ Fixed problematic emojis in README.md"

0 commit comments

Comments
 (0)