diff --git a/Task/Deploy-CheckExtension.ps1 b/Task/Deploy-CheckExtension.ps1 index cf72ddd..be87597 100644 --- a/Task/Deploy-CheckExtension.ps1 +++ b/Task/Deploy-CheckExtension.ps1 @@ -113,6 +113,22 @@ Enable Debug Logging. Maps to "Enable Debug Logging" in Activity Log settings. A list of URLs that will completely bypass blocking. Entering **ANY** will decrease security on that website significantly. '@)][string[]]$urlAllowlist, + [Parameter(HelpMessage=@' +Enable Generic Webhook. Maps to "Generic Webhook Enabled" in webhook settings. +| State | Effect | +|-------|-----------------------------------------------------| +| `0` | Disabled (default) | +| `1` | Enabled (requires GenericWebhookUrl and Events) | +'@)][ValidateSet(0,1)][int]$EnableGenericWebhook = 0, + [Parameter(HelpMessage=@' +Generic Webhook URL. Required if EnableGenericWebhook=1. Blank by default. +'@)][string]$GenericWebhookUrl = '', + [Parameter(HelpMessage=@' +Generic Webhook Event Types. Array of event types to send to the webhook. +Valid values: detection_alert, false_positive_report, page_blocked, rogue_app_detected, threat_detected, validation_event +'@)][ValidateSet('detection_alert','false_positive_report','page_blocked','rogue_app_detected','threat_detected','validation_event')] + [string[]]$GenericWebhookEvents, + [Parameter(HelpMessage=@' Branding: Company Name shown in extension UI. '@)][string]$CompanyName = 'CyberDrain', @@ -142,6 +158,44 @@ Write-Host "Starting enforcement for Extensions: Chrome=$ChromeExtensionId Edge= # [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter','')] param([string]$FutureParam) # Prefer explicit functional parameters over relying on script scope to satisfy analyzers & improve clarity. +function ConvertTo-StringArray { + <# + .SYNOPSIS + Safely converts input to a properly typed string array for registry MultiString values. + .DESCRIPTION + Ensures the returned value is always System.String[] type, never Object[]. + Handles null, empty arrays, and arrays with values correctly. + Uses [string[]] casting with explicit array conversion to ensure type survives $using: scope transfer. + #> + param([Parameter(ValueFromPipeline)]$InputArray) + + # If null, return empty string array with explicit type + if ($null -eq $InputArray) { + $emptyArray = [string[]]::new(0) + return ,$emptyArray + } + + # Ensure it's treated as an array + $arr = @($InputArray) + if ($arr.Count -eq 0) { + $emptyArray = [string[]]::new(0) + return ,$emptyArray + } + + # Use strongly typed array creation + $stringArray = [string[]]::new($arr.Count) + for ($i = 0; $i -lt $arr.Count; $i++) { + if ($null -ne $arr[$i]) { + $stringArray[$i] = [string]$arr[$i] + } else { + $stringArray[$i] = [string]::Empty + } + } + + # Return with unary comma to prevent unwrapping + return ,$stringArray +} + function Get-ManagedStorageBasePath { param( [string]$ChromeExtensionId, @@ -171,6 +225,9 @@ function Get-DesiredItem { [int]$UpdateInterval, [int]$EnableDebugLogging, [string[]]$urlAllowlist, + [int]$EnableGenericWebhook, + [string]$GenericWebhookUrl, + [string[]]$GenericWebhookEvents, [string]$CompanyName, [string]$CompanyUrl, [string]$ProductName, @@ -187,6 +244,7 @@ function Get-DesiredItem { foreach($b in $bases){ # Build canonical Present arrays once $brandingKey = Join-Path $b.ManagedKey 'customBranding' + $webhookKey = Join-Path $b.ManagedKey 'genericWebhook' $policyItems = @( @{ Path=$b.ManagedKey; Name='showNotifications'; Type='DWord'; Value=$ShowNotifications }, @{ Path=$b.ManagedKey; Name='enableValidPageBadge'; Type='DWord'; Value=$EnableValidPageBadge }, @@ -197,7 +255,12 @@ function Get-DesiredItem { @{ Path=$b.ManagedKey; Name='customRulesUrl'; Type='String'; Value=$CustomRulesUrl }, @{ Path=$b.ManagedKey; Name='updateInterval'; Type='DWord'; Value=$UpdateInterval }, @{ Path=$b.ManagedKey; Name='enableDebugLogging'; Type='DWord'; Value=$EnableDebugLogging } - @{ Path=$b.ManagedKey; Name='urlAllowlist'; Type='MultiString'; Value=$urlAllowlist } + @{ Path=$b.ManagedKey; Name='urlAllowlist'; Type='MultiString'; Value=(ConvertTo-StringArray $urlAllowlist) } + ) + $webhookItems = @( + @{ Path=$webhookKey; Name='enabled'; Type='DWord'; Value=$EnableGenericWebhook }, + @{ Path=$webhookKey; Name='url'; Type='String'; Value=$GenericWebhookUrl }, + @{ Path=$webhookKey; Name='events'; Type='MultiString'; Value=(ConvertTo-StringArray $GenericWebhookEvents) } ) $brandingItems = @( @{ Path=$brandingKey; Name='companyName'; Type='String'; Value=$CompanyName }, @@ -213,16 +276,17 @@ function Get-DesiredItem { ) if($Ensure -eq 'Present'){ - $policyItems + $brandingItems + $settingsItems | ForEach-Object { $_ } + $policyItems + $webhookItems + $brandingItems + $settingsItems | ForEach-Object { $_ } } else { # Transform for Absent: null policy & branding values, block extension, drop update_url $absentPolicy = $policyItems | ForEach-Object { @{ Path=$_.Path; Name=$_.Name; Type=$_.Type; Value=$null } } + $absentWebhook = $webhookItems | ForEach-Object { @{ Path=$_.Path; Name=$_.Name; Type=$_.Type; Value=$null } } $absentBranding = $brandingItems | ForEach-Object { @{ Path=$_.Path; Name=$_.Name; Type=$_.Type; Value=$null } } $absentSettings = @( @{ Path=$b.SettingsKey; Name='installation_mode'; Type='String'; Value='blocked' }, @{ Path=$b.SettingsKey; Name='update_url'; Type='Remove'; Value=$null } ) - $absentPolicy + $absentBranding + $absentSettings | ForEach-Object { $_ } + $absentPolicy + $absentWebhook + $absentBranding + $absentSettings | ForEach-Object { $_ } } } } @@ -234,6 +298,15 @@ if($EnableCippReporting -eq 1){ } } +if($EnableGenericWebhook -eq 1){ + if([string]::IsNullOrWhiteSpace($GenericWebhookUrl)){ + throw 'GenericWebhookUrl must be provided when EnableGenericWebhook=1.' + } + if($null -eq $GenericWebhookEvents -or $GenericWebhookEvents.Count -eq 0){ + throw 'At least one event type must be specified in GenericWebhookEvents when EnableGenericWebhook=1.' + } +} + # Build desired items once $desiredItems = Get-DesiredItem ` -Ensure $Ensure ` @@ -251,6 +324,9 @@ $desiredItems = Get-DesiredItem ` -UpdateInterval $UpdateInterval ` -EnableDebugLogging $EnableDebugLogging ` -urlAllowlist $urlAllowlist ` + -EnableGenericWebhook $EnableGenericWebhook ` + -GenericWebhookUrl $GenericWebhookUrl ` + -GenericWebhookEvents $GenericWebhookEvents ` -CompanyName $CompanyName ` -CompanyUrl $CompanyUrl ` -ProductName $ProductName `