diff --git a/docs/deployment/chrome-edge-deployment-instructions/windows/domain-deployment.md b/docs/deployment/chrome-edge-deployment-instructions/windows/domain-deployment.md index 1a651c61..91de282b 100644 --- a/docs/deployment/chrome-edge-deployment-instructions/windows/domain-deployment.md +++ b/docs/deployment/chrome-edge-deployment-instructions/windows/domain-deployment.md @@ -2,28 +2,113 @@ {% tabs %} {% tab title="Intune" %} -You need to create **two custom profiles** in Intune (one for Chrome, one for Edge).\ -Each profile contains **two OMA-URI settings**: - -* **Installation policy** → tells the browser to force-install the extension. -* **Configuration policy** → applies your custom extension settings. +The simplest method of Intune deployment is via a win32 script. Follow the steps below to: *** -#### Step 1 – Open Intune and Start a New Profile +## Setup Script + +1. Download a copy of the Setup-Windows-Chrome-and-Edge.ps1 script from the Check repository on GitHub using the button below. -1. Go to Intune Admin Center. -2. Navigate to: **Devices → Configuration profiles** -3. Click on **Create → Import Policy** -4. Import the following file to deploy the extensions. This will deploy the configuration +Import File -Import File +2. Run the script locally on your computer to generate the following scripts: + 1. Deploy-Windows-Chrome-and-Edge.ps1 + 2. Remove-Windows-Chrome-and-Edge.ps1 + 3. Detect-Windows-Chrome-and-Edge.ps1 +3. You will be prompted during the Setup script on how you want to configure Check. Follow the script's guidance to ensure you're accurately entering values for the script. These values will be used for both the Deploy and Detect to ensure the extension is properly deployed. +4. Set the output location the script will use to generate the three new scripts. + +{% hint style="info" %} You can also download the three scripts directly from the Check GitHub repo and edit the configuration settings manually. {% endhint %} *** -#### Step 2: Configuration +## Adding to Intune + +### Prerequisites + +- Microsoft Intune admin access +- The [Microsoft Win32 Content Prep Tool](https://github.com/microsoft/Microsoft-Win32-Content-Prep-Tool) (`IntuneWinAppUtil.exe`) to package scripts as `.intunewin` files + +### Step 1: Package the Scripts + +Intune Win32 apps require an `.intunewin` package. Place your three configured scripts in a folder, then run: + +```powershell +.\IntuneWinAppUtil.exe -c "C:\path\to\scripts\folder" -s "Deploy-Windows-Chrome-and-Edge.ps1" -o "C:\path\to\output" +``` + +This creates `Deploy-Windows-Chrome-and-Edge.intunewin`. + +### Step 3: Configure App Information + +| Field | Value | +|-------|-------| +| Name | `Check by CyberDrain - Browser Extension` | +| Description | `Deploys and configures the Check by CyberDrain phishing protection extension for Chrome and Edge browsers.` | +| Publisher | Your company name or `CyberDrain` | + +### Step 4: Configure Program Settings + +| Field | Value | +|-------|-------| +| Install command | `powershell.exe -ExecutionPolicy Bypass -File Deploy-Windows-Chrome-and-Edge.ps1` | +| Uninstall command | `powershell.exe -ExecutionPolicy Bypass -File Remove-Windows-Chrome-and-Edge.ps1` | +| Install behavior | **System** | +| Device restart behavior | **No specific action** | + +### Step 5: Configure Requirements + +| Field | Value | +|-------|-------| +| Operating system architecture | **64-bit** | +| Minimum operating system | **Windows 10 1607** (or your minimum supported version) | + +### Step 6: Configure Detection Rules + +1. Under **Detection rules**, select **Use a custom detection script** +2. Upload `Detect-Windows-Chrome-and-Edge.ps1` +3. Set the following: + +| Field | Value | +|-------|-------| +| Run script as 32-bit process on 64-bit clients | **No** | +| Enforce script signature check | **No** | +| Run script in 64-bit PowerShell host | **No** | + +The detection script checks that all registry keys written by the install script exist and have the correct values. It exits with code `0` when everything matches (app detected) and code `1` when any value is missing or wrong (app not detected, triggers reinstall). + +### Step 7: Assign the App + +1. Under **Assignments**, click **Add group** under **Required** +2. Choose your target: + - **All devices** — deploys to every Intune-managed Windows device + - **All users** — deploys to devices used by any licensed user + - **Select groups** — deploy to specific Azure AD / Entra ID groups +3. Click **Review + create** > **Create** + +## Updating Settings + +When you need to change extension settings (e.g., enable page blocking, update branding): + +1. Re-run the setup script with new values, or manually edit the config blocks in both `Deploy-` and `Detect-` scripts +2. Re-package with `IntuneWinAppUtil.exe` +3. In Intune, either update the existing app or delete and recreate it with the new package + +Because the detection script body changes when settings change, Intune will detect the app as "not installed" on endpoints and automatically redeploy with the updated configuration. + +## Uninstalling + +To remove the extension from managed devices: + +- **Option A:** In Intune, change the app assignment from **Required** to **Uninstall**. Intune will run the `Remove-Windows-Chrome-and-Edge.ps1` script on targeted devices. +- **Option B:** Delete the app from Intune entirely. Note that this stops management but does not actively remove the registry keys from devices that already have them. + +## Troubleshooting -Documentation to follow +- **Extension not appearing after deployment:** Check that the install script ran as System (not User). Verify registry keys exist under `HKLM:\SOFTWARE\Policies\Google\Chrome\ExtensionSettings\` and `HKLM:\SOFTWARE\Policies\Microsoft\Edge\ExtensionSettings\`. +- **Intune keeps reinstalling the app:** The detection script values don't match what the install script wrote. Ensure both scripts have identical configuration values. +- **Detection script shows as failed:** Run the detection script manually on a test device as Administrator to see which check fails (it will exit at the first mismatch). {% endtab %} {% tab title="Group Policy" %} diff --git a/enterprise/Detect-Windows-Chrome-and-Edge.ps1 b/enterprise/Detect-Windows-Chrome-and-Edge.ps1 new file mode 100644 index 00000000..d97a6f29 --- /dev/null +++ b/enterprise/Detect-Windows-Chrome-and-Edge.ps1 @@ -0,0 +1,170 @@ +# Check Extension - Intune Detection Script +# This script verifies that the Check by CyberDrain extension is correctly configured +# in the registry for both Chrome and Edge browsers. +# +# IMPORTANT: The settings below MUST match the values in your Deploy-Windows-Chrome-and-Edge.ps1. +# If any value differs, Intune will detect the app as "not installed" and trigger a reinstall. +# +# Exit codes: 0 = compliant (extension correctly configured), 1 = non-compliant (drift detected) + +# Define extension details +# Chrome +$chromeExtensionId = "benimdeioplgkhanklclahllklceahbe" +$chromeUpdateUrl = "https://clients2.google.com/service/update2/crx" +$chromeManagedStorageKey = "HKLM:\SOFTWARE\Policies\Google\Chrome\3rdparty\extensions\$chromeExtensionId\policy" +$chromeExtensionSettingsKey = "HKLM:\SOFTWARE\Policies\Google\Chrome\ExtensionSettings\$chromeExtensionId" + +#Edge +$edgeExtensionId = "knepjpocdagponkonnbggpcnhnaikajg" +$edgeUpdateUrl = "https://edge.microsoft.com/extensionwebstorebase/v1/crx" +$edgeManagedStorageKey = "HKLM:\SOFTWARE\Policies\Microsoft\Edge\3rdparty\extensions\$edgeExtensionId\policy" +$edgeExtensionSettingsKey = "HKLM:\SOFTWARE\Policies\Microsoft\Edge\ExtensionSettings\$edgeExtensionId" + +# Extension Configuration Settings +$showNotifications = 1 # 0 = Unchecked, 1 = Checked (Enabled); default is 1; This will set the "Show Notifications" option in the extension settings. +$enableValidPageBadge = 0 # 0 = Unchecked, 1 = Checked (Enabled); default is 0; This will set the "Show Valid Page Badge" option in the extension settings. +$enablePageBlocking = 1 # 0 = Unchecked, 1 = Checked (Enabled); default is 1; This will set the "Enable Page Blocking" option in the extension settings. +$forceToolbarPin = 1 # 0 = Not pinned, 1 = Force pinned to toolbar; default is 1 +$enableCippReporting = 0 # 0 = Unchecked, 1 = Checked (Enabled); default is 0; This will set the "Enable CIPP Reporting" option in the extension settings. +$cippServerUrl = "" # This will set the "CIPP Server URL" option in the extension settings; default is blank; if you set $enableCippReporting to 1, you must set this to a valid URL including the protocol (e.g., https://cipp.cyberdrain.com). Can be vanity URL or the default azurestaticapps.net domain. +$cippTenantId = "" # This will set the "Tenant ID/Domain" option in the extension settings; default is blank; if you set $enableCippReporting to 1, you must set this to a valid Tenant ID. +$customRulesUrl = "" # This will set the "Config URL" option in the Detection Configuration settings; default is blank. +$updateInterval = 24 # This will set the "Update Interval" option in the Detection Configuration settings; default is 24 (hours). Range: 1-168 hours (1 hour to 1 week). +$urlAllowlist = @() # This will set the "URL Allowlist" option in the Detection Configuration settings; default is blank; if you want to add multiple URLs, add them as a comma-separated list within the brackets (e.g., @("https://example1.com", "https://example2.com")). Supports simple URLs with * wildcard (e.g., https://*.example.com) or advanced regex patterns (e.g., ^https:\/\/(www\.)?example\.com\/.*$). +$domainSquattingEnabled = 1 # 0 = Disabled, 1 = Enabled; default is 1; controls domain squatting detection from managed policy/config. +$enableDebugLogging = 0 # 0 = Unchecked, 1 = Checked (Enabled); default is 0; This will set the "Enable Debug Logging" option in the Activity Log settings. + +# Generic Webhook Settings +$enableGenericWebhook = 0 # 0 = Disabled, 1 = Enabled; default is 0; This will enable the generic webhook for sending detection events to a custom endpoint. +$webhookUrl = "" # This will set the "Webhook URL" option; default is blank; if you set $enableGenericWebhook to 1, you must set this to a valid URL including the protocol (e.g., https://webhook.example.com/endpoint). +$webhookEvents = @() # This will set the "Event Types" to send to the webhook; default is blank; if you set $enableGenericWebhook to 1, you can specify which events to send. Available events: "detection_alert", "false_positive_report", "page_blocked", "rogue_app_detected", "threat_detected", "validation_event". Example: @("detection_alert", "page_blocked", "threat_detected"). + +# Custom Branding Settings +$companyName = "CyberDrain" # This will set the "Company Name" option in the Custom Branding settings; default is "CyberDrain". +$productName = "Check - Phishing Protection" # This will set the "Product Name" option in the Custom Branding settings; default is "Check - Phishing Protection". +$supportEmail = "" # This will set the "Support Email" option in the Custom Branding settings; default is blank. +$supportUrl = "" # This will set the "Support URL" option in the Custom Branding settings; default is blank. +$privacyPolicyUrl = "" # This will set the "Privacy URL" option in the Custom Branding settings; default is blank. +$aboutUrl = "" # This will set the "About URL" option in the Custom Branding settings; default is blank. +$primaryColor = "#F77F00" # This will set the "Primary Color" option in the Custom Branding settings; default is "#F77F00"; must be a valid hex color code (e.g., #FFFFFF). +$logoUrl = "" # This will set the "Logo URL" option in the Custom Branding settings; default is blank. Must be a valid URL including the protocol (e.g., https://example.com/logo.png); protocol must be https; recommended size is 48x48 pixels with a maximum of 128x128. + +# Extension Settings +$installationMode = "force_installed" + +# Helper to check a registry value matches expected +function Test-RegValue { + param ( + [string]$Path, + [string]$Name, + $Expected + ) + $val = (Get-ItemProperty -Path $Path -Name $Name -ErrorAction SilentlyContinue).$Name + return ($null -ne $val -and $val -eq $Expected) +} + +# Define browser configurations for detection +$browsers = @( + @{ + Name = 'Chrome' + ExtensionId = $chromeExtensionId + UpdateUrl = $chromeUpdateUrl + ManagedStorageKey = $chromeManagedStorageKey + ExtensionSettingsKey = $chromeExtensionSettingsKey + ToolbarProp = 'toolbar_pin' + ToolbarValue = 'force_pinned' + }, + @{ + Name = 'Edge' + ExtensionId = $edgeExtensionId + UpdateUrl = $edgeUpdateUrl + ManagedStorageKey = $edgeManagedStorageKey + ExtensionSettingsKey = $edgeExtensionSettingsKey + ToolbarProp = 'toolbar_state' + ToolbarValue = 'force_shown' + } +) + +foreach ($browser in $browsers) { + # Verify managed storage key exists + if (!(Test-Path $browser.ManagedStorageKey)) { exit 1 } + + $policyKey = $browser.ManagedStorageKey + + # Core DWord settings + if (!(Test-RegValue $policyKey 'showNotifications' $showNotifications)) { exit 1 } + if (!(Test-RegValue $policyKey 'enableValidPageBadge' $enableValidPageBadge)) { exit 1 } + if (!(Test-RegValue $policyKey 'enablePageBlocking' $enablePageBlocking)) { exit 1 } + if (!(Test-RegValue $policyKey 'enableCippReporting' $enableCippReporting)) { exit 1 } + if (!(Test-RegValue $policyKey 'updateInterval' $updateInterval)) { exit 1 } + if (!(Test-RegValue $policyKey 'enableDebugLogging' $enableDebugLogging)) { exit 1 } + + # Core String settings + if (!(Test-RegValue $policyKey 'cippServerUrl' $cippServerUrl)) { exit 1 } + if (!(Test-RegValue $policyKey 'cippTenantId' $cippTenantId)) { exit 1 } + if (!(Test-RegValue $policyKey 'customRulesUrl' $customRulesUrl)) { exit 1 } + + # domainSquatting subkey + $domainSquattingKey = "$policyKey\domainSquatting" + if (!(Test-Path $domainSquattingKey)) { exit 1 } + if (!(Test-RegValue $domainSquattingKey 'enabled' $domainSquattingEnabled)) { exit 1 } + + # customBranding subkey + $brandingKey = "$policyKey\customBranding" + if (!(Test-Path $brandingKey)) { exit 1 } + if (!(Test-RegValue $brandingKey 'companyName' $companyName)) { exit 1 } + if (!(Test-RegValue $brandingKey 'productName' $productName)) { exit 1 } + if (!(Test-RegValue $brandingKey 'supportEmail' $supportEmail)) { exit 1 } + if (!(Test-RegValue $brandingKey 'supportUrl' $supportUrl)) { exit 1 } + if (!(Test-RegValue $brandingKey 'privacyPolicyUrl' $privacyPolicyUrl)) { exit 1 } + if (!(Test-RegValue $brandingKey 'aboutUrl' $aboutUrl)) { exit 1 } + if (!(Test-RegValue $brandingKey 'primaryColor' $primaryColor)) { exit 1 } + if (!(Test-RegValue $brandingKey 'logoUrl' $logoUrl)) { exit 1 } + + # genericWebhook subkey + $webhookKey = "$policyKey\genericWebhook" + if (!(Test-Path $webhookKey)) { exit 1 } + if (!(Test-RegValue $webhookKey 'enabled' $enableGenericWebhook)) { exit 1 } + if (!(Test-RegValue $webhookKey 'url' $webhookUrl)) { exit 1 } + + # genericWebhook\events subkey — verify exact count and values + $eventsKey = "$webhookKey\events" + if (!(Test-Path $eventsKey)) { exit 1 } + if ($webhookEvents.Count -gt 0) { + $eventsCount = (Get-Item $eventsKey).Property.Count + if ($eventsCount -ne $webhookEvents.Count) { exit 1 } + for ($i = 0; $i -lt $webhookEvents.Count; $i++) { + if (!(Test-RegValue $eventsKey ($i + 1).ToString() $webhookEvents[$i])) { exit 1 } + } + } else { + $existingEvents = (Get-Item $eventsKey).Property + if ($null -ne $existingEvents -and $existingEvents.Count -gt 0) { exit 1 } + } + + # urlAllowlist subkey — verify exact count and values + $allowlistKey = "$policyKey\urlAllowlist" + if (!(Test-Path $allowlistKey)) { exit 1 } + if ($urlAllowlist.Count -gt 0) { + $allowlistCount = (Get-Item $allowlistKey).Property.Count + if ($allowlistCount -ne $urlAllowlist.Count) { exit 1 } + for ($i = 0; $i -lt $urlAllowlist.Count; $i++) { + if (!(Test-RegValue $allowlistKey ($i + 1).ToString() $urlAllowlist[$i])) { exit 1 } + } + } else { + $existingAllowlist = (Get-Item $allowlistKey).Property + if ($null -ne $existingAllowlist -and $existingAllowlist.Count -gt 0) { exit 1 } + } + + # ExtensionSettings key + if (!(Test-Path $browser.ExtensionSettingsKey)) { exit 1 } + if (!(Test-RegValue $browser.ExtensionSettingsKey 'installation_mode' $installationMode)) { exit 1 } + if (!(Test-RegValue $browser.ExtensionSettingsKey 'update_url' $browser.UpdateUrl)) { exit 1 } + + # Toolbar pin — only checked when enabled (upstream install script does not write this property when disabled) + if ($forceToolbarPin -eq 1) { + if (!(Test-RegValue $browser.ExtensionSettingsKey $browser.ToolbarProp $browser.ToolbarValue)) { exit 1 } + } +} + +Write-Output "Check extension is correctly configured for Chrome and Edge." +exit 0 diff --git a/enterprise/Setup-Windows-Chrome-and-Edge.ps1 b/enterprise/Setup-Windows-Chrome-and-Edge.ps1 new file mode 100644 index 00000000..3b7974ae --- /dev/null +++ b/enterprise/Setup-Windows-Chrome-and-Edge.ps1 @@ -0,0 +1,290 @@ +# Check Extension - Interactive Setup Script +# Downloads the latest Check extension deployment scripts from GitHub and walks you +# through configuring each setting. Outputs ready-to-upload scripts for Intune. +# +# Usage: Run this script in PowerShell. It will prompt for each setting and generate +# configured Deploy, Remove, and Detect scripts in your chosen output directory. +# +# For Intune deployment instructions, see: +# https://docs.check.tech/deployment/chrome-edge-deployment-instructions/windows/domain-deployment#intune + +Write-Host "" +Write-Host "======================================================" -ForegroundColor DarkCyan +Write-Host " Check by CyberDrain - Intune Deployment Setup" -ForegroundColor DarkCyan +Write-Host "======================================================" -ForegroundColor DarkCyan +Write-Host "" +Write-Host "This script will download the latest Check extension scripts from GitHub" +Write-Host "and walk you through configuring each setting for your environment." +Write-Host "" + +# GitHub raw URLs for the template scripts +$baseUrl = "https://raw.githubusercontent.com/CyberDrain/Check/refs/heads/main/enterprise" +$scripts = @{ + Deploy = @{ Url = "$baseUrl/Deploy-Windows-Chrome-and-Edge.ps1"; FileName = "Deploy-Windows-Chrome-and-Edge.ps1" } + Remove = @{ Url = "$baseUrl/Remove-Windows-Chrome-and-Edge.ps1"; FileName = "Remove-Windows-Chrome-and-Edge.ps1" } + Detect = @{ Url = "$baseUrl/Detect-Windows-Chrome-and-Edge.ps1"; FileName = "Detect-Windows-Chrome-and-Edge.ps1" } +} + +# Download templates +Write-Host "Downloading latest scripts from GitHub..." -ForegroundColor Yellow +$templates = @{} +foreach ($key in $scripts.Keys) { + try { + $templates[$key] = Invoke-WebRequest -Uri $scripts[$key].Url -UseBasicParsing -TimeoutSec 30 | Select-Object -ExpandProperty Content + Write-Host " Downloaded $($scripts[$key].FileName)" -ForegroundColor Green + } catch { + Write-Host " Failed to download $($scripts[$key].FileName): $($_.Exception.Message)" -ForegroundColor Red + Write-Host " Please check your internet connection and try again." -ForegroundColor Red + exit 1 + } +} +Write-Host "" + +# Prompt helper functions +function Read-Setting { + param ( + [string]$Name, + [string]$Description, + [string]$Default, + [string]$Type = "string" + ) + $prompt = "$Name - $Description" + if ($Default -ne "") { + $prompt += " [default: $Default]" + } else { + $prompt += " [default: blank]" + } + $value = Read-Host $prompt + if ($value -eq "") { $value = $Default } + + if ($Type -eq "bool") { + while ($value -ne "0" -and $value -ne "1") { + Write-Host " Please enter 0 or 1." -ForegroundColor Yellow + $value = Read-Host $prompt + if ($value -eq "") { $value = $Default } + } + } + if ($Type -eq "int") { + while ($value -notmatch '^\d+$') { + Write-Host " Please enter a number." -ForegroundColor Yellow + $value = Read-Host $prompt + if ($value -eq "") { $value = $Default } + } + if ($Name -eq "updateInterval") { + while ([int]$value -lt 1 -or [int]$value -gt 168) { + Write-Host " Update interval must be between 1 and 168 hours." -ForegroundColor Yellow + $value = Read-Host $prompt + if ($value -eq "") { $value = $Default } + } + } + } + if ($Type -eq "string" -and $value -match '"') { + while ($value -match '"') { + Write-Host " Double-quote characters are not supported in this field." -ForegroundColor Yellow + $value = Read-Host $prompt + if ($value -eq "") { $value = $Default } + } + } + return $value +} + +function Read-ArraySetting { + param ( + [string]$Name, + [string]$Description + ) + Write-Host "$Name - $Description" + Write-Host " Enter values one at a time. Press Enter on a blank line when done." + $values = @() + $i = 1 + while ($true) { + $entry = Read-Host " [$i]" + if ($entry -eq "") { break } + $values += $entry + $i++ + } + return $values +} + +####################################################################### +# Extension Configuration Settings +####################################################################### +Write-Host "--- Extension Configuration Settings ---" -ForegroundColor Cyan +Write-Host "" + +$cfg_showNotifications = Read-Setting -Name "showNotifications" -Description "Show notifications (0 = Disabled, 1 = Enabled)" -Default "1" -Type "bool" +$cfg_enableValidPageBadge = Read-Setting -Name "enableValidPageBadge" -Description "Show valid page badge (0 = Disabled, 1 = Enabled)" -Default "0" -Type "bool" +$cfg_enablePageBlocking = Read-Setting -Name "enablePageBlocking" -Description "Enable page blocking (0 = Disabled, 1 = Enabled)" -Default "1" -Type "bool" +$cfg_forceToolbarPin = Read-Setting -Name "forceToolbarPin" -Description "Force pin extension to toolbar (0 = Not pinned, 1 = Force pinned)" -Default "1" -Type "bool" +$cfg_updateInterval = Read-Setting -Name "updateInterval" -Description "Update interval in hours (1-168)" -Default "24" -Type "int" +$cfg_enableDebugLogging = Read-Setting -Name "enableDebugLogging" -Description "Enable debug logging (0 = Disabled, 1 = Enabled)" -Default "0" -Type "bool" +$cfg_domainSquattingEnabled = Read-Setting -Name "domainSquattingEnabled" -Description "Enable domain squatting detection (0 = Disabled, 1 = Enabled)" -Default "1" -Type "bool" +$cfg_customRulesUrl = Read-Setting -Name "customRulesUrl" -Description "Custom rules/config URL (leave blank if not used)" -Default "" +Write-Host "" + +####################################################################### +# CIPP Reporting +####################################################################### +Write-Host "--- CIPP Reporting ---" -ForegroundColor Cyan +Write-Host "" + +$cfg_enableCippReporting = Read-Setting -Name "enableCippReporting" -Description "Enable CIPP reporting (0 = Disabled, 1 = Enabled)" -Default "0" -Type "bool" +if ($cfg_enableCippReporting -eq "1") { + $cfg_cippServerUrl = Read-Setting -Name "cippServerUrl" -Description "CIPP Server URL (e.g., https://cipp.cyberdrain.com)" -Default "" + $cfg_cippTenantId = Read-Setting -Name "cippTenantId" -Description "Tenant ID or domain for CIPP reporting" -Default "" +} else { + $cfg_cippServerUrl = "" + $cfg_cippTenantId = "" +} +Write-Host "" + +####################################################################### +# Generic Webhook Settings +####################################################################### +Write-Host "--- Generic Webhook Settings ---" -ForegroundColor Cyan +Write-Host "" + +$cfg_enableGenericWebhook = Read-Setting -Name "enableGenericWebhook" -Description "Enable generic webhook (0 = Disabled, 1 = Enabled)" -Default "0" -Type "bool" +if ($cfg_enableGenericWebhook -eq "1") { + $cfg_webhookUrl = Read-Setting -Name "webhookUrl" -Description "Webhook URL (e.g., https://webhook.example.com/endpoint)" -Default "" + $cfg_webhookEvents = Read-ArraySetting -Name "webhookEvents" -Description "Event types to send. Available: detection_alert, false_positive_report, page_blocked, rogue_app_detected, threat_detected, validation_event" +} else { + $cfg_webhookUrl = "" + $cfg_webhookEvents = @() +} +Write-Host "" + +####################################################################### +# URL Allowlist +####################################################################### +Write-Host "--- URL Allowlist ---" -ForegroundColor Cyan +Write-Host "" + +$cfg_urlAllowlist = Read-ArraySetting -Name "urlAllowlist" -Description "URLs to allowlist. Supports wildcards (e.g., https://*.example.com) and regex patterns" +Write-Host "" + +####################################################################### +# Custom Branding Settings +####################################################################### +Write-Host "--- Custom Branding Settings ---" -ForegroundColor Cyan +Write-Host "" + +$cfg_companyName = Read-Setting -Name "companyName" -Description "Company name" -Default "CyberDrain" +$cfg_productName = Read-Setting -Name "productName" -Description "Product name" -Default "Check - Phishing Protection" +$cfg_supportEmail = Read-Setting -Name "supportEmail" -Description "Support email address" -Default "" +$cfg_supportUrl = Read-Setting -Name "supportUrl" -Description "Support URL" -Default "" +$cfg_privacyPolicyUrl = Read-Setting -Name "privacyPolicyUrl" -Description "Privacy policy URL" -Default "" +$cfg_aboutUrl = Read-Setting -Name "aboutUrl" -Description "About URL" -Default "" +$cfg_primaryColor = Read-Setting -Name "primaryColor" -Description "Primary color (hex code)" -Default "#F77F00" +$cfg_logoUrl = Read-Setting -Name "logoUrl" -Description "Logo URL (https, recommended 48x48, max 128x128)" -Default "" +Write-Host "" + +####################################################################### +# Output Path +####################################################################### +Write-Host "--- Output ---" -ForegroundColor Cyan +Write-Host "" + +$defaultOutputPath = (Get-Location).Path +$outputPath = Read-Host "Output directory [default: $defaultOutputPath]" +if ($outputPath -eq "") { $outputPath = $defaultOutputPath } + +if (!(Test-Path $outputPath)) { + New-Item -Path $outputPath -ItemType Directory -Force | Out-Null + Write-Host "Created output directory: $outputPath" -ForegroundColor Green +} +Write-Host "" + +####################################################################### +# Build replacement map +####################################################################### + +# Helper to build a PowerShell array literal string from an array +function Format-ArrayLiteral { + param ([string[]]$Values) + if ($Values.Count -eq 0) { return '@()' } + $quoted = $Values | ForEach-Object { $escaped = $_ -replace '"', '""'; "`"$escaped`"" } + return "@($($quoted -join ', '))" +} + +# Each entry: variable assignment pattern to find -> replacement value +# Scalar replacements target the value + start of inline comment +$replacements = @( + @{ Pattern = '$showNotifications = 1 #'; Value = "`$showNotifications = $cfg_showNotifications #" } + @{ Pattern = '$enableValidPageBadge = 0 #'; Value = "`$enableValidPageBadge = $cfg_enableValidPageBadge #" } + @{ Pattern = '$enablePageBlocking = 1 #'; Value = "`$enablePageBlocking = $cfg_enablePageBlocking #" } + @{ Pattern = '$forceToolbarPin = 1 #'; Value = "`$forceToolbarPin = $cfg_forceToolbarPin #" } + @{ Pattern = '$enableCippReporting = 0 #'; Value = "`$enableCippReporting = $cfg_enableCippReporting #" } + @{ Pattern = '$cippServerUrl = "" #'; Value = "`$cippServerUrl = `"$cfg_cippServerUrl`" #" } + @{ Pattern = '$cippTenantId = "" #'; Value = "`$cippTenantId = `"$cfg_cippTenantId`" #" } + @{ Pattern = '$customRulesUrl = "" #'; Value = "`$customRulesUrl = `"$cfg_customRulesUrl`" #" } + @{ Pattern = '$updateInterval = 24 #'; Value = "`$updateInterval = $cfg_updateInterval #" } + @{ Pattern = '$domainSquattingEnabled = 1 #'; Value = "`$domainSquattingEnabled = $cfg_domainSquattingEnabled #" } + @{ Pattern = '$enableDebugLogging = 0 #'; Value = "`$enableDebugLogging = $cfg_enableDebugLogging #" } + @{ Pattern = '$enableGenericWebhook = 0 #'; Value = "`$enableGenericWebhook = $cfg_enableGenericWebhook #" } + @{ Pattern = '$webhookUrl = "" #'; Value = "`$webhookUrl = `"$cfg_webhookUrl`" #" } + @{ Pattern = '$companyName = "CyberDrain" #'; Value = "`$companyName = `"$cfg_companyName`" #" } + @{ Pattern = '$productName = "Check - Phishing Protection" #'; Value = "`$productName = `"$cfg_productName`" #" } + @{ Pattern = '$supportEmail = "" #'; Value = "`$supportEmail = `"$cfg_supportEmail`" #" } + @{ Pattern = '$supportUrl = "" #'; Value = "`$supportUrl = `"$cfg_supportUrl`" #" } + @{ Pattern = '$privacyPolicyUrl = "" #'; Value = "`$privacyPolicyUrl = `"$cfg_privacyPolicyUrl`" #" } + @{ Pattern = '$aboutUrl = "" #'; Value = "`$aboutUrl = `"$cfg_aboutUrl`" #" } + @{ Pattern = '$primaryColor = "#F77F00" #'; Value = "`$primaryColor = `"$cfg_primaryColor`" #" } + @{ Pattern = '$logoUrl = "" #'; Value = "`$logoUrl = `"$cfg_logoUrl`" #" } +) + +# Array replacements — replace the full assignment line including inline comment +$arrayReplacements = @( + @{ Pattern = '$urlAllowlist = @() #'; Value = "`$urlAllowlist = $(Format-ArrayLiteral $cfg_urlAllowlist) #" } + @{ Pattern = '$webhookEvents = @() #'; Value = "`$webhookEvents = $(Format-ArrayLiteral $cfg_webhookEvents) #" } +) + +####################################################################### +# Apply replacements and write output files +####################################################################### + +function Apply-Replacements { + param ([string]$Content) + + foreach ($r in $replacements) { + $Content = $Content.Replace($r.Pattern, $r.Value) + } + foreach ($r in $arrayReplacements) { + $Content = $Content.Replace($r.Pattern, $r.Value) + } + + return $Content +} + +# Deploy script — apply all replacements +$deployContent = Apply-Replacements -Content $templates['Deploy'] +$deployPath = Join-Path $outputPath $scripts['Deploy'].FileName +Set-Content -Path $deployPath -Value $deployContent -Encoding UTF8 +Write-Host "Written: $deployPath" -ForegroundColor Green + +# Detect script — apply all replacements (same config block format) +$detectContent = Apply-Replacements -Content $templates['Detect'] +$detectPath = Join-Path $outputPath $scripts['Detect'].FileName +Set-Content -Path $detectPath -Value $detectContent -Encoding UTF8 +Write-Host "Written: $detectPath" -ForegroundColor Green + +# Remove script — copy as-is (no config to replace) +$removePath = Join-Path $outputPath $scripts['Remove'].FileName +Set-Content -Path $removePath -Value $templates['Remove'] -Encoding UTF8 +Write-Host "Written: $removePath" -ForegroundColor Green + +Write-Host "" +Write-Host "======================================================" -ForegroundColor DarkCyan +Write-Host " Setup complete!" -ForegroundColor Green +Write-Host "======================================================" -ForegroundColor DarkCyan +Write-Host "" +Write-Host "Your configured scripts are in: $outputPath" -ForegroundColor Yellow +Write-Host "" +Write-Host "Next steps:" -ForegroundColor Yellow +Write-Host " 1. Package the scripts as a Win32 app (.intunewin) or use Intune's script deployment" +Write-Host " 2. Upload to Microsoft Intune admin center > Apps > Windows" +Write-Host " 3. Set install command: powershell.exe -ExecutionPolicy Bypass -File Deploy-Windows-Chrome-and-Edge.ps1" +Write-Host " 4. Set uninstall command: powershell.exe -ExecutionPolicy Bypass -File Remove-Windows-Chrome-and-Edge.ps1" +Write-Host " 5. Add detection script: Detect-Windows-Chrome-and-Edge.ps1" +Write-Host " 6. Assign to devices/users as Required" +Write-Host ""