Omnicit.PIM
0.4.0-preview0003
Entra ID Privileged Identity Management (PIM) Self Activation Commands for Directory Roles, Azure Resources, and Entra ID Groups
Minimum PowerShell version
7.2
Installation Options
Owners
Copyright
(c) Omnicit. All rights reserved.
Package Details
Author(s)
- Omnicit (originally by Justin Grote @justinwgrote)
Tags
PIM Azure EntraID Identity Privileged Windows MacOS Linux
Functions
Connect-OPIM Disable-OPIMAzureRole Disable-OPIMDirectoryRole Disable-OPIMEntraIDGroup Disable-OPIMMyRole Disconnect-OPIM Enable-OPIMAzureRole Enable-OPIMDirectoryRole Enable-OPIMEntraIDGroup Enable-OPIMMyRole Get-OPIMAzureRole Get-OPIMConfiguration Get-OPIMDirectoryRole Get-OPIMEntraIDGroup Install-OPIMConfiguration Remove-OPIMConfiguration Set-OPIMConfiguration Wait-OPIMDirectoryRole
PSEditions
Dependencies
-
- Az.Resources (>= 9.0.3)
- Microsoft.Graph.Authentication (>= 2.36.0)
Release Notes
## [0.4.0-preview0003] - 2026-04-21
### Added
- `Get-OPIMCurrentTenantInfo` private helper — resolves the current tenant GUID and display name from the active Graph session. Used by `Install-`, `Set-`, and `Remove-OPIMConfiguration` to enrich the confirmation prompt.
- `Install-OPIMConfiguration` now auto-resolves `-TenantId` from the active Graph context when the parameter is omitted. A non-terminating error is emitted when no `-TenantId` is supplied and no active Graph session is available.
### Changed
- `Install-OPIMConfiguration`, `Set-OPIMConfiguration`, and `Remove-OPIMConfiguration` now have `ConfirmImpact = 'High'`. The `ShouldProcess` confirmation prompt includes the tenant alias, display name, and resolved GUID, making it clear which tenant is being modified before any write occurs.
- `-TenantId` in `Install-OPIMConfiguration` is no longer `[Mandatory]`; it is auto-resolved from `Get-MgContext` when omitted.
- PSScriptAnalyzer suppressions added to all six argument-completer classes (`AzureEligibleRoleCompleter`, `AzureActivatedRoleCompleter`, `DirectoryEligibleRoleCompleter`, `DirectoryActivatedRoleCompleter`, `GroupEligibleCompleter`, `GroupActivatedCompleter`).
### Changed
- `Write-CmdletError` revamped: new `ErrorRecord` parameter set (pass-through), `InnerException` parameter for exception chaining, `[CmdletBinding()]` added. All public and private functions now use `Write-CmdletError` as the single error-emission entry point.
- All variable names across `Convert-GraphHttpException`, `Get-MyId`, `Invoke-OPIMGraphRequest`, `Export-OPIMTenantMap`, and completer classes updated to PascalCase per module code-style rules.
(alias `Connect-PIM`) — new public cmdlet to pre-authenticate against Microsoft Graph and optionally Azure. A single browser prompt covers all PIM surfaces (directory roles, Entra ID groups, Azure RBAC). All `Get-/Enable-/Disable-OPIM*` cmdlets call this automatically on first use.
- `Disconnect-OPIM` (alias `Disconnect-PIM`) — new public cmdlet to clear all cached session tokens and disconnect from Graph and Azure.
- Centralized MSAL-based authentication layer (`Initialize-OPIMAuth`, `Get-OPIMMsalApplication` private helpers). All PIM cmdlets now share a single token-acquisition flow that caches the result and is idempotent when called multiple times in the same session.
- ACRS Conditional Access claims-challenge handling moved into `Invoke-OPIMGraphRequest`. A single reactive browser re-prompt is issued when Graph returns a step-up challenge, eliminating repeated browser windows when activating multiple roles in one `Enable-OPIMMyRole` call.
- `Invoke-OPIMGraphRequest` private wrapper replaces direct `Invoke-MgGraphRequest` calls throughout the module. Provides bearer-token security (removes raw error records before any processing), ACRS retry, and consistent `Convert-GraphHttpException` error conversion.
(ParameterSetName `ByIdentity`) added to all six `Enable-OPIM*` and `Disable-OPIM*` cmdlets. Activates or deactivates a role/group by schedule ID (or schedule `Name` for Azure) without tab completion. For `Disable-*` cmdlets, the ID must correspond to an active schedule instance (from `Get-OPIM* -Activated`). For Azure RBAC the identity is the `Name` property.
- `Get-OPIMDirectoryRole`, `Get-OPIMEntraIDGroup`, and `Get-OPIMAzureRole` gain a new `-All` ParameterSet that returns **both** eligible and active schedules for the current user in a single call. `-All` and `-Activated` are mutually exclusive.
- `Get-OPIMDirectoryRole` — new `-RoleName` positional parameter (`[Position = 0]`) with tab completion via `DirectoryEligibleRoleCompleter`. Extracts the schedule ID from the trailing `(id)` and performs a dual-search across eligible and active endpoints.
- `Get-OPIMEntraIDGroup` — new `-GroupName` positional parameter (`[Position = 0]`) with tab completion via `GroupEligibleCompleter`. Extracts the schedule ID from the trailing `(id)` and performs a dual-search across eligible and active endpoints.
- `Get-OPIMAzureRole` — new `-RoleName` positional parameter (`[Position = 0]`) with tab completion via `AzureEligibleRoleCompleter`, and new `-Identity` parameter for direct look-up by schedule `Name`. Both perform dual-search across eligible and active endpoints.
- Combined schedule view: When `-All`, `-RoleName`/`-GroupName`/`-Identity` trigger dual-search, all three `Get-OPIM*` cmdlets now return `Omnicit.PIM.*CombinedSchedule` typed objects with a `Status` column (`Eligible` or `Active`) for consistent table output across both result types.
- New format/type files for combined schedule views: `Omnicit.PIM.DirectoryCombinedSchedule`, `Omnicit.PIM.GroupCombinedSchedule`, `Omnicit.PIM.AzureCombinedSchedule` — each with a `Status` column in the default table view.
### Performance
- **Module load time reduced by ~8 seconds** (~55% of total import time). Consolidated 13 individual `*.Format.ps1xml` files into a single `Omnicit.PIM.Format.ps1xml` and 13 `*.Types.ps1xml` files into a single `Omnicit.PIM.Types.ps1xml`. Previously each file triggered a full format/type table rebuild (~0.49s and ~0.11s per call respectively).
- `FormatsToProcess` re-enabled in the module manifest — format data is now loaded natively by PowerShell at zero extra cost. This was previously disabled because `Update-FormatData -PrependPath` was needed to override Az.Resources native types; that override (`RoleAssignmentScheduleRequest`) is no longer needed since all output is wrapped as `Omnicit.PIM.*` custom types.
- `suffix.ps1` now loads a single consolidated `Omnicit.PIM.Types.ps1xml` file (1 call to `Update-TypeData`) instead of enumerating and loading 13 individual files (14 calls). `TypesToProcess` remains disabled in the manifest because `Remove-Module` does not clean type data, causing "member already present" errors on `Import-Module -Force`.
- Removed orphaned `RoleAssignmentScheduleRequest.Format.ps1xml` and `RoleAssignmentScheduleRequest.Types.ps1xml` — these targeted the native Az `Microsoft.Azure.PowerShell.Cmdlets.Resources.Authorization.Models.Api20201001Preview.RoleAssignmentScheduleRequest` type, but all Azure output is now wrapped with `Omnicit.PIM.AzureAssignmentScheduleRequest`.
- Pipeline safety guards: `Enable-OPIMDirectoryRole`, `Enable-OPIMEntraIDGroup`, `Enable-OPIMAzureRole` now skip pipeline objects already tagged as active assignment instances (e.g. objects piped from `Get-OPIM* -All` that have `Status = Active`), emitting a `Write-Verbose` message instead of attempting an activation that would fail.
- Pipeline safety guards: `Disable-OPIMDirectoryRole`, `Disable-OPIMEntraIDGroup`, `Disable-OPIMAzureRole` now skip pipeline objects tagged as eligible-only schedules (e.g. objects piped from `Get-OPIM* -All` that have `Status = Eligible`), emitting a non-terminating error instead of attempting a deactivation that would fail.
### Changed
- **BREAKING** — `Get-OPIMDirectoryRole -All`, `Get-OPIMEntraIDGroup -All`, and `Get-OPIMAzureRole -All` no longer remove `filterByCurrentUser` / `asTarget()` to list all principals. They now return **both** eligible and active schedules for the **current user**. Admins seeking all-principals data should query the Graph API directly with elevated permissions.
- **BREAKING** — `-All` and `-Activated` are now mutually exclusive on all three `Get-OPIM*` cmdlets. Combining them raises a parameter binding error.
- `Enable-OPIMDirectoryRole`, `Enable-OPIMEntraIDGroup`, `Enable-OPIMAzureRole` — `-Justification` is now positional `[Position = 1]` and `-Hours` is positional `[Position = 2]`, enabling: `Enable-OPIMDirectoryRole 'Role (id)' 'Justification' 4`.
### Fixed
- `Get-OPIMDirectoryRole -Activated` no longer applies a post-filter of `assignmentType -eq 'Activated'`. All items returned by `roleAssignmentScheduleInstances` are inherently active assignments; the filter suppressed results when the real Graph API response omitted or differed in that field.
- `Get-OPIMEntraIDGroup -All` no longer throws `MissingParameters: The required parameters GroupId or PrincipalId is missing`. The PIM Groups API requires `filterByCurrentUser(on='principal')` even when listing all types; this is now preserved.
- `Get-OPIMAzureRole -All` no longer throws `InsufficientPermissions`. The `asTarget()` filter is now preserved with `-All`, restricting results to the current user at scope `/`.
- `Get-OPIMAzureRole -Activated -Scope '<specific-scope>'` now returns only instances at that exact scope. Previously, `Get-AzRoleAssignmentScheduleInstance` returned inherited parent-scope instances; these are now filtered out client-side when scope is not `/`.
- `Get-OPIMDirectoryRole`, `Get-OPIMEntraIDGroup` — improved `.PARAMETER Filter` documentation with OData examples. Added `.EXAMPLE` blocks for `-Filter` and `-Identity` usage.
- `Get-OPIMEntraIDGroup` — `-AccessType` filter now applies correctly when `-All` is combined with `-AccessType member` or `-AccessType owner`. Previously the filter was silently ignored in `-All` mode.
- `Get-OPIMAzureRole` — removed `[Alias('Id')]` from the `-Scope` parameter. PowerShell's prefix-matching treated `Id` as an abbreviation of `-Identity`, causing "Parameter set cannot be resolved" errors when `-Identity` was specified alongside the default `$Scope = '/'` binding.
- `Get-OPIMAzureRole` — `Add-Member -NotePropertyName Status` now uses `-Force` to prevent "Cannot add a member with the name 'Status' because a member already exists" errors when the same object is processed more than once (e.g. across multiple pipeline invocations).
- `Get-OPIMAzureRole` dual-search now correctly separates the `-Name` (Get parameter set) and `-Filter` (List parameter set) calls to `Get-AzRoleEligibilitySchedule` and `Get-AzRoleAssignmentScheduleInstance`. These are mutually exclusive parameter sets in Az.Resources; previously passing both parameters caused a parameter binding error.
— wraps `Invoke-MgGraphRequest` for PIM activation POST requests with au
FileList
- Omnicit.PIM.nuspec
- Omnicit.PIM.psd1
- Formats\README.md
- Formats\Omnicit.PIM.Types.ps1xml
- Omnicit.PIM.psm1
- Formats\Omnicit.PIM.Format.ps1xml
- en-US\about_Omnicit.PIM.help.txt
Version History
| Version | Downloads | Last updated |
|---|---|---|
| 0.4.0 | 10 | 4/21/2026 |
| 0.4.0-previe... (current version) | 2 | 4/21/2026 |
| 0.4.0-previe... | 3 | 4/20/2026 |
| 0.4.0-previe... | 4 | 4/19/2026 |
| 0.3.1 | 5 | 4/16/2026 |
| 0.3.1-previe... | 2 | 4/16/2026 |
| 0.3.1-previe... | 2 | 4/16/2026 |
| 0.3.1-previe... | 2 | 4/16/2026 |
| 0.3.0 | 2 | 4/16/2026 |
| 0.3.0-previe... | 4 | 4/15/2026 |
| 0.3.0-previe... | 4 | 4/14/2026 |
| 0.3.0-previe... | 2 | 4/14/2026 |
| 0.3.0-previe... | 2 | 4/13/2026 |
| 0.3.0-previe... | 4 | 4/2/2026 |
| 0.3.0-previe... | 2 | 4/2/2026 |