Bake in the enrolment token, and install Chrome when missing
Setup asked for a token that is the same on every machine - a token is reusable and enrols any number of browsers - so it is a default in both scripts now and step 7 is a plain yes/no. It is a modest secret: it lets someone enrol their own browser into the org and nothing more, and rotating it is a console click and a one-line change. Both scripts also install Chrome if it is absent, from Google's enterprise MSI and the official .deb, since enrolling a browser that is not there writes a token nothing reads. Chromium is refused rather than substituted: no cloud management, so it could never be enrolled - and on ARM, where Chrome is not published at all, the Linux script says so instead of installing something that cannot do the job. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
35dd15d584
commit
389c714caf
@@ -135,13 +135,20 @@ the console already set to force install, and Chrome keeps it updated. Run on
|
|||||||
its own at any time:
|
its own at any time:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\enroll-chrome-management.ps1 -Token <token>
|
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\enroll-chrome-management.ps1
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo scripts/enroll-chrome-management.sh <token>
|
sudo scripts/enroll-chrome-management.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The enrolment token is built into both scripts — a token is reusable across any
|
||||||
|
number of machines — so there is nothing to type. Pass one explicitly to use a
|
||||||
|
different org. Chrome itself is installed first if the machine hasn't got it,
|
||||||
|
from Google's own enterprise MSI on Windows and the official .deb on Linux;
|
||||||
|
Chromium is not accepted as a substitute, because it has no cloud-management
|
||||||
|
support and can never be enrolled.
|
||||||
|
|
||||||
**Enrolment is not optional.** No Chromium browser will force-install an
|
**Enrolment is not optional.** No Chromium browser will force-install an
|
||||||
off-store extension on an unmanaged machine, whatever the registry says — it
|
off-store extension on an unmanaged machine, whatever the registry says — it
|
||||||
reads the policy and blanks it. Enrolling is what makes Chrome managed without
|
reads the policy and blanks it. Enrolling is what makes Chrome managed without
|
||||||
|
|||||||
@@ -21,8 +21,14 @@
|
|||||||
#>
|
#>
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory = $true, ParameterSetName = 'Enrol')]
|
# Defaulted so setup is hands-off. An enrolment token is reusable and enrols
|
||||||
[string]$Token,
|
# 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
|
# 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.
|
# on a trading PC: a revoked token would leave you with no browser.
|
||||||
@@ -34,7 +40,10 @@ param(
|
|||||||
|
|
||||||
# Fail instead of asking for elevation. Also the loop-breaker: the elevated
|
# Fail instead of asking for elevation. Also the loop-breaker: the elevated
|
||||||
# copy is launched with this set, so it can never spawn another.
|
# copy is launched with this set, so it can never spawn another.
|
||||||
[switch]$NoElevate
|
[switch]$NoElevate,
|
||||||
|
|
||||||
|
# Fail rather than installing Chrome when it is missing.
|
||||||
|
[switch]$SkipChromeInstall
|
||||||
)
|
)
|
||||||
|
|
||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
@@ -52,6 +61,7 @@ if (-not ([Security.Principal.WindowsPrincipal]$identity).IsInRole(
|
|||||||
# arguments are already parsed and can be passed on intact.
|
# arguments are already parsed and can be passed on intact.
|
||||||
Write-Host 'Asking for administrator rights — the enrolment token is machine-level.'
|
Write-Host 'Asking for administrator rights — the enrolment token is machine-level.'
|
||||||
$psArgs = @('-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', "`"$PSCommandPath`"", '-NoElevate')
|
$psArgs = @('-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', "`"$PSCommandPath`"", '-NoElevate')
|
||||||
|
if ($SkipChromeInstall) { $psArgs += '-SkipChromeInstall' }
|
||||||
if ($Remove) { $psArgs += '-Remove' }
|
if ($Remove) { $psArgs += '-Remove' }
|
||||||
else {
|
else {
|
||||||
$psArgs += @('-Token', $Token)
|
$psArgs += @('-Token', $Token)
|
||||||
@@ -63,6 +73,38 @@ if (-not ([Security.Principal.WindowsPrincipal]$identity).IsInRole(
|
|||||||
exit $elevated.ExitCode
|
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).'
|
||||||
|
Invoke-WebRequest -Uri 'https://dl.google.com/dl/chrome/install/googlechromestandaloneenterprise64.msi' `
|
||||||
|
-OutFile $msi -UseBasicParsing
|
||||||
|
|
||||||
|
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'
|
$key = 'HKLM:\SOFTWARE\Policies\Google\Chrome'
|
||||||
if (-not (Test-Path $key)) { New-Item -Path $key -Force | Out-Null }
|
if (-not (Test-Path $key)) { New-Item -Path $key -Force | Out-Null }
|
||||||
|
|
||||||
|
|||||||
@@ -5,13 +5,21 @@
|
|||||||
# from a file under /etc at startup, so this needs root, and it applies to every
|
# from a file under /etc at startup, so this needs root, and it applies to every
|
||||||
# user on the machine.
|
# user on the machine.
|
||||||
#
|
#
|
||||||
# sudo scripts/enroll-chrome-management.sh <token>
|
# sudo scripts/enroll-chrome-management.sh # the built-in token
|
||||||
|
# sudo scripts/enroll-chrome-management.sh <token> # a different one
|
||||||
# sudo scripts/enroll-chrome-management.sh --remove
|
# sudo scripts/enroll-chrome-management.sh --remove
|
||||||
#
|
#
|
||||||
# Chrome only — Chromium builds have no cloud-management support, so a Chromium
|
# Chrome only — Chromium builds have no cloud-management support, so a Chromium
|
||||||
# install cannot be enrolled and stays subject to the off-store restriction.
|
# install cannot be enrolled and stays subject to the off-store restriction.
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Defaulted so setup is hands-off. A token is reusable and enrols any number of
|
||||||
|
# browsers, which is what makes a baked-in default work. It is a modest secret:
|
||||||
|
# anyone holding it can enrol *their* browser into the org — our policies and a
|
||||||
|
# row in the console — and nothing more. Rotate it in Devices > Chrome > Managed
|
||||||
|
# browsers and change it here.
|
||||||
|
DEFAULT_TOKEN=ce4fa6cd-e940-45f6-9086-85075d6cff34
|
||||||
|
|
||||||
DIR=/etc/opt/chrome/policies/enrollment
|
DIR=/etc/opt/chrome/policies/enrollment
|
||||||
TOKEN_FILE="$DIR/CloudManagementEnrollmentToken"
|
TOKEN_FILE="$DIR/CloudManagementEnrollmentToken"
|
||||||
|
|
||||||
@@ -19,7 +27,6 @@ info() { printf ' %s\n' "$1"; }
|
|||||||
fail() { printf '\n\033[1;31mERROR: %s\033[0m\n' "$1" >&2; exit 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"
|
[ "$(id -u)" -eq 0 ] || fail "run this with sudo — the token lives under /etc"
|
||||||
[ $# -ge 1 ] || fail "usage: $0 <enrollment-token> | --remove"
|
|
||||||
|
|
||||||
if [ "$1" = "--remove" ]; then
|
if [ "$1" = "--remove" ]; then
|
||||||
rm -f "$TOKEN_FILE" "$DIR/CloudManagementEnrollmentOptions"
|
rm -f "$TOKEN_FILE" "$DIR/CloudManagementEnrollmentOptions"
|
||||||
@@ -30,12 +37,33 @@ if [ "$1" = "--remove" ]; then
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
[ -d /etc/opt/chrome ] || fail "no /etc/opt/chrome — this is for Google Chrome, not Chromium"
|
TOKEN="${1:-$DEFAULT_TOKEN}"
|
||||||
|
|
||||||
|
# Enrolling a browser that is not installed would write a token nothing reads.
|
||||||
|
# Chromium is not a substitute: it has no cloud-management support, so it can
|
||||||
|
# never be enrolled, and Google publishes Chrome for x86_64 only — on a Pi there
|
||||||
|
# is no version of this that works, and saying so beats installing something
|
||||||
|
# that cannot do the job.
|
||||||
|
if ! command -v google-chrome >/dev/null 2>&1 && [ ! -x /opt/google/chrome/chrome ]; then
|
||||||
|
ARCH=$(uname -m)
|
||||||
|
[ "$ARCH" = "x86_64" ] || fail "Google Chrome is not published for $ARCH. Chromium cannot be enrolled — this machine cannot run the extension."
|
||||||
|
command -v apt-get >/dev/null || fail "Chrome is missing and this is not an apt system — install Google Chrome, then re-run"
|
||||||
|
|
||||||
|
info "Google Chrome is not installed — fetching it from Google (about 120 MB)"
|
||||||
|
DEB=$(mktemp --suffix=.deb)
|
||||||
|
curl -fsSL -o "$DEB" https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb \
|
||||||
|
|| fail "could not download Chrome"
|
||||||
|
# apt rather than dpkg: it pulls the dependencies a bare dpkg -i would leave
|
||||||
|
# half-configured.
|
||||||
|
DEBIAN_FRONTEND=noninteractive apt-get install -y "$DEB" >/dev/null || fail "Chrome install failed"
|
||||||
|
rm -f "$DEB"
|
||||||
|
info "Chrome installed"
|
||||||
|
fi
|
||||||
|
|
||||||
mkdir -p "$DIR"
|
mkdir -p "$DIR"
|
||||||
# The file must contain the token and nothing else: no quotes, no newline noise,
|
# The file must contain the token and nothing else: no quotes, no newline noise,
|
||||||
# no filename extension. Chrome reads it verbatim.
|
# no filename extension. Chrome reads it verbatim.
|
||||||
printf '%s' "$1" > "$TOKEN_FILE"
|
printf '%s' "$TOKEN" > "$TOKEN_FILE"
|
||||||
chmod 644 "$TOKEN_FILE"
|
chmod 644 "$TOKEN_FILE"
|
||||||
info "wrote $TOKEN_FILE"
|
info "wrote $TOKEN_FILE"
|
||||||
|
|
||||||
|
|||||||
+7
-8
@@ -150,16 +150,15 @@ echo
|
|||||||
info "[7/7] Chrome extension"
|
info "[7/7] Chrome extension"
|
||||||
info " Enrols this machine's Chrome, after which the extension installs"
|
info " Enrols this machine's Chrome, after which the extension installs"
|
||||||
info " itself from the Admin console and stays updated on its own."
|
info " itself from the Admin console and stays updated on its own."
|
||||||
info " The token is in the Admin console under Devices > Chrome >"
|
info " Installs Chrome first if it is not here yet. Needs sudo."
|
||||||
info " Managed browsers. Blank to skip."
|
read -r -p " Set this up now? [Y/n] " DOEXT
|
||||||
read -r -p " Enrollment token: " ENROLTOKEN
|
|
||||||
EXTPOLICY=0
|
EXTPOLICY=0
|
||||||
if [ -n "${ENROLTOKEN:-}" ]; then
|
if [ "${DOEXT,,}" != "n" ]; then
|
||||||
if sudo bash scripts/enroll-chrome-management.sh "$ENROLTOKEN"; then EXTPOLICY=1; else
|
if sudo bash scripts/enroll-chrome-management.sh; then EXTPOLICY=1; else
|
||||||
warn "enrolment failed - re-run: sudo scripts/enroll-chrome-management.sh <token>"
|
warn "enrolment failed - re-run: sudo scripts/enroll-chrome-management.sh"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
info " Skipped. Run: sudo scripts/enroll-chrome-management.sh <token>"
|
info " Skipped. Run: sudo scripts/enroll-chrome-management.sh"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── summary ─────────────────────────────────────────────────────────────────
|
# ── summary ─────────────────────────────────────────────────────────────────
|
||||||
@@ -186,7 +185,7 @@ if [ "$EXTPOLICY" -eq 1 ]; then
|
|||||||
info " and the extension installs itself within a minute or two."
|
info " and the extension installs itself within a minute or two."
|
||||||
else
|
else
|
||||||
info " - Enrol Chrome so it can install the extension:"
|
info " - Enrol Chrome so it can install the extension:"
|
||||||
info " sudo scripts/enroll-chrome-management.sh <token>"
|
info " sudo scripts/enroll-chrome-management.sh"
|
||||||
fi
|
fi
|
||||||
info " - Add your firm credentials on the dashboard's Settings page"
|
info " - Add your firm credentials on the dashboard's Settings page"
|
||||||
if [ -n "${WAYLAND_DISPLAY:-}" ] && [ -z "${DISPLAY:-}" ]; then
|
if [ -n "${WAYLAND_DISPLAY:-}" ] && [ -z "${DISPLAY:-}" ]; then
|
||||||
|
|||||||
+11
-11
@@ -335,14 +335,14 @@ echo.
|
|||||||
echo [7/7] Chrome extension
|
echo [7/7] Chrome extension
|
||||||
echo Enrols this machine's Chrome, after which the extension installs
|
echo Enrols this machine's Chrome, after which the extension installs
|
||||||
echo itself from the Admin console and stays updated on its own.
|
echo itself from the Admin console and stays updated on its own.
|
||||||
echo The token is in the Admin console under
|
echo Installs Chrome first if it is not here yet.
|
||||||
echo Devices ^> Chrome ^> Managed browsers. Blank to skip.
|
set "DOEXT="
|
||||||
set "ENROLTOKEN="
|
set /p "DOEXT= Set this up now? [Y/n] "
|
||||||
set /p "ENROLTOKEN= Enrollment token: "
|
if /i "%DOEXT%"=="n" goto :ext_skipped
|
||||||
if not defined ENROLTOKEN goto :ext_skipped
|
REM The enrolment token is built into the script, so there is nothing to type.
|
||||||
REM The token is machine-scoped, so this raises a UAC prompt and only this. The
|
REM It is machine-scoped, so this raises a UAC prompt - the only one in this
|
||||||
REM script asks for elevation itself; nothing else in this installer needs it.
|
REM installer, and the script asks for it itself.
|
||||||
powershell -NoProfile -ExecutionPolicy Bypass -File "%TARGET%\scripts\enroll-chrome-management.ps1" -Token "%ENROLTOKEN%"
|
powershell -NoProfile -ExecutionPolicy Bypass -File "%TARGET%\scripts\enroll-chrome-management.ps1"
|
||||||
if errorlevel 1 (
|
if errorlevel 1 (
|
||||||
echo [!] Enrolment failed. Re-run scripts\enroll-chrome-management.ps1 with
|
echo [!] Enrolment failed. Re-run scripts\enroll-chrome-management.ps1 with
|
||||||
echo a fresh token from the Admin console to try again.
|
echo a fresh token from the Admin console to try again.
|
||||||
@@ -353,8 +353,8 @@ if errorlevel 1 (
|
|||||||
goto :ext_done
|
goto :ext_done
|
||||||
|
|
||||||
:ext_skipped
|
:ext_skipped
|
||||||
echo Skipped. Run scripts\enroll-chrome-management.ps1 -Token ^<token^>
|
echo Skipped. Run scripts\enroll-chrome-management.ps1 later;
|
||||||
echo later; until then this machine gets no extension.
|
echo until then this machine gets no extension.
|
||||||
set "EXTPOLICY=0"
|
set "EXTPOLICY=0"
|
||||||
|
|
||||||
:ext_done
|
:ext_done
|
||||||
@@ -400,7 +400,7 @@ if "%EXTPOLICY%"=="1" (
|
|||||||
echo and the extension installs itself within a minute or two.
|
echo and the extension installs itself within a minute or two.
|
||||||
) else (
|
) else (
|
||||||
echo - Enrol Chrome so it can install the extension:
|
echo - Enrol Chrome so it can install the extension:
|
||||||
echo scripts\enroll-chrome-management.ps1 -Token ^<token^>
|
echo scripts\enroll-chrome-management.ps1
|
||||||
)
|
)
|
||||||
echo - Add your firm credentials on the dashboard's Settings page
|
echo - Add your firm credentials on the dashboard's Settings page
|
||||||
echo.
|
echo.
|
||||||
|
|||||||
Reference in New Issue
Block a user