<# .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( # Defaulted so setup is hands-off. An enrolment token is reusable and enrols # any number of browsers, which is what makes a baked-in default work at all. # It is a modest secret: anyone holding it can enrol *their* browser into the # org, which gets them our policies and a row in the console — it grants no # access to the Google account or to anything else. Rotate it in Devices > # Chrome > Managed browsers and change it here. [Parameter(ParameterSetName = 'Enrol')] [string]$Token = 'ce4fa6cd-e940-45f6-9086-85075d6cff34', # 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, # Fail instead of asking for elevation. Also the loop-breaker: the elevated # copy is launched with this set, so it can never spawn another. [switch]$NoElevate, # Fail rather than installing Chrome when it is missing. [switch]$SkipChromeInstall ) $ErrorActionPreference = 'Stop' $identity = [Security.Principal.WindowsIdentity]::GetCurrent() if (-not ([Security.Principal.WindowsPrincipal]$identity).IsInRole( [Security.Principal.WindowsBuiltInRole]::Administrator)) { if ($NoElevate) { throw 'Run this from an elevated PowerShell — the enrolment token is machine-level.' } # Relaunch elevated rather than making the caller do it. setup-windows.bat # runs unelevated on purpose — nothing else it does needs admin — so this is # the one UAC prompt in the whole install, and it is raised here where the # arguments are already parsed and can be passed on intact. Write-Host 'Asking for administrator rights — the enrolment token is machine-level.' $psArgs = @('-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', "`"$PSCommandPath`"", '-NoElevate') if ($SkipChromeInstall) { $psArgs += '-SkipChromeInstall' } if ($Remove) { $psArgs += '-Remove' } else { $psArgs += @('-Token', $Token) if ($Mandatory) { $psArgs += '-Mandatory' } } $elevated = Start-Process -FilePath (Get-Process -Id $PID).Path -Verb RunAs -Wait -PassThru ` -ArgumentList $psArgs exit $elevated.ExitCode } # ── Chrome itself ──────────────────────────────────────────────────────────── # Enrolling a browser that is not installed would write a token nothing ever # reads. Chromium is deliberately not accepted as a substitute: it has no # cloud-management support, so it can never be enrolled and would stay subject # to the off-store restriction forever. function Find-Chrome { foreach ($exe in @("$env:ProgramFiles\Google\Chrome\Application\chrome.exe", "${env:ProgramFiles(x86)}\Google\Chrome\Application\chrome.exe", "$env:LOCALAPPDATA\Google\Chrome\Application\chrome.exe")) { if ($exe -and (Test-Path $exe)) { return $exe } } return $null } if (-not $Remove -and -not (Find-Chrome)) { if ($SkipChromeInstall) { throw 'Google Chrome is not installed, and -SkipChromeInstall was given.' } # Google's own enterprise MSI, which installs machine-wide and silently. We # are already elevated by this point, so this needs no second prompt. $msi = Join-Path $env:TEMP 'googlechromestandaloneenterprise64.msi' Write-Host 'Google Chrome is not installed — downloading it from Google (about 120 MB).' # Progress off for the duration. Windows PowerShell re-renders the progress # bar on every buffer, which on a 120 MB file costs far more time than the # transfer itself — minutes instead of seconds, looking for all the world # like a stalled download. $previousProgress = $ProgressPreference $ProgressPreference = 'SilentlyContinue' try { Invoke-WebRequest -Uri 'https://dl.google.com/dl/chrome/install/googlechromestandaloneenterprise64.msi' ` -OutFile $msi -UseBasicParsing } finally { $ProgressPreference = $previousProgress } Write-Host 'Installing Chrome...' $msiexec = Start-Process msiexec.exe -Wait -PassThru -ArgumentList @('/i', "`"$msi`"", '/qn', '/norestart') Remove-Item $msi -ErrorAction SilentlyContinue if ($msiexec.ExitCode -ne 0) { throw "Chrome install failed (msiexec exit $($msiexec.ExitCode))." } if (-not (Find-Chrome)) { throw 'Chrome still not found after installing.' } Write-Host 'Chrome installed.' } $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. "@