Omnicit.PIM.psd1
|
# # Module manifest for module 'Omnicit.PIM' # # Generated by: Omnicit # # Generated on: 2026-03-25 # @{ # Script module or binary module file associated with this manifest. RootModule = 'Omnicit.PIM.psm1' # Version number of this module. ModuleVersion = '0.5.1' # Supported PSEditions CompatiblePSEditions = @('Core') # ID used to uniquely identify this module GUID = 'ed16ca8d-c9c0-4987-90b9-749edc96ebb8' # Author of this module Author = 'Omnicit (originally by Justin Grote @justinwgrote)' # Company or vendor of this module CompanyName = 'Omnicit' # Copyright statement for this module Copyright = '(c) Omnicit. All rights reserved.' # Description of the functionality provided by this module Description = 'Entra ID Privileged Identity Management (PIM) Self Activation Commands for Directory Roles, Azure Resources, and Entra ID Groups' # Minimum version of the PowerShell engine required by this module PowerShellVersion = '7.2' # Name of the PowerShell host required by this module # PowerShellHostName = '' # Minimum version of the PowerShell host required by this module # PowerShellHostVersion = '' # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. # DotNetFrameworkVersion = '' # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. # ClrVersion = '' # Processor architecture (None, X86, Amd64) required by this module # ProcessorArchitecture = '' # Modules that must be imported into the global environment prior to importing this module RequiredModules = @( @{ ModuleName = 'Az.Resources'; ModuleVersion = '9.0.3' } @{ ModuleName = 'Microsoft.Graph.Authentication'; ModuleVersion = '2.36.0' } ) # Assemblies that must be loaded prior to importing this module # RequiredAssemblies = @() # Script files (.ps1) that are run in the caller's environment prior to importing this module. # ScriptsToProcess = @() # Type files (.ps1xml) to be loaded when importing this module # Disabled: TypesToProcess re-registers type members on every Import-Module -Force but Remove-Module does NOT # clean type data, so the second test file import fails with "member is already present" errors. # Types are loaded via a single Update-TypeData -AppendPath call in the psm1 suffix instead. TypesToProcess = @() # Format files (.ps1xml) to be loaded when importing this module # Re-enabled: all format targets are Omnicit.PIM.* custom types (no Az-native type overrides), so # the AppendPath precedence issue with Az.Resources no longer applies. # The orphaned RoleAssignmentScheduleRequest override was removed because all Azure functions now # wrap output with Omnicit.PIM.AzureAssignmentScheduleRequest before returning. FormatsToProcess = @('Formats/Omnicit.PIM.Format.ps1xml') # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess # NestedModules = @() # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. FunctionsToExport = @('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') # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. CmdletsToExport = @() # Variables to export from this module VariablesToExport = @() # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. AliasesToExport = @('Connect-PIM','Disable-PIMResourceRole','Disable-PIMADRole','Disable-PIMRole','Disable-PIMGroup','unpim','Disable-OPIMMyRoles','Disconnect-PIM','Enable-PIMResourceRole','Enable-PIMADRole','Enable-PIMRole','Enable-PIMGroup','pim','Enable-OPIMMyRoles','Get-PIMResourceRole','Get-PIMConfig','Get-PIMADRole','Get-PIMRole','Get-PIMGroup','Remove-PIMConfig','Set-PIMConfig','Wait-PIMADRole','Wait-PIMRole') # DSC resources to export from this module DscResourcesToExport = @() # List of all modules packaged with this module # ModuleList = @() # List of all files packaged with this module # FileList = @() # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. PrivateData = @{ PSData = @{ # Tags applied to this module. These help with module discovery in online galleries. Tags = @('PIM', 'Azure', 'EntraID', 'Identity', 'Privileged', 'Windows', 'MacOS', 'Linux') # A URL to the license for this module. LicenseUri = 'https://github.com/Omnicit/Omnicit.PIM/LICENSE' # A URL to the main website for this project. ProjectUri = 'https://github.com/Omnicit/Omnicit.PIM' # A URL to an icon representing this module. IconUri = 'https://raw.githubusercontent.com/Omnicit/Omnicit.PIM/main/assets/icon.png' # ReleaseNotes of this module ReleaseNotes = '## [0.5.1-preview0001] - 2026-05-29 ### Fixed - `Enable-OPIMMyRole`/`Get-OPIMAzureRole` no longer skip the Azure sign-in when a stale autosaved Az context exists in a fresh session. `Initialize-OPIMAuth` now validates the cached Az context with a silent `Get-AzAccessToken` before trusting it; if no token can be acquired it reconnects via `Connect-AzAccount` (restoring the expected second browser prompt for Azure RBAC). - `Invoke-OPIMGraphRequest` now recovers from the PIM `RoleAssignmentRequestAcrsValidationFailed` activation error automatically. The claims challenge in this 400 response body is URL-encoded (`&claims=%7B...%7D`), a different encoding from the base64url `WWW-Authenticate: claims="..."` 401 form the parser previously handled. `Get-ClaimsFromException` now decodes both encodings (and raw JSON) and feeds the result to the existing MSAL `AcquireTokenInteractive().WithClaims()` step-up, so activations requiring a Conditional Access authentication context succeed with a single browser prompt and **no** manual `Disconnect-OPIM`. - `Invoke-OPIMGraphRequest` ACRS retry no longer gates on the session-sticky `$script:_OPIMAuthState.ClaimsSatisfied` flag. Each call performs at most one step-up retry on its own, so a second activation in the same session that requires a claims challenge is no longer silently skipped. - `Invoke-OPIMGraphRequest` now transparently re-authenticates and retries once when Graph rejects a bearer token as invalid/expired (HTTP 401 or `InvalidAuthenticationToken`/`CompactToken`/`token is expired`/`Lifetime validation failed`), via the new `Initialize-OPIMAuth -ForceRefresh` path (MSAL `AcquireTokenSilent().WithForceRefresh($true)`) — recovering without a destructive full disconnect. - CI build (`Build & Package Module`) no longer fails with "The required module ''Configuration'' is not loaded" when importing `ModuleBuilder`. `Configuration` and `Metadata` (ModuleBuilder''s transitive runtime dependencies) are now listed explicitly in `RequiredModules.psd1` because PSResourceGet 1.0.1 does not install transitive `RequiredModules` during the bootstrap on a clean agent. ### Changed - `Initialize-OPIMAuth` now disables the Web Account Manager (WAM) broker at **process scope** (`Update-AzConfig -EnableLoginByWam $false -Scope Process`) immediately before `Connect-AzAccount`, so Azure RBAC sign-in uses the system browser consistently with the Graph side instead of the WAM account picker that hangs in some terminals. The user''s persisted Az config is never modified. (Unlike the previously removed Graph-side `Set-MgGraphOption -DisableLoginByWAM`, the Az-side `Update-AzConfig -EnableLoginByWam` toggle is honoured by `Connect-AzAccount`.) - `Initialize-OPIMAuth` gains a `-ForceRefresh` switch that bypasses the cached-token idempotency check and forces MSAL to mint a fresh access token from the refresh token. ### 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 **curre' # Prerelease string of this module Prerelease = 'preview0001' # Flag to indicate whether the module requires explicit user acceptance for install/update/save # RequireLicenseAcceptance = $false # External dependent modules of this module # ExternalModuleDependencies = @() } # End of PSData hashtable } # End of PrivateData hashtable # HelpInfo URI of this module # HelpInfoURI = '' # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. # DefaultCommandPrefix = '' } |