From a103d7b6f1faab2abf9f050cb37551aa5540b72a Mon Sep 17 00:00:00 2001 From: Brandon Li Date: Mon, 31 Aug 2026 15:44:16 -0500 Subject: [PATCH] Script the Chrome Enterprise Core enrolment Enrolling is what lifts the off-store restriction without joining a domain, and it is one machine-scoped token in both places Chrome looks: HKLM on Windows, a file under /etc/opt/chrome/policies/enrollment on Linux. Both scripts take --remove, and both say plainly that removing the token locally does not release the seat in the Admin console. Co-Authored-By: Claude Opus 5 --- deploy/README.md | 19 ++++++- scripts/enroll-chrome-management.ps1 | 84 ++++++++++++++++++++++++++++ scripts/enroll-chrome-management.sh | 47 ++++++++++++++++ 3 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 scripts/enroll-chrome-management.ps1 create mode 100755 scripts/enroll-chrome-management.sh diff --git a/deploy/README.md b/deploy/README.md index 8da7f3b..4681883 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -124,8 +124,23 @@ is one of: disk when the dashboard reports a newer version, and the updater has already pulled those files. Works today, any browser, nothing to enrol. - **Enrol Chrome in Chrome Enterprise Core** (free, and it does not require a - domain-joined machine): one `CloudManagementEnrollmentToken` registry value - makes the browser managed, and everything here then works as designed. + domain-joined machine): one `CloudManagementEnrollmentToken` makes the browser + managed, and everything here then works as designed. Generate a token in the + Admin console under Devices > Chrome > Managed browsers, then: + + ```powershell + powershell -NoProfile -ExecutionPolicy Bypass -File scripts\enroll-chrome-management.ps1 -Token + ``` + + ```bash + sudo scripts/enroll-chrome-management.sh + ``` + + Both need admin/root — the token is machine-scoped — and both are Chrome only; + Chromium has no cloud-management support and Edge is not covered by any of + this. Once enrolled you can either keep using `install-extension-policy`, or + force-install the extension from the Admin console instead, which reaches + every enrolled machine at once. - **Publish to a web store.** Store-hosted extensions update themselves with no policy at all — at the price of a listing and a review on every release. diff --git a/scripts/enroll-chrome-management.ps1 b/scripts/enroll-chrome-management.ps1 new file mode 100644 index 0000000..ad8f9ca --- /dev/null +++ b/scripts/enroll-chrome-management.ps1 @@ -0,0 +1,84 @@ +<# +.SYNOPSIS + Enrol this machine's Chrome in Chrome Enterprise Core. + +.DESCRIPTION + Chrome refuses to force-install an extension from outside its own web store + unless the machine counts as enterprise managed. Enrolment is the way to + qualify without joining a domain: one machine-level token, and from the next + launch Chrome takes policy from the Google Admin console and the off-store + restriction lifts. install-extension-policy.ps1 then works as intended. + + The token comes from the Admin console: Devices > Chrome > Managed browsers > + the enrollment-token button. One token can enrol any number of machines, and + it is only used at enrolment. + + Needs an elevated PowerShell — the token is machine-scoped, and Chrome does + not read it from the user hive. + +.EXAMPLE + powershell -NoProfile -ExecutionPolicy Bypass -File scripts\enroll-chrome-management.ps1 -Token abcd1234-... +#> +[CmdletBinding()] +param( + [Parameter(Mandatory = $true, ParameterSetName = 'Enrol')] + [string]$Token, + + # Refuse to start Chrome at all if enrolment fails. Sound on a fleet, risky + # on a trading PC: a revoked token would leave you with no browser. + [Parameter(ParameterSetName = 'Enrol')] + [switch]$Mandatory, + + [Parameter(Mandatory = $true, ParameterSetName = 'Remove')] + [switch]$Remove +) + +$ErrorActionPreference = 'Stop' + +$identity = [Security.Principal.WindowsIdentity]::GetCurrent() +if (-not ([Security.Principal.WindowsPrincipal]$identity).IsInRole( + [Security.Principal.WindowsBuiltInRole]::Administrator)) { + throw 'Run this from an elevated PowerShell — the enrolment token is machine-level.' +} + +$key = 'HKLM:\SOFTWARE\Policies\Google\Chrome' +if (-not (Test-Path $key)) { New-Item -Path $key -Force | Out-Null } + +if ($Remove) { + foreach ($name in 'CloudManagementEnrollmentToken', 'CloudManagementEnrollmentMandatory') { + if ($null -ne (Get-ItemProperty -Path $key -Name $name -ErrorAction SilentlyContinue)) { + Remove-ItemProperty -Path $key -Name $name + Write-Host "Removed $name" + } + } + Write-Host @" + +Restart Chrome. Note this stops Chrome asking for policy, but does not undo the +enrolment on Google's side — delete the browser from Devices > Chrome > Managed +browsers as well, or it keeps a seat and shows as stale. +"@ + exit 0 +} + +New-ItemProperty -Path $key -Name 'CloudManagementEnrollmentToken' ` + -Value $Token -PropertyType String -Force | Out-Null +Write-Host "Wrote CloudManagementEnrollmentToken to $key" + +if ($Mandatory) { + New-ItemProperty -Path $key -Name 'CloudManagementEnrollmentMandatory' ` + -Value 1 -PropertyType DWord -Force | Out-Null + Write-Host 'Enrolment is now mandatory — Chrome will not start unenrolled.' +} + +Write-Host @" + +Next: + 1. Restart Chrome completely (check Task Manager for stray chrome.exe). + 2. chrome://policy should name the Admin console as a policy source, and + chrome://management should say the browser is managed. + 3. The machine appears under Devices > Chrome > Managed browsers. + 4. Then install the extension, which is no longer blocked: + powershell -NoProfile -ExecutionPolicy Bypass -File scripts\install-extension-policy.ps1 -Browser Chrome + Or skip that and force-install it from the Admin console instead, which + covers every enrolled machine at once. +"@ diff --git a/scripts/enroll-chrome-management.sh b/scripts/enroll-chrome-management.sh new file mode 100755 index 0000000..53ef7f4 --- /dev/null +++ b/scripts/enroll-chrome-management.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +# Enrol this machine's Chrome in Chrome Enterprise Core. +# +# The Linux counterpart to enroll-chrome-management.ps1. Chrome reads the token +# from a file under /etc at startup, so this needs root, and it applies to every +# user on the machine. +# +# sudo scripts/enroll-chrome-management.sh +# sudo scripts/enroll-chrome-management.sh --remove +# +# Chrome only — Chromium builds have no cloud-management support, so a Chromium +# install cannot be enrolled and stays subject to the off-store restriction. +set -euo pipefail + +DIR=/etc/opt/chrome/policies/enrollment +TOKEN_FILE="$DIR/CloudManagementEnrollmentToken" + +info() { printf ' %s\n' "$1"; } +fail() { printf '\n\033[1;31mERROR: %s\033[0m\n' "$1" >&2; exit 1; } + +[ "$(id -u)" -eq 0 ] || fail "run this with sudo — the token lives under /etc" +[ $# -ge 1 ] || fail "usage: $0 | --remove" + +if [ "$1" = "--remove" ]; then + rm -f "$TOKEN_FILE" "$DIR/CloudManagementEnrollmentOptions" + info "removed $TOKEN_FILE" + info "Restart Chrome. This stops it asking for policy, but does not undo the" + info "enrolment on Google's side — delete the browser from Devices > Chrome >" + info "Managed browsers too." + exit 0 +fi + +[ -d /etc/opt/chrome ] || fail "no /etc/opt/chrome — this is for Google Chrome, not Chromium" + +mkdir -p "$DIR" +# The file must contain the token and nothing else: no quotes, no newline noise, +# no filename extension. Chrome reads it verbatim. +printf '%s' "$1" > "$TOKEN_FILE" +chmod 644 "$TOKEN_FILE" +info "wrote $TOKEN_FILE" + +echo +info "Next:" +info " 1. Restart Chrome completely." +info " 2. chrome://policy should name the Admin console as a policy source, and" +info " chrome://management should say the browser is managed." +info " 3. Then: sudo scripts/install-extension-policy.sh"