Commit 95fb6dc8 authored by Vadim Shtayura's avatar Vadim Shtayura Committed by Commit Bot

[cipd] Check CIPD client hash during updates on Windows.

This is Windows counterpart to https://chromium-review.googlesource.com/1171957

Also cleanup code style in cipd.ps1 script. It appears the common convention
for global variables in PowerShell is $GlobalVar and for locals is $localVar.

R=nodir@chromium.org, iannucci@chromium.org
BUG=870166

Change-Id: Ib8ffbad85497db31f7f5d44fdca6ed843e56f220
Reviewed-on: https://chromium-review.googlesource.com/1175248
Commit-Queue: Vadim Shtayura <vadimsh@chromium.org>
Reviewed-by: 's avatarNodir Turakulov <nodir@chromium.org>
parent efb38bb3
......@@ -5,15 +5,16 @@
setlocal
set CIPD_CLIENT_SRV=https://chrome-infra-packages.appspot.com
for /f %%i in (%~dp0cipd_client_version) do set CIPD_CLIENT_VER=%%i
set CIPD_BACKEND=https://chrome-infra-packages.appspot.com
set VERSION_FILE="%~dp0cipd_client_version"
set CIPD_BINARY="%~dp0.cipd_client.exe"
if not exist "%~dp0.cipd_client.exe" (
if not exist %CIPD_BINARY% (
call :CLEAN_BOOTSTRAP
goto :EXEC_CIPD
)
call :SELF_UPDATE
call :SELF_UPDATE >nul 2>&1
if %ERRORLEVEL% neq 0 (
echo CIPD client self-update failed, trying to bootstrap it from scratch... 1>&2
call :CLEAN_BOOTSTRAP
......@@ -25,7 +26,7 @@ if %ERRORLEVEL% neq 0 (
echo Failed to bootstrap or update CIPD client 1>&2
)
if %ERRORLEVEL% equ 0 (
"%~dp0.cipd_client.exe" %*
"%CIPD_BINARY%" %*
)
endlocal & (
......@@ -46,7 +47,12 @@ exit /b %EXPORT_ERRORLEVEL%
:: alternate data stream. This is equivalent to clicking the "Unblock" button
:: in the file's properties dialog.
echo.>%~dp0cipd.ps1:Zone.Identifier
powershell -NoProfile -ExecutionPolicy RemoteSigned -Command "%~dp0cipd.ps1" < nul
powershell -NoProfile -ExecutionPolicy RemoteSigned ^
-Command "%~dp0cipd.ps1" ^
-CipdBinary "%CIPD_BINARY%" ^
-BackendURL "%CIPD_BACKEND%" ^
-VersionFile "%VERSION_FILE%" ^
<nul
if %ERRORLEVEL% equ 0 (
:: Need to call SELF_UPDATE to setup .cipd_version file.
call :SELF_UPDATE
......@@ -55,5 +61,7 @@ exit /B %ERRORLEVEL%
:SELF_UPDATE
"%~dp0.cipd_client.exe" selfupdate -version "%CIPD_CLIENT_VER%" -service-url "%CIPD_CLIENT_SRV%"
"%CIPD_BINARY%" selfupdate ^
-version-file "%VERSION_FILE%" ^
-service-url "%CIPD_BACKEND%"
exit /B %ERRORLEVEL%
......@@ -2,72 +2,117 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
$myPath = Split-Path $MyInvocation.MyCommand.Path -Parent
Param(
# Path to download the CIPD binary to.
[parameter(Mandatory=$true)][string]$CipdBinary,
# E.g. "https://chrome-infra-packages.appspot.com".
[parameter(Mandatory=$true)][string]$BackendURL,
# Path to the cipd_client_version file with the client version.
[parameter(Mandatory=$true)][string]$VersionFile
)
function GetEnvVar([string] $key, [scriptblock] $defaultFn) {
if (Test-Path "Env:\$key") {
return (Get-ChildItem "Env:\$key").Value
}
return $defaultFn.Invoke()
}
$cipdClientVer = GetEnvVar "CIPD_CLIENT_VER" {
Get-Content (Join-Path $myPath -ChildPath 'cipd_client_version') -TotalCount 1
}
$cipdClientSrv = GetEnvVar "CIPD_CLIENT_SRV" {
"https://chrome-infra-packages.appspot.com"
}
$DepotToolsPath = Split-Path $MyInvocation.MyCommand.Path -Parent
$plat="windows"
if ([environment]::Is64BitOperatingSystem) {
$arch="amd64"
if ([System.IntPtr]::Size -eq 8) {
$Platform = "windows-amd64"
} else {
$arch="386"
$Platform = "windows-386"
}
$url = "$cipdClientSrv/client?platform=$plat-$arch&version=$cipdClientVer"
$client = Join-Path $myPath -ChildPath ".cipd_client.exe"
# Put depot_tool's git revision into the user agent string.
try {
$depot_tools_version = &git -C $myPath rev-parse HEAD 2>&1
$DepotToolsVersion = &git -C $DepotToolsPath rev-parse HEAD 2>&1
if ($LastExitCode -eq 0) {
$user_agent = "depot_tools/$depot_tools_version"
$UserAgent = "depot_tools/$DepotToolsVersion"
} else {
$user_agent = "depot_tools/???"
$UserAgent = "depot_tools/???"
}
} catch [System.Management.Automation.CommandNotFoundException] {
$user_agent = "depot_tools/no_git/???"
$UserAgent = "depot_tools/no_git/???"
}
$Env:CIPD_HTTP_USER_AGENT_PREFIX = $UserAgent
# Tries to delete the file, ignoring errors. Used for best-effort cleanups.
function Delete-If-Possible($path) {
try {
[System.IO.File]::Delete($path)
} catch {
$err = $_.Exception.Message
echo "Warning: error when deleting $path - $err. Ignoring."
}
}
# Returns the expected SHA256 hex digest for the given platform reading it from
# *.digests file.
function Get-Expected-SHA256($platform) {
$digestsFile = $VersionFile+".digests"
foreach ($line in Get-Content $digestsFile) {
if ($line -match "^([0-9a-z\-]+)\s+sha256\s+([0-9a-f]+)$") {
if ($Matches[1] -eq $platform) {
return $Matches[2]
}
}
}
throw "No SHA256 digests for $platform in $digestsFile"
}
# Returns SHA256 hex digest of a binary file at the given path.
function Get-Actual-SHA256($path) {
# Note: we don't use Get-FileHash to be compatible with PowerShell v3.0
$file = [System.IO.File]::Open($path, [System.IO.FileMode]::Open)
try {
$algo = New-Object System.Security.Cryptography.SHA256Managed
$hash = $algo.ComputeHash($file)
} finally {
$file.Close()
}
$hex = ""
foreach ($byte in $hash) {
$hex += $byte.ToString("x2")
}
return $hex
}
$Env:CIPD_HTTP_USER_AGENT_PREFIX = $user_agent
# Use a lock fle to prevent simultaneous processes from stepping on each other.
$cipd_lock = Join-Path $myPath -ChildPath '.cipd_client.lock'
$ExpectedSHA256 = Get-Expected-SHA256 $Platform
$Version = (Get-Content $VersionFile).Trim()
$URL = "$BackendURL/client?platform=$Platform&version=$Version"
# Use a lock file to prevent simultaneous processes from stepping on each other.
$CipdLockPath = Join-Path $DepotToolsPath -ChildPath ".cipd_client.lock"
$TmpPath = $CipdBinary + ".tmp"
while ($true) {
$cipd_lock_file = $false
$CipdLockFile = $null
try {
$cipd_lock_file = [System.IO.File]::OpenWrite($cipd_lock)
$CipdLockFile = [System.IO.File]::OpenWrite($CipdLockPath)
echo "Downloading CIPD client for $Platform from $URL..."
$wc = (New-Object System.Net.WebClient)
$wc.Headers.Add("User-Agent", $UserAgent)
$wc.DownloadFile($URL, $TmpPath)
echo "Bootstrapping cipd client for $plat-$arch from $url..."
$wc = (New-Object System.Net.WebClient)
$wc.Headers.add('User-Agent', $user_agent)
$wc.DownloadFile($url, $client)
break
$ActualSHA256 = Get-Actual-SHA256 $TmpPath
if ($ActualSHA256 -ne $ExpectedSHA256) {
throw "Invalid SHA256 digest: $ActualSHA256 != $ExpectedSHA256"
}
Move-Item -LiteralPath $TmpPath -Destination $CipdBinary -Force
break
} catch [System.IO.IOException] {
echo "CIPD bootstrap lock is held, trying again after delay..."
Start-Sleep -s 1
echo "CIPD bootstrap lock is held, trying again after delay..."
Start-Sleep -s 1
} catch {
$err = $_.Exception.Message
echo "CIPD bootstrap failed: $err"
throw $err
throw # for some reason this is needed to exit while(...) loop on errors
} finally {
if ($cipd_lock_file) {
$cipd_lock_file.Close()
$cipd_lock_file = $false
try {
[System.IO.File]::Delete($cipd_lock)
} catch {}
}
Delete-If-Possible $TmpPath
if ($CipdLockFile) {
$CipdLockFile.Close()
Delete-If-Possible $CipdLockPath
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment