Public/Update-PSDVTableWebHookAuthSecret.ps1
|
function Update-PSDVTableWebHookAuthSecret { <# .SYNOPSIS Updates the authentication secret for an existing Dataverse table webhook. .DESCRIPTION Update-PSDVTableWebHookAuthSecret modifies the authentication secret for an existing webhook registration. The function can find the webhook by table and name, or by the specific webhook step ID for more precise identification. It then updates the service endpoint's auth configuration with the new secret value. The secret will be passed in the x-dv-webhook-secret header when the webhook is triggered. If no secret is provided, the auth configuration is cleared. .PARAMETER Table The logical name of the Dataverse table that the webhook is registered for. .PARAMETER WebHookName The name of the webhook registration to update. Use when webhook names are unique for the table. .PARAMETER WebHookStepId The unique identifier (GUID) of the webhook step to update. Use when webhook names might not be unique or for precise identification. .PARAMETER AuthSecret The new authentication secret value. If not provided or empty, the auth configuration will be cleared. .EXAMPLE Update-PSDVTableWebHookAuthSecret -Table "account" -WebHookName "Account Changes Monitor" -AuthSecret "NewSecretValue123" Updates the authentication secret for the "Account Changes Monitor" webhook using name-based lookup. .EXAMPLE Update-PSDVTableWebHookAuthSecret -Table "contact" -WebHookStepId "12345678-1234-1234-1234-123456789012" -AuthSecret "NewSecretValue123" Updates the authentication secret for a specific webhook using its step ID. .EXAMPLE Update-PSDVTableWebHookAuthSecret -Table "contact" -WebHookName "Contact Sync Webhook" -AuthSecret "" Clears the authentication secret for the specified webhook. .EXAMPLE Get-PSDVTableWebHook -Table "account" | Where-Object Name -eq "My Webhook" | ForEach-Object { Update-PSDVTableWebHookAuthSecret -Table "account" -WebHookStepId $_.WebHookStepId -AuthSecret "UpdatedSecret" } Updates the auth secret for a webhook found via Get-PSDVTableWebHook using step ID for precise identification. #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory, ParameterSetName = 'ByName')] [Parameter(Mandatory, ParameterSetName = 'ByStepId')] [String] $Table, [Parameter(Mandatory, ParameterSetName = 'ByName')] [String] $WebHookName, [Parameter(Mandatory, ParameterSetName = 'ByStepId')] [Guid] $WebHookStepId, [Parameter(ParameterSetName = 'ByName')] [Parameter(ParameterSetName = 'ByStepId')] [String] $AuthSecret ) if ($null -eq $Global:DATAVERSEACCESSTOKEN) { throw 'No existing connection to Dataverse Environment, run Connect-PSDVOrg before executing other PSDV cmdlets' } if ($PSBoundParameters.ContainsKey('WebHookStepId') -and $WebHookStepId -eq [Guid]::Empty) { throw 'WebHookStepId cannot be an empty GUID' } try { $serviceEndpointId = $null $webhookInfo = $null if ($PSCmdlet.ParameterSetName -eq 'ByName') { Write-Verbose "Finding webhook '$WebHookName' for table '$Table' using name-based lookup" # Find the webhook by table and name $existingWebhook = Get-PSDVTableWebHook -Table $Table -Name $WebHookName if (-not $existingWebhook) { throw "Webhook '$WebHookName' not found for table '$Table'" } # Handle case where multiple webhooks match the name filter if ($existingWebhook.Count -gt 1) { # Try exact name match $exactMatch = $existingWebhook | Where-Object { $_.Name -eq $WebHookName } if ($exactMatch.Count -eq 1) { $existingWebhook = $exactMatch } elseif ($exactMatch.Count -gt 1) { throw "Multiple webhooks found with exact name '$WebHookName' for table '$Table'. Please use -WebHookStepId parameter for precise identification. Found step IDs: $($exactMatch.WebHookStepId -join ', ')" } else { throw "Multiple webhooks found containing name '$WebHookName' for table '$Table'. Found: $($existingWebhook.Name -join ', '). Please use -WebHookStepId parameter for precise identification." } } $serviceEndpointId = $existingWebhook.ServiceEndpointId $webhookInfo = $existingWebhook Write-Verbose "Found webhook '$WebHookName' with service endpoint ID: $serviceEndpointId" } elseif ($PSCmdlet.ParameterSetName -eq 'ByStepId') { Write-Verbose "Finding webhook with step ID '$WebHookStepId' for table '$Table' using step ID lookup" # Get webhook step details directly by ID and validate table $webhookStep = Invoke-PSDVWebRequest -WebUri "api/data/v9.2/sdkmessageprocessingsteps($WebHookStepId)" -Select "sdkmessageprocessingstepid,name,description" -Expand "eventhandler_serviceendpoint(`$select=serviceendpointid,name,url),sdkmessagefilterid(`$select=sdkmessagefilterid,primaryobjecttypecode)" if (-not $webhookStep) { throw "Webhook step '$WebHookStepId' not found" } # Validate that the webhook is for the specified table if ($webhookStep.sdkmessagefilterid.primaryobjecttypecode -ne $Table) { throw "Webhook step '$WebHookStepId' is not configured for table '$Table'. It is configured for table '$($webhookStep.sdkmessagefilterid.primaryobjecttypecode)'" } # Validate that it has a service endpoint (is actually a webhook) if (-not $webhookStep.eventhandler_serviceendpoint -or -not $webhookStep.eventhandler_serviceendpoint.serviceendpointid) { throw "Step '$WebHookStepId' is not a webhook step (no service endpoint found)" } $serviceEndpointId = $webhookStep.eventhandler_serviceendpoint.serviceendpointid $webhookInfo = [PSCustomObject]@{ WebHookStepId = $webhookStep.sdkmessageprocessingstepid Name = $webhookStep.name ServiceEndpointId = $webhookStep.eventhandler_serviceendpoint.serviceendpointid Url = $webhookStep.eventhandler_serviceendpoint.url ServiceEndpointName = $webhookStep.eventhandler_serviceendpoint.name } Write-Verbose "Found webhook step '$($webhookStep.name)' with service endpoint ID: $serviceEndpointId" } # Prepare the auth value based on whether a secret is provided if ($PSBoundParameters.ContainsKey('AuthSecret') -and -not [string]::IsNullOrEmpty($AuthSecret)) { $escapedAuthSecret = ConvertTo-PSDVXmlAttributeValue -Value $AuthSecret $authValue = "<settings><setting name=""x-dv-webhook-secret"" value=""$escapedAuthSecret""/></settings>" $actionDescription = "Update authentication secret" } else { $authValue = "<settings></settings>" $actionDescription = "Clear authentication secret" } # Update the service endpoint $updateData = @{ "authvalue" = $authValue } $targetDescription = if ($PSCmdlet.ParameterSetName -eq 'ByName') { "$WebHookName (Service Endpoint: $serviceEndpointId)" } else { "$($webhookInfo.Name) (Step ID: $WebHookStepId, Service Endpoint: $serviceEndpointId)" } if ($PSCmdlet.ShouldProcess($targetDescription, $actionDescription)) { $requestHeaders = @{ 'Prefer' = 'odata.include-annotations="*",return=representation' } Write-Verbose "$actionDescription for webhook '$($webhookInfo.Name)'" $null = Invoke-PSDVWebRequest -WebUri "api/data/v9.2/serviceendpoints($serviceEndpointId)" -Method Patch -Body $updateData -Headers $requestHeaders Write-Verbose "Successfully updated webhook authentication secret" # Return updated webhook information return [PSCustomObject]@{ WebHookName = $webhookInfo.Name WebHookStepId = $webhookInfo.WebHookStepId Table = $Table ServiceEndpointId = $serviceEndpointId Url = $webhookInfo.Url ParameterSetUsed = $PSCmdlet.ParameterSetName AuthSecretUpdated = if ($PSBoundParameters.ContainsKey('AuthSecret') -and -not [string]::IsNullOrEmpty($AuthSecret)) { $true } else { $false } AuthSecretCleared = if (-not $PSBoundParameters.ContainsKey('AuthSecret') -or [string]::IsNullOrEmpty($AuthSecret)) { $true } else { $false } UpdatedOn = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss") } } else { $whatIfTarget = if ($PSCmdlet.ParameterSetName -eq 'ByName') { $WebHookName } else { "$($webhookInfo.Name) (Step ID: $WebHookStepId)" } Write-Verbose "Would $($actionDescription.ToLower()) for webhook: $whatIfTarget" return } } catch { $errorTarget = if ($PSCmdlet.ParameterSetName -eq 'ByName') { "'$WebHookName' in table '$Table'" } else { "step ID '$WebHookStepId' in table '$Table'" } throw "Error updating webhook auth secret for $errorTarget`: $($_.Exception.Message)" } } |