Files

66 lines
2.7 KiB
PowerShell

# Sign the given files with the release certificate from the repository secrets.
#
# msime-installer's Sign-PackageBinaries-Local.ps1 mints a self-signed certificate for local
# testing and must never run in CI, so this is a separate path using the real certificate. Used
# for the uiAccess Server binary and the finished installer.
#
# Requires CERTIFICATE_BASE64, CERTIFICATE_PASSWORD, TIMESTAMP_URL.
param(
[Parameter(Mandatory)][string[]]$Path,
[switch]$Recurse
)
$ErrorActionPreference = 'Stop'
$targets = if ($Recurse) {
Get-ChildItem -Recurse -File -Include '*.exe', '*.dll' -Path $Path
}
else {
Get-Item -Path $Path
}
# A package can contain the same payload through multiple input paths. Sign each
# physical file at most once; certificate usage is per signed file, not per
# signtool invocation.
$targets = @($targets | Sort-Object FullName -Unique)
if (-not $targets) {
throw "Nothing to sign under: $($Path -join ', ')"
}
Write-Host "Signing $($targets.Count) unique file(s):"
$targets | ForEach-Object { Write-Host " - $($_.FullName)" }
$signtool = Get-ChildItem 'C:\Program Files (x86)\Windows Kits\10\bin\*\x64\signtool.exe' |
Sort-Object FullName -Descending | Select-Object -First 1
if (-not $signtool) { throw 'signtool.exe not found in the Windows SDK.' }
if ($env:CERTIFICATE_THUMBPRINT) {
$thumbprint = $env:CERTIFICATE_THUMBPRINT -replace '\s', ''
$cert = Get-ChildItem Cert:\CurrentUser\My\$thumbprint -ErrorAction SilentlyContinue
if ($cert -and $cert.HasPrivateKey) {
& $signtool.FullName sign /sha1 $thumbprint /fd sha256 /tr $env:TIMESTAMP_URL /td sha256 /v @($targets.FullName)
if ($LASTEXITCODE -ne 0) { throw "signtool failed with exit code $LASTEXITCODE" }
Write-Host "Signed using certificate store thumbprint $thumbprint."
return
}
if (-not ($env:CERTIFICATE_BASE64 -and $env:CERTIFICATE_PASSWORD)) {
throw "Certificate with thumbprint $thumbprint is not available with a private key, and no PFX fallback is configured."
}
Write-Warning "Certificate thumbprint $thumbprint is unavailable; falling back to the PFX secret."
}
if ($env:CERTIFICATE_BASE64 -and $env:CERTIFICATE_PASSWORD) {
$pfx = Join-Path $env:RUNNER_TEMP 'metasequoia-signing.pfx'
[IO.File]::WriteAllBytes($pfx, [Convert]::FromBase64String($env:CERTIFICATE_BASE64))
try {
& $signtool.FullName sign /f $pfx /p $env:CERTIFICATE_PASSWORD /fd sha256 /tr $env:TIMESTAMP_URL /td sha256 /v @($targets.FullName)
if ($LASTEXITCODE -ne 0) { throw "signtool failed with exit code $LASTEXITCODE" }
} finally { Remove-Item $pfx -Force -ErrorAction SilentlyContinue }
}
else {
throw 'No usable signing certificate is configured.'
}
Write-Host "Signed $($targets.Count) file(s)."