Public/PasswordSynchronisation/Resume-JIMPendingPasswordChange.ps1
|
# Copyright (c) Tetron Limited. All rights reserved. # Licensed under the Tetron Commercial License. See LICENSE file in the project root. function Resume-JIMPendingPasswordChange { <# .SYNOPSIS Puts queued password changes back on the Password Synchronisation queue and asks JIM to deliver them now. .DESCRIPTION Makes every matching change due immediately. The Password Delivery Service is woken by the change and attempts them within about a second, whatever the synchronisation engine is doing. This is what you run once the reason a Connected System refused the passwords has been dealt with: the changes are parked behind that system, and nothing will attempt them again until somebody says so. Applies to changes JIM could still deliver, which is Pending, Parked and Cancelled. An Expired change is left alone: the password it carried is gone, so there is nothing to send. Retrying a change clears the failure recorded against it and resets its attempt count. Whatever it covers, this is one request and one Activity. Piping a hundred parked changes in does not produce a hundred audit entries; a retry over a directory that has come back is one decision, and the record should say so. The command is named Resume- rather than Retry- because Retry is not a PowerShell approved verb; a module exporting one warns on import. Resume is the approved verb for starting something that was suspended, which is what a parked or cancelled change is. .PARAMETER Id The unique identifiers of the queued changes to retry. Accepts queued changes from the pipeline. Combines with the other criteria rather than replacing them, so "-Status Parked" alongside piped changes means "these, if they are still parked": a change delivered since you listed it is not retried. .PARAMETER ConnectedSystemId Retry the changes queued for one Connected System. Accepts a Connected System from the pipeline. .PARAMETER Status Retry only changes in this state: Pending, Parked or Cancelled. Expired changes are never retried. .PARAMETER FailureReason Retry only changes whose last attempt failed this way. .PARAMETER MetaverseObjectId Retry only one identity's queued changes. .PARAMETER Search Retry only changes matching this free-text search over the identity and Connected System names. .PARAMETER EntireQueue Retry every queued password change in the deployment. Required when nothing else narrows the request, so a command that names no criteria cannot act on everything by accident. .PARAMETER Force Skips the confirmation prompt. .OUTPUTS PSCustomObject with an AffectedCount property: how many changes were made due again. .EXAMPLE Resume-JIMPendingPasswordChange -ConnectedSystemId 3 Retries every queued password change for Connected System 3. The usual command after a directory that was refusing passwords has been fixed. .EXAMPLE Get-JIMPendingPasswordChange -Status Parked | Resume-JIMPendingPasswordChange -Force Retries every parked change, in a single request. Run the Get on its own first to see what that covers. .EXAMPLE Resume-JIMPendingPasswordChange -Status Parked -FailureReason Transient -WhatIf Shows what would be retried without retrying it: the changes that failed for a reason that may well have gone away on its own. .EXAMPLE $result = Resume-JIMPendingPasswordChange -ConnectedSystemId 3 -Force "$($result.AffectedCount) password change(s) will be attempted again." Reports how much the retry covered. Zero is a valid answer, not an error: it means nothing was owed. .LINK Get-JIMPendingPasswordChange Stop-JIMPendingPasswordChange Set-JIMMetaverseObjectPassword #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')] [OutputType([PSCustomObject])] param( [Parameter(ValueFromPipelineByPropertyName)] [guid[]]$Id, [Parameter(ValueFromPipelineByPropertyName)] [int]$ConnectedSystemId, [Parameter()] [ValidateSet('Pending', 'Parked', 'Expired', 'Cancelled')] [string]$Status, [Parameter()] [ValidateSet('None', 'Transient', 'ConfigurationFault', 'PolicyRejection', 'TargetObjectNotFound', 'UnsupportedOperation')] [string]$FailureReason, [Parameter()] [guid]$MetaverseObjectId, [Parameter()] [string]$Search, [Parameter()] [switch]$EntireQueue, [Parameter()] [switch]$Force ) begin { # Collected here and acted on in end, deliberately. A per-row request would be one Activity per row, and # the server records an Activity per administrator action precisely so a bulk retry reads as the one # decision it was. $collectedIds = [System.Collections.Generic.List[guid]]::new() } process { if ($Id) { foreach ($changeId in $Id) { $collectedIds.Add($changeId) } } } end { if (-not $script:JIMConnection) { Write-Error "You are not connected to JIM. Run Connect-JIM -Url <your JIM URL> to authenticate, then try again." return } # An empty pipeline is a successful no-op, not a failure: "retry everything parked" on a day when # nothing is parked is exactly the outcome the caller wanted. if ($collectedIds.Count -eq 0 -and $PSCmdlet.MyInvocation.ExpectingInput -and -not $PSBoundParameters.ContainsKey('ConnectedSystemId')) { Write-Verbose "Nothing reached Resume-JIMPendingPasswordChange from the pipeline; there is nothing to retry." return } $target = if ($collectedIds.Count -gt 0) { if ($collectedIds.Count -eq 1) { "1 queued password change" } else { "$($collectedIds.Count) queued password changes" } } elseif ($EntireQueue) { "every queued password change" } else { "the matching queued password changes" } if (-not $Force -and -not $PSCmdlet.ShouldProcess($target, "Attempt delivery again")) { return } Invoke-JIMPasswordQueueAction -Action 'retry' -Id $collectedIds.ToArray() ` -BoundParameters $PSBoundParameters -EntireQueue:$EntireQueue } } |