Public/Start-CheckIDPasswordAgentListener.ps1

<#
.DESCRIPTION
    Starts the CheckIDPasswordAgent listener. The listener continuously checks for password reset requests and processes them.

.SYNOPSIS
    Starts the CheckIDPasswordAgent listener.

.EXAMPLE
    Start-CheckIDPasswordAgentListener -Sleep 5
#>

function Start-CheckIDPasswordAgentListener {
    [CmdletBinding()]
    Param(
        # Sleep interval in seconds between checks for new requests
        [Parameter(Mandatory = $false)]
        [ValidateRange(1, 10)]
        [int] $Sleep = 5
    )

    process {
        if(!(get-command Set-ADAccountPassword* | ? Name -eq Set-ADAccountPassword)) {
            Write-Error -Message "Set-ADAccountPassword cmdlet is not available. Please ensure the Active Directory module is installed and imported."
            Write-EventLog -LogName "Application" -Source "CheckIDPasswordAgent" -EventId 1210 -EntryType Error -Message "Set-ADAccountPassword cmdlet is not available. Please ensure the Active Directory module is installed and imported." -ErrorAction Continue
            return
        }

        Write-Verbose "Starting CheckIDPasswordAgent listener with a sleep interval of $Sleep seconds"
        Write-EventLog -LogName "Application" -Source "CheckIDPasswordAgent" -EventId 1006 -EntryType Information -Message "Starting CheckIDPasswordAgent listener with a sleep interval of $Sleep seconds" -ErrorAction Continue

        while ($true) {
            try {
                $requests = Receive-CheckIDPasswordAgentRequests

                if ($requests) {
                    $requests | ForEach-Object {
                        $request = $_
                        try {
                            if(!$request.onPremisesSecurityIdentifier) {
                                Write-Warning "No onPremisesSecurityIdentifier found for user $($request.userPrincipalName) (Cloud only probably, so we are not doing anything)"
                            } else {
                                Write-Verbose "Setting password for user $($request.userPrincipalName) / $($request.onPremisesSecurityIdentifier)"
                                Write-EventLog -LogName "Application" -Source "CheckIDPasswordAgent" -EventId 1008 -EntryType Information -Message "Setting password for user $($request.userPrincipalName) / $($request.onPremisesSecurityIdentifier) with ID: $($request.id)" -ErrorAction Continue
                                Set-ADAccountPassword -Identity $request.onPremisesSecurityIdentifier -NewPassword (ConvertTo-SecureString -String $request.password -AsPlainText -Force) -Reset
                            }

                            $request | Confirm-CheckIDPasswordAgentRequest -Status "Success"
                        }
                        catch {
                            Write-Error -Message "Failed to set password for user $($request.userPrincipalName): $request"
                            Write-EventLog -LogName "Application" -Source "CheckIDPasswordAgent" -EventId 1201 -EntryType Error -Message "Failed to set password for user $($request.userPrincipalName) with ID $($request.id) - $request" -ErrorAction Continue
                            
                            $request | Confirm-CheckIDPasswordAgentRequest -Status "Error" -Message $_.Exception.Message
                        }
                    }
                }
                else {
                    Write-Verbose "No requests found, sleeping for $Sleep seconds"
                    # Too verbose, no need to inform for every API GET request interval. Fills up Windows event log
                    # Write-EventLog -LogName "Application" -Source "CheckIDPasswordAgent" -EventId 1007 -EntryType Information -Message "No requests found, sleeping for $Sleep seconds" -ErrorAction Continue
                    Start-Sleep -Seconds $Sleep
                }
            } catch {
                Write-Error -Message "An error occurred in the listener loop: $_"
                Write-EventLog -LogName "Application" -Source "CheckIDPasswordAgent" -EventId 1203 -EntryType Error -Message "An error occurred in the listener loop: $_" -ErrorAction Continue
                Start-Sleep -Seconds $Sleep
            }
        }
        
    }
}