[Windows] Refactor helpers that verify hashsum and signature (#8886)

This commit is contained in:
Vasilii Polikarpov
2023-11-30 09:22:14 +01:00
committed by GitHub
parent abb81511d4
commit 92e22bd8c6
17 changed files with 151 additions and 109 deletions

View File

@@ -12,10 +12,9 @@ $downloadUrl = ($assets.browser_download_url -ilike "*aliyun-cli-windows-*-amd64
$packagePath = Invoke-DownloadWithRetry $downloadUrl
#region Supply chain security - Alibaba Cloud CLI
$fileHash = (Get-FileHash -Path $packagePath -Algorithm SHA256).Hash
$hashUrl = ($assets.browser_download_url -ilike "*SHASUMS256.txt*") | Select-Object -First 1
$externalHash = (Invoke-RestMethod -Uri $hashURL).ToString().Split("`n").Where({ $_ -ilike "*$installerFileName*" }).Split(' ')[0]
Use-ChecksumComparison $fileHash $externalHash
Test-FileChecksum $packagePath -ExpectedSHA256Sum $externalHash
#endregion
Write-Host "Expand aliyun-cli archive"

View File

@@ -63,11 +63,7 @@ $androidToolset = (Get-ToolsetContent).android
$cmdlineToolsUrl = $androidToolset.commandline_tools_url
$cmdlineToolsArchPath = Invoke-DownloadWithRetry $cmdlineToolsUrl
#region Supply chain security
$localFileHash = (Get-FileHash -Path $cmdlineToolsArchPath -Algorithm SHA256).Hash
Use-ChecksumComparison -LocalFileHash $localFileHash -DistributorFileHash $androidToolset.hash
#endregion
Test-FileChecksum $cmdlineToolsArchPath -ExpectedSHA256Sum $androidToolset.hash
Expand-7ZipArchive -Path $cmdlineToolsArchPath -DestinationPath "${SDKInstallRoot}\cmdline-tools"

View File

@@ -25,7 +25,7 @@ if ($userPath) {
# Verify and run choco installer
$signatureThumbprint = "83AC7D88C66CB8680BCE802E0F0F5C179722764B"
$InstallScriptPath = Invoke-DownloadWithRetry 'https://chocolatey.org/install.ps1'
Test-FileSignature -FilePath $InstallScriptPath -ExpectedThumbprint $signatureThumbprint
Test-FileSignature -Path $InstallScriptPath -ExpectedThumbprint $signatureThumbprint
Invoke-Expression $InstallScriptPath
# Turn off confirmation

View File

@@ -21,6 +21,6 @@ Add-MachinePathItem $CloudFoundryCliPath
# Validate cf signature
$CloudFoundrySignatureThumbprint = "4C69EDD13930ED01B83DD1D17B09C434DC1F2177"
Test-FileSignature -FilePath "$CloudFoundryCliPath\cf.exe" -ExpectedThumbprint $CloudFoundrySignatureThumbprint
Test-FileSignature -Path "$CloudFoundryCliPath\cf.exe" -ExpectedThumbprint $CloudFoundrySignatureThumbprint
Invoke-PesterTests -TestFile "CLI.Tools" -TestName "CloudFoundry CLI"

View File

@@ -22,7 +22,7 @@ function Get-SDKVersionsToInstall (
$currentReleases = $currentReleases.'releases' | Where-Object { !$_.'release-version'.Contains('-') }
$sdks = @()
ForEach ($release in $currentReleases) {
foreach ($release in $currentReleases) {
$sdks += $release.'sdk'
$sdks += $release.'sdks'
}
@@ -30,7 +30,7 @@ function Get-SDKVersionsToInstall (
return $sdks.version `
| Sort-Object { [Version] $_ } -Unique `
| Group-Object { $_.Substring(0, $_.LastIndexOf('.') + 2) } `
| Foreach-Object { $_.Group[-1] }
| ForEach-Object { $_.Group[-1] }
}
function Invoke-Warmup (
@@ -62,9 +62,7 @@ function InstallSDKVersion (
#region Supply chain security
$distributorFileHash = (Invoke-RestMethod -Uri "https://dotnetcli.blob.core.windows.net/dotnet/release-metadata/$dotnetVersion/releases.json").releases.sdks.Where({ $_.version -eq $SdkVersion }).files.Where({ $_.name -eq 'dotnet-sdk-win-x64.zip' }).hash
$localFileHash = (Get-FileHash -Path $ZipPath -Algorithm 'SHA512').Hash
Use-ChecksumComparison -LocalFileHash $localFileHash -DistributorFileHash $distributorFileHash
Test-FileChecksum $ZipPath -ExpectedSHA512Sum $distributorFileHash
#endregion
} else {
Write-Host "Sdk version $sdkVersion already installed"
@@ -87,29 +85,23 @@ function InstallAllValidSdks() {
$installationUrl = "https://dot.net/v1/${installationName}"
Invoke-DownloadWithRetry -Url $installationUrl -Path ".\$installationName"
ForEach ($dotnetVersion in $dotnetVersions)
{
foreach ($dotnetVersion in $dotnetVersions) {
$sdkVersionsToInstall = Get-SDKVersionsToInstall -DotnetVersion $dotnetVersion
ForEach ($sdkVersion in $sdkVersionsToInstall)
{
foreach ($sdkVersion in $sdkVersionsToInstall) {
InstallSDKVersion -SdkVersion $sdkVersion -DotnetVersion $dotnetVersion -Warmup $warmup
}
}
}
function InstallTools()
{
function InstallTools() {
$dotnetTools = (Get-ToolsetContent).dotnet.tools
ForEach ($dotnetTool in $dotnetTools)
{
foreach ($dotnetTool in $dotnetTools) {
dotnet tool install $($dotnetTool.name) --tool-path "C:\Users\Default\.dotnet\tools" --add-source https://api.nuget.org/v3/index.json | Out-Null
}
}
function RunPostInstallationSteps()
{
function RunPostInstallationSteps() {
# Add dotnet to PATH
Add-MachinePathItem "C:\Program Files\dotnet"

View File

@@ -28,7 +28,7 @@ Expand-7ZipArchive -Path $archivePath -DestinationPath $edgeDriverPath
#Validate the EdgeDriver signature
$signatureThumbprint = "CB9C4FBEA1D87D2D468AC5A9CAAB0163F6AD8401"
Test-FileSignature -FilePath "$edgeDriverPath\msedgedriver.exe" -ExpectedThumbprint $signatureThumbprint
Test-FileSignature -Path "$edgeDriverPath\msedgedriver.exe" -ExpectedThumbprint $signatureThumbprint
Write-Host "Setting the environment variables..."
[Environment]::SetEnvironmentVariable("EdgeWebDriver", $EdgeDriverPath, "Machine")

View File

@@ -50,7 +50,7 @@ Expand-7ZipArchive -Path $GeckoDriverArchPath -DestinationPath $GeckoDriverPath
# Validate Gecko WebDriver signature
$GeckoDriverSignatureThumbprint = "1326B39C3D5D2CA012F66FB439026F7B59CB1974"
Test-FileSignature -FilePath "$GeckoDriverPath/geckodriver.exe" -ExpectedThumbprint $GeckoDriverSignatureThumbprint
Test-FileSignature -Path "$GeckoDriverPath/geckodriver.exe" -ExpectedThumbprint $GeckoDriverSignatureThumbprint
Write-Host "Setting the environment variables..."
Add-MachinePathItem -PathItem $GeckoDriverPath

View File

@@ -64,12 +64,7 @@ function Install-JavaJDK {
# Download and extract java binaries to temporary folder
$downloadUrl = $asset.binary.package.link
$archivePath = Invoke-DownloadWithRetry $downloadUrl
#region Supply chain security - JDK
$fileHash = (Get-FileHash -Path $archivePath -Algorithm SHA256).Hash
$externalHash = $asset.binary.package.checksum
Use-ChecksumComparison $fileHash $externalHash
#endregion
Test-FileChecksum $archivePath -ExpectedSHA256Sum $asset.binary.package.checksum
# We have to replace '+' sign in the version to '-' due to the issue with incorrect path in Android builds https://github.com/actions/runner-images/issues/3014
$fullJavaVersion = $asset.version.semver -replace '\+', '-'
@@ -138,8 +133,7 @@ $sha256sum = '79479DDE416B082F38ECD1F2F7C6DEBD4D0C2249AF80FD046D1CE05D628F2EC6'
$coberturaPath = "C:\cobertura-2.1.1"
$archivePath = Invoke-DownloadWithRetry $uri
$fileHash = (Get-FileHash -Path $archivePath -Algorithm SHA256).Hash
Use-ChecksumComparison $fileHash $sha256sum
Test-FileChecksum $archivePath -ExpectedSHA256Sum $sha256sum
Expand-7ZipArchive -Path $archivePath -DestinationPath "C:\"
[Environment]::SetEnvironmentVariable("COBERTURA_HOME", $coberturaPath, "Machine")

View File

@@ -14,9 +14,8 @@ $kotlinDownloadUrl = Resolve-GithubReleaseAssetUrl `
$kotlinArchivePath = Invoke-DownloadWithRetry $kotlinDownloadUrl
#region Supply chain security
$fileHash = (Get-FileHash -Path $kotlinArchivePath -Algorithm SHA256).Hash
$externalHash = Get-HashFromGitHubReleaseBody -RepoOwner "JetBrains" -RepoName "kotlin" -FileName "$kotlinBinaryName-*.zip" -Version $kotlinVersion -WordNumber 2
Use-ChecksumComparison $fileHash $externalHash
Test-FileChecksum $kotlinArchivePath -ExpectedSHA256Sum $externalHash
#endregion
Write-Host "Expand Kotlin archive"

View File

@@ -14,10 +14,9 @@ $null = New-Item -Path $destFilePath -ItemType Directory -Force
$packagePath = Invoke-DownloadWithRetry -Url $kindDownloadLink -Path "$destFilePath\kind.exe"
#region Supply chain security - Kind
$fileHash = (Get-FileHash -Path $packagePath -Algorithm SHA256).Hash
$hashUrl = ($assets.browser_download_url -match "kind-windows-amd64.sha256sum") | Select-Object -First 1
$externalHash = (Invoke-RestMethod -Uri $hashURL).ToString().Split("`n").Where({ $_ -ilike "*kind-windows-amd64*" }).Split(' ')[0]
Use-ChecksumComparison $fileHash $externalHash
Test-FileChecksum $packagePath -ExpectedSHA256Sum $externalHash
#endregion
Add-MachinePathItem $destFilePath

View File

@@ -21,10 +21,9 @@ function Install-Msys2 {
Write-Host "Finished download"
#region Supply chain security - Kind
$fileHash = (Get-FileHash -Path $msys2File -Algorithm SHA256).Hash
$hashUrl = ($assets.browser_download_url -match "msys2-checksums.txt") | Select-Object -First 1
$externalHash = (Invoke-RestMethod -Uri $hashURL).ToString().Split("`n").Where({ $_ -ilike "*msys2-x86_64*" }).Split(' ')[0]
Use-ChecksumComparison $fileHash $externalHash
Test-FileChecksum $msys2File -ExpectedSHA256Sum $externalHash
#endregion
# extract tar.xz to C:\

View File

@@ -102,16 +102,13 @@ foreach($toolsetVersion in $toolsetVersions.versions)
$tempPyPyPackagePath = Invoke-DownloadWithRetry $latestMajorPyPyVersion.download_url
#region Supply chain security
$localFileHash = (Get-FileHash -Path $tempPyPyPackagePath -Algorithm SHA256).Hash
$distributorFileHash = $null
ForEach($node in $checksums) {
foreach ($node in $checksums) {
if ($node.InnerText -ilike "*${filename}*") {
$distributorFileHash = $node.InnerText.ToString().Split("`n").Where({ $_ -ilike "*${filename}*" }).Split(' ')[0]
}
}
Use-ChecksumComparison -LocalFileHash $localFileHash -DistributorFileHash $distributorFileHash
Test-FileChecksum $tempPyPyPackagePath -ExpectedSHA256Sum $distributorFileHash
#endregion
Install-PyPy -PackagePath $tempPyPyPackagePath -Architecture $toolsetVersions.arch

View File

@@ -13,10 +13,8 @@ $env:CARGO_HOME = "C:\Users\Default\.cargo"
$rustupPath = Invoke-DownloadWithRetry "https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe"
#region Supply chain security
$localFileHash = (Get-FileHash -Path (Join-Path ${env:TEMP} 'rustup-init.exe') -Algorithm SHA256).Hash
$distributorFileHash = (Invoke-RestMethod -Uri 'https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe.sha256').Trim()
Use-ChecksumComparison -LocalFileHash $localFileHash -DistributorFileHash $distributorFileHash
Test-FileChecksum (Join-Path ${env:TEMP} 'rustup-init.exe') -ExpectedSHA256Sum $distributorFileHash
#endregion
# Install Rust by running rustup-init.exe (disabling the confirmation prompt with -y)

View File

@@ -16,10 +16,9 @@ $DestinationPath = Join-Path $StackToolcachePath "x64"
$StackArchivePath = Invoke-DownloadWithRetry $DownloadUrl
#region Supply chain security - Stack
$fileHash = (Get-FileHash -Path $StackArchivePath -Algorithm SHA256).Hash
$hashUrl = $StackReleasesJson.assets | Where-Object { $_.name.EndsWith("$DownloadFilePattern.sha256") } | Select-Object -ExpandProperty "browser_download_url" -First 1
$externalHash = (Invoke-RestMethod -Uri $hashURL).ToString().Split("`n").Where({ $_ -ilike "*$DownloadFilePattern*" }).Split(' ')[0]
Use-ChecksumComparison $fileHash $externalHash
Test-FileChecksum $StackArchivePath -ExpectedSHA256Sum $externalHash
#endregion
Write-Host "Expand stack archive"

View File

@@ -38,8 +38,8 @@ Export-ModuleMember -Function @(
'Get-VisualStudioInstance'
'Get-VisualStudioComponents'
'Get-WindowsUpdateStates'
'Use-ChecksumComparison'
'Get-HashFromGitHubReleaseBody'
'Test-FileChecksum'
'Test-FileSignature'
'Update-Environment'
)

View File

@@ -75,20 +75,18 @@ function Install-Binary {
if ($PSBoundParameters.ContainsKey('ExpectedSignature')) {
if ($ExpectedSignature) {
Test-FileSignature -FilePath $filePath -ExpectedThumbprint $ExpectedSignature
Test-FileSignature -Path $filePath -ExpectedThumbprint $ExpectedSignature
} else {
throw "ExpectedSignature parameter is specified, but no signature is provided."
}
}
if ($ExpectedSHA256Sum) {
$fileHash = (Get-FileHash -Path $filePath -Algorithm SHA256).Hash
Use-ChecksumComparison $fileHash $ExpectedSHA256Sum
Test-FileChecksum $filePath -ExpectedSHA256Sum $ExpectedSHA256Sum
}
if ($ExpectedSHA512Sum) {
$fileHash = (Get-FileHash -Path $filePath -Algorithm SHA512).Hash
Use-ChecksumComparison $fileHash $ExpectedSHA512Sum
Test-FileChecksum $filePath -ExpectedSHA512Sum $ExpectedSHA512Sum
}
if ($ExtraInstallArgs -and $InstallArgs) {
@@ -789,23 +787,6 @@ function Resolve-GithubReleaseAssetUrl {
return ($matchedUrl -as [string])
}
function Use-ChecksumComparison {
param (
[Parameter(Mandatory = $true)]
[string]$LocalFileHash,
[Parameter(Mandatory = $true)]
[string]$DistributorFileHash
)
Write-Verbose "Performing checksum verification"
if ($LocalFileHash -ne $DistributorFileHash) {
throw "Checksum verification failed. Expected hash: $DistributorFileHash; Actual hash: $LocalFileHash."
} else {
Write-Verbose "Checksum verification passed"
}
}
function Get-HashFromGitHubReleaseBody {
param (
[string] $RepoOwner,
@@ -846,15 +827,104 @@ function Get-HashFromGitHubReleaseBody {
}
return $result
}
function Test-FileSignature {
function Test-FileChecksum {
<#
.SYNOPSIS
Verifies the checksum of a file.
.DESCRIPTION
The Test-FileChecksum function verifies the SHA256 or SHA512 checksum of a file against an expected value.
If the checksum does not match the expected value, the function throws an error.
.PARAMETER Path
The path to the file for which to verify the checksum.
.PARAMETER ExpectedSHA256Sum
The expected SHA256 checksum. If this parameter is provided, the function will calculate the SHA256 checksum of the file and compare it to this value.
.PARAMETER ExpectedSHA512Sum
The expected SHA512 checksum. If this parameter is provided, the function will calculate the SHA512 checksum of the file and compare it to this value.
.EXAMPLE
Test-FileChecksum -Path "C:\temp\file.txt" -ExpectedSHA256Sum "ABC123"
Verifies that the SHA256 checksum of the file at C:\temp\file.txt is ABC123.
.EXAMPLE
Test-FileChecksum -Path "C:\temp\file.txt" -ExpectedSHA512Sum "DEF456"
Verifies that the SHA512 checksum of the file at C:\temp\file.txt is DEF456.
#>
param (
[Parameter(Mandatory = $true)]
[string]$FilePath,
[Parameter(Mandatory = $true, Position = 0)]
[string] $Path,
[Parameter(Mandatory = $false)]
[String] $ExpectedSHA256Sum,
[Parameter(Mandatory = $false)]
[String] $ExpectedSHA512Sum
)
Write-Verbose "Performing checksum verification"
if ($ExpectedSHA256Sum -and $ExpectedSHA512Sum) {
throw "Only one of the ExpectedSHA256Sum and ExpectedSHA512Sum parameters can be provided"
}
if (-not (Test-Path $Path)) {
throw "File not found: $Path"
}
if ($ExpectedSHA256Sum) {
$fileHash = (Get-FileHash -Path $Path -Algorithm SHA256).Hash
$expectedHash = $ExpectedSHA256Sum
}
if ($ExpectedSHA512Sum) {
$fileHash = (Get-FileHash -Path $Path -Algorithm SHA512).Hash
$expectedHash = $ExpectedSHA512Sum
}
if ($fileHash -ne $expectedHash) {
throw "Checksum verification failed: expected $expectedHash, got $fileHash"
} else {
Write-Verbose "Checksum verification passed"
}
}
function Test-FileSignature {
<#
.SYNOPSIS
Tests the file signature of a given file.
.DESCRIPTION
The Test-FileSignature function checks the signature of a file against the expected thumbprints.
It uses the Get-AuthenticodeSignature cmdlet to retrieve the signature information of the file.
If the signature status is not valid or the thumbprint does not match the expected thumbprints, an exception is thrown.
.PARAMETER Path
Specifies the path of the file to test.
.PARAMETER ExpectedThumbprint
Specifies the expected thumbprints to match against the file's signature.
.EXAMPLE
Test-FileSignature -Path "C:\Path\To\File.exe" -ExpectedThumbprint "A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6Q7R8S9T0"
This example tests the signature of the file "C:\Path\To\File.exe" against the expected thumbprint "A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6Q7R8S9T0".
#>
param(
[Parameter(Mandatory = $true, Position = 0)]
[string] $Path,
[Parameter(Mandatory = $true)]
[string[]] $ExpectedThumbprint
)
$signature = Get-AuthenticodeSignature $FilePath
$signature = Get-AuthenticodeSignature $Path
if ($signature.Status -ne "Valid") {
throw "Signature status is not valid. Status: $($signature.Status)"
@@ -862,14 +932,14 @@ function Test-FileSignature {
foreach ($thumbprint in $ExpectedThumbprint) {
if ($signature.SignerCertificate.Thumbprint.Contains($thumbprint)) {
Write-Output "Signature for $FilePath is valid"
Write-Output "Signature for $Path is valid"
$signatureMatched = $true
return
}
}
if ($signatureMatched) {
Write-Output "Signature for $FilePath is valid"
Write-Output "Signature for $Path is valid"
} else {
throw "Signature thumbprint do not match expected."
}

View File

@@ -41,7 +41,7 @@ Function Install-VisualStudio {
$bootstrapperFilePath = Invoke-DownloadWithRetry $BootstrapperUrl
# Verify that the bootstrapper is signed by Microsoft
Test-FileSignature -FilePath $bootstrapperFilePath -ExpectedThumbprint $SignatureThumbprint
Test-FileSignature -Path $bootstrapperFilePath -ExpectedThumbprint $SignatureThumbprint
try {
Write-Host "Enable short name support on Windows needed for Xamarin Android AOT, defaults appear to have been changed in Azure VMs"