Skip to content

Commit 203a607

Browse files
feat: release v2.1.0 - MG display names, duplicate suppression, activation-window visibility, PSGallery import notification, deactivation safety (thanks @l-gosling)
What's included - Management group scopes show friendly names (or / for tenant root) - Suppress subscription-level inherited eligible duplicates when MG-level eligible exists - Enrich tenant-root/MG active assignments with activation Start/End (temporary activations visible) - Normalize RoleDefinitionId to GUID for reliable deduplication - Import-time PSGallery version notification (opt-out via $script:SuppressUpdateNotification) - Community fix: Scope-aware activation/deactivation and safer deactivation (thanks @l-gosling)
1 parent 7b309db commit 203a607

5 files changed

Lines changed: 249 additions & 63 deletions

File tree

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
- **Scheduling**: Plan role activations for future times
1313
- **Enhanced Reporting**: Built-in activation history and analytics
1414

15+
---
16+
17+
## [2.1.0] - 2026-01-27
18+
19+
### ✅ Enhancements
20+
- Management group display names: management-group scopes are now presented with friendly display names (or `/` for tenant root) instead of raw management-group IDs.
21+
- Suppress inherited eligible duplicates: subscription-scoped inherited eligible roles are now suppressed when the same role is available at the management-group level to avoid duplicate activation entries.
22+
- Temporary activation visibility: tenant-root and management-group active assignments are enriched with PIM activation Start/End windows so temporary activations show expiry rather than appearing permanently active.
23+
- Role definition normalization: normalize role definition identifiers to GUIDs during de-duplication to prevent duplicates caused by full-path vs GUID variants.
24+
- Import-time PSGallery notification: module import performs a best-effort PSGallery check and emits a Microsoft-style warning when a newer release is available (opt-out via `$script:SuppressUpdateNotification`).
25+
26+
### 🛠️ Fixes
27+
- Activation/Deactivation Scope and Safety: Added explicit `Scope` support for activation/deactivation operations and improved error handling to prevent attempting to deactivate roles that have been activated for less than the required 5-minute grace period. (Thanks to Lukas Gosling (@l-gosling) for this contribution.)
28+
29+
### Notes
30+
- These are additive fixes and enhancements focused on Azure resource role display, de-duplication, and temporary activation handling.
31+
32+
1533
---
1634

1735
## [2.0.0] - 2025-12-29

PIMActivation.psd1

Lines changed: 14 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
RootModule = 'PIMActivation.psm1'
44

55
# Version number of this module.
6-
ModuleVersion = '2.0.0'
6+
ModuleVersion = '2.1.0'
77

88
# Supported PSEditions - Requires PowerShell Core (7+)
99
CompatiblePSEditions = @('Core')
@@ -62,49 +62,22 @@
6262
# A URL to an icon representing this module.
6363
IconUri = 'https://raw.githubusercontent.com/Noble-Effeciency13/PIMActivation/main/Resources/icon.png'
6464

65-
# ReleaseNotes
66-
ReleaseNotes = @'
67-
## PIMActivation v2.0.0 - Azure Resources & Parallel Processing Engine
65+
# ReleaseNotes
66+
ReleaseNotes = @'
67+
## PIMActivation v2.1.0 - Patch & Enhancements
6868
69-
### 🚀 Major New Features
70-
- **Azure Resource Roles Support**: Full integration with Azure Resource PIM for subscription, resource group, and individual resource role management
71-
- **Parallel Processing Engine**: High-performance concurrent execution for all operations with real-time progress tracking
72-
- **Enhanced Role Display**: Azure roles display with [Azure] prefix and portal-aligned resource/scope columns
73-
- **Cross-Subscription Support**: Automatic enumeration and management across all accessible Azure subscriptions
74-
- **Modular Architecture**: Split functions into individual files for better maintainability
69+
### ✅ Enhancements
70+
- Management group display names: management-group scopes are now shown with their friendly display name (or `/` for tenant root) instead of raw MG IDs.
71+
- Inherited eligible role suppression: subscription-scoped inherited eligible roles are suppressed when the same role is available at the management-group level to avoid duplicate activation entries.
72+
- Temporary activation detection: initial tenant-root and management-group active assignments are enriched with PIM activation schedule Start/End windows so temporarily activated roles show expiry rather than appearing permanently active.
73+
- Role definition normalization: role definition identifiers are normalized (GUID) during deduplication to eliminate duplicates caused by full-path vs GUID variants.
74+
- Import-time PSGallery notification: on import the module performs a best-effort check against the PowerShell Gallery and warns when a newer release is available. The notification follows Microsoft module style and provides Update-Module / Install-Module examples. This check can be suppressed via `$script:SuppressUpdateNotification`.
7575
76-
### ⚡ Performance Features
77-
- **Parallel Processing by Default**: Concurrent execution for Azure, Entra, and Group operations
78-
- **Real-Time Progress Tracking**: Enhanced verbose output with emoji indicators (🚀, ✅, ❌) and timing metrics
79-
- **Smart Throttling**: Default ThrottleLimit of 10 concurrent operations, configurable up to 50
80-
- **Thread-Safe Operations**: ConcurrentBag and ConcurrentDictionary for safe parallel result aggregation
76+
### 🛠️ Fixes (Community Contribution)
77+
- Activation/Deactivation Scope and Safety: Added explicit `Scope` support when activating and deactivating Azure PIM roles and improved error handling to prevent attempting to deactivate a role that was activated less than the required 5-minute window. (Thanks to Lukas Gosling (@l-gosling) for this contribution.)
8178
82-
### ✅ Added
83-
- Complete Azure Resource role activation and deactivation support
84-
- Select All button for bulk role selection in GUI
85-
- `Get-AzureResourceRoles` function with parallel subscription processing
86-
- `Initialize-AzureResourceSupport` for Azure module management
87-
- `DisableParallelProcessing` parameter for sequential processing when needed
88-
- Enhanced scope parsing for Azure ARM resource hierarchies
89-
- Support for both PIM-eligible and active Azure Resource role assignments
90-
91-
### 🔧 Enhanced Performance
92-
- All v1.2.x optimizations preserved and extended:
93-
- ArrayList-based collections for optimal memory usage
94-
- Batch API operations reducing Graph calls by 85%
95-
- Memoized scope display name lookups
96-
- Intelligent role deduplication and caching
97-
- NEW: Parallel processing across all role types and policy operations
98-
99-
### 📋 Requirements
100-
- PowerShell 7.0+ (required for parallel processing engine)
101-
- Az.Accounts 5.1.0+ and Az.Resources 6.0.0+ (auto-installed for Azure resources)
102-
- Microsoft Graph PowerShell modules (existing requirements preserved)
103-
104-
### 📚 More
105-
- Changelog: https://github.com/Noble-Effeciency13/PIMActivation/blob/main/CHANGELOG.md
106-
- Blog Post: https://www.chanceofsecurity.com/post/microsoft-entra-pim-bulk-role-activation-tool
107-
- Releases: https://github.com/Noble-Effeciency13/PIMActivation/releases
79+
### ⚡ Notes
80+
- These changes are additive and preserve existing public APIs. They improve display fidelity and de-duplication for Azure resource roles and make temporary activations visible as such in the UI.
10881
10982
PowerShell module for comprehensive PIM role management across Entra ID, Groups, and Azure Resources with parallel processing engine and modern GUI.
11083
'@

PIMActivation.psm1

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ $script:IncludeAzureResources = $false
2727
# Startup parameters (for restarts)
2828
$script:StartupParameters = @{}
2929

30+
# Control runtime update-notification behavior. Can be set by consumers to suppress the PSGallery check.
31+
$script:SuppressUpdateNotification = $false
32+
3033
# Restart flag
3134
$script:RestartRequested = $false
3235

@@ -77,8 +80,6 @@ $script:RequiredModuleVersions = @{
7780
'Microsoft.Graph.Identity.Governance' = '2.29.0'
7881
'Microsoft.Graph.Groups' = '2.29.0'
7982
'Microsoft.Graph.Identity.SignIns' = '2.29.0'
80-
# 'Az.Accounts' = '5.1.0'
81-
# 'Az.Resources' = '6.0.0'
8283
}
8384

8485
#endregion Module Setup
@@ -158,11 +159,54 @@ $script:DependenciesValidated = $false
158159
Write-Verbose "PIMActivation module loaded. Use Start-PIMActivation to begin."
159160
Write-Verbose "Dependencies will be validated and installed automatically when needed."
160161

162+
# Check PowerShell Gallery for newer module version and notify on import (best-effort)
163+
try {
164+
if (-not $script:SuppressUpdateNotification) {
165+
if (Get-Command -Name Find-Module -Module PowerShellGet -ErrorAction SilentlyContinue) {
166+
try {
167+
$remote = Find-Module -Name $script:ModuleName -Repository PSGallery -ErrorAction SilentlyContinue
168+
if ($remote -and $remote.Version) {
169+
$localVersion = $null
170+
try {
171+
$manifest = Join-Path $script:ModuleRoot "$($script:ModuleName).psd1"
172+
if (Test-Path $manifest) {
173+
$md = Import-PowerShellDataFile -Path $manifest
174+
$localVersion = [Version]($md.ModuleVersion)
175+
}
176+
} catch {}
177+
178+
if (-not $localVersion) {
179+
# Fallback to module manifest discovery
180+
$localVersion = [Version]('0.0.0')
181+
}
182+
183+
$remoteVersion = [Version]($remote.Version.ToString())
184+
if ($remoteVersion -gt $localVersion) {
185+
$psgalleryUrl = "https://www.powershellgallery.com/packages/$($script:ModuleName)/$($remoteVersion)"
186+
$msg = @()
187+
$msg += "A newer version of the module '$($script:ModuleName)' is available on the PowerShell Gallery."
188+
$msg += "Installed version: $localVersion"
189+
$msg += "Latest version: $remoteVersion"
190+
$msg += "To update this module, run: Update-Module -Name $($script:ModuleName) -Force"
191+
$msg += "If Update-Module is unavailable, you can install the latest version with: Install-Module -Name $($script:ModuleName) -Force"
192+
$msg += "More information: $psgalleryUrl"
193+
Write-Warning ($msg -join "`n")
194+
}
195+
}
196+
} catch {
197+
Write-Verbose "PSGallery version check failed: $($_.Exception.Message)"
198+
}
199+
}
200+
}
201+
} catch {
202+
Write-Verbose "Update notification check encountered an error: $($_.Exception.Message)"
203+
}
161204
#endregion Module Initialization
162205

163206
#region Cleanup
164207

165208
# Clean up variables
166209
Remove-Variable -Name Private, Public, functionFolders, folder, folderPath, functions, function, privateRoot, import -ErrorAction SilentlyContinue
167210

168-
#endregion Cleanup
211+
212+
#endregion Cleanup

0 commit comments

Comments
 (0)