diff --git a/README.md b/README.md index 3923413..86b46b9 100644 --- a/README.md +++ b/README.md @@ -145,7 +145,9 @@ sudo scripts/install-extension-policy.sh ``` No administrator rights on Windows, where it goes into the user's own policy -hive; root on Linux, where Chrome only reads policy from `/etc`. See +hive; root on Linux, where Chrome only reads policy from `/etc`. **Not Edge** — +an unmanaged Edge refuses to install anything that is not from the Microsoft +Store, so use Chrome or Brave, or run the unpacked copy there. See [deploy/README.md](deploy/README.md). Either way the extension notices when the dashboard is running newer code than it is: a policy install asks Chrome to fetch the new CRX, an unpacked one reloads itself from disk. Clicking the reload diff --git a/deploy/README.md b/deploy/README.md index 49189fc..eb465b9 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -93,10 +93,22 @@ powershell -NoProfile -ExecutionPolicy Bypass -File scripts\install-extension-po sudo scripts/install-extension-policy.sh ``` -Both configure every Chromium-family browser they find — Chrome, Edge and Brave -take the same CRX, the same update manifest and the same policy, differing only -in where that policy is written. Narrow it with `-Browser Edge` if you would -rather not. +Both configure every Chromium-family browser they find, and narrowing that to +one is `-Browser Chrome`. + +**Edge is the exception, and it is not one we can fix.** Unmanaged Edge installs +extensions from the Microsoft Store and nowhere else. It reads the policy and +then blanks it — `edge://policy` shows `[BLOCKED];` with "This device +isn't managed by your organization" — so a self-hosted CRX cannot be installed +there at all unless the machine is domain-joined, Intune-enrolled or +Entra-joined. Chrome and Brave have no equivalent restriction. The script +detects this and skips Edge rather than leaving a permanent policy error and a +"Managed by your organization" badge behind; `-Force` overrides it. + +On a machine that has to be Edge, load `extension/` unpacked there instead. It +still picks up releases: an unpacked copy reloads itself from disk when the +dashboard reports a newer version, which is what the updater has already +pulled. The Windows script writes to the current user's policy hive and needs no elevation; `-Scope Machine` covers every account on the box and does need an diff --git a/scripts/install-extension-policy.ps1 b/scripts/install-extension-policy.ps1 index a8b9023..9ff58f9 100644 --- a/scripts/install-extension-policy.ps1 +++ b/scripts/install-extension-policy.ps1 @@ -44,7 +44,10 @@ param( [string]$UpdateUrl = 'https://ext.juicerroom.com/updates.xml', - [switch]$Remove + [switch]$Remove, + + # Write the Edge policy even though Edge will refuse to act on it. + [switch]$Force ) $ErrorActionPreference = 'Stop' @@ -91,6 +94,28 @@ function Test-BrowserInstalled([string]$Name) { return $false } +<# + Edge refuses to install an extension it did not get from the Microsoft Store + unless the device is managed — domain-joined, Intune-enrolled or Entra-joined. + The policy is read and then blanked: edge://policy shows the value as + "[BLOCKED]..." with "This device isn't managed by your organization", and an + "Invalid extension ID" error from parsing that prefix. + + Chrome and Brave have no such restriction. So on an unmanaged machine there + is nothing to be gained by writing Edge's key, and a real cost: Edge starts + reporting "Managed by your organization" and shows a policy error forever. +#> +function Test-DeviceManaged { + try { + $status = & dsregcmd /status 2>$null | Out-String + return ($status -match 'AzureAdJoined\s*:\s*YES') -or + ($status -match 'DomainJoined\s*:\s*YES') -or + ($status -match 'EnterpriseJoined\s*:\s*YES') + } catch { + return $false # no dsregcmd is itself a fair sign this is not managed + } +} + $hive = if ($Scope -eq 'Machine') { 'HKLM:' } else { 'HKCU:' } if ($Scope -eq 'Machine') { @@ -111,6 +136,20 @@ if (-not $targets) { throw 'Found no Chrome, Edge or Brave installation. Name one with -Browser to configure it regardless of what this can see.' } +if (-not $Remove -and ($targets -contains 'Edge') -and -not $Force -and -not (Test-DeviceManaged)) { + Write-Warning @' +Edge is skipped: this device is not managed (not domain-joined, Intune-enrolled +or Entra-joined), and unmanaged Edge only installs extensions from the Microsoft +Store. It would read the policy and blank the value. + + Use Chrome or Brave for the update-server install, or load extension\ unpacked + in Edge - an unpacked copy still reloads itself when the dashboard reports a + newer version. -Force writes the key anyway. +'@ + $targets = @($targets | Where-Object { $_ -ne 'Edge' }) + if (-not $targets) { exit 1 } +} + Write-Host "Configuring: $($targets -join ', ')"