fix: sign Windows release installers
This commit is contained in:
115
.github/scripts/configure-windows-authenticode.ps1
vendored
Normal file
115
.github/scripts/configure-windows-authenticode.ps1
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
param(
|
||||
[string]$ConfigPath = "src-tauri/tauri.windows-signing.conf.json"
|
||||
)
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
function Read-FirstEnv {
|
||||
param([string[]]$Names)
|
||||
|
||||
foreach ($Name in $Names) {
|
||||
$Value = [Environment]::GetEnvironmentVariable($Name)
|
||||
if (-not [string]::IsNullOrWhiteSpace($Value)) {
|
||||
return $Value.Trim()
|
||||
}
|
||||
}
|
||||
|
||||
throw "Set one of these environment variables: $($Names -join ', ')"
|
||||
}
|
||||
|
||||
function Read-OptionalEnv {
|
||||
param(
|
||||
[string[]]$Names,
|
||||
[string]$DefaultValue
|
||||
)
|
||||
|
||||
foreach ($Name in $Names) {
|
||||
$Value = [Environment]::GetEnvironmentVariable($Name)
|
||||
if (-not [string]::IsNullOrWhiteSpace($Value)) {
|
||||
return $Value.Trim()
|
||||
}
|
||||
}
|
||||
|
||||
return $DefaultValue
|
||||
}
|
||||
|
||||
function Normalize-Thumbprint {
|
||||
param([string]$Thumbprint)
|
||||
|
||||
return ($Thumbprint -replace "\s", "").ToUpperInvariant()
|
||||
}
|
||||
|
||||
function Convert-CertificateSecretToBytes {
|
||||
param([string]$CertificateSecret)
|
||||
|
||||
$Base64Lines = $CertificateSecret -split "\r?\n" |
|
||||
Where-Object { $_ -notmatch "^-+BEGIN " -and $_ -notmatch "^-+END " }
|
||||
$CertificateBase64 = ($Base64Lines -join "") -replace "\s", ""
|
||||
|
||||
try {
|
||||
return [Convert]::FromBase64String($CertificateBase64)
|
||||
} catch {
|
||||
throw "Windows code-signing certificate must be base64-encoded PFX data."
|
||||
}
|
||||
}
|
||||
|
||||
$CertificateSecret = Read-FirstEnv @("WINDOWS_CODE_SIGNING_CERTIFICATE", "WINDOWS_CERTIFICATE")
|
||||
$CertificatePassword = Read-FirstEnv @("WINDOWS_CODE_SIGNING_CERTIFICATE_PASSWORD", "WINDOWS_CERTIFICATE_PASSWORD")
|
||||
$ConfiguredThumbprint = Read-OptionalEnv @("WINDOWS_CODE_SIGNING_CERTIFICATE_THUMBPRINT", "WINDOWS_CERTIFICATE_THUMBPRINT") ""
|
||||
$DigestAlgorithm = Read-OptionalEnv @("WINDOWS_CODE_SIGNING_DIGEST_ALGORITHM") "sha256"
|
||||
$TimestampUrl = Read-OptionalEnv @("WINDOWS_CODE_SIGNING_TIMESTAMP_URL", "WINDOWS_TIMESTAMP_URL") "http://timestamp.digicert.com"
|
||||
|
||||
$TempRoot = Join-Path ([IO.Path]::GetTempPath()) "tolaria-windows-signing"
|
||||
if (-not [string]::IsNullOrWhiteSpace($env:RUNNER_TEMP)) {
|
||||
$TempRoot = Join-Path $env:RUNNER_TEMP "tolaria-windows-signing"
|
||||
}
|
||||
New-Item -ItemType Directory -Force -Path $TempRoot | Out-Null
|
||||
|
||||
$PfxPath = Join-Path $TempRoot "certificate.pfx"
|
||||
[IO.File]::WriteAllBytes($PfxPath, (Convert-CertificateSecretToBytes $CertificateSecret))
|
||||
|
||||
$SecurePassword = ConvertTo-SecureString -String $CertificatePassword -Force -AsPlainText
|
||||
$ImportedCertificates = @(Import-PfxCertificate -FilePath $PfxPath -CertStoreLocation Cert:\CurrentUser\My -Password $SecurePassword)
|
||||
Remove-Item -Force -ErrorAction SilentlyContinue $PfxPath
|
||||
|
||||
$ImportedCertificate = $ImportedCertificates | Where-Object { $_.HasPrivateKey } | Select-Object -First 1
|
||||
if ($null -eq $ImportedCertificate) {
|
||||
throw "The imported Windows code-signing certificate does not include a private key."
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($ConfiguredThumbprint)) {
|
||||
$CertificateThumbprint = Normalize-Thumbprint $ImportedCertificate.Thumbprint
|
||||
} else {
|
||||
$CertificateThumbprint = Normalize-Thumbprint $ConfiguredThumbprint
|
||||
}
|
||||
|
||||
$StoreCertificate = Get-ChildItem Cert:\CurrentUser\My |
|
||||
Where-Object { (Normalize-Thumbprint $_.Thumbprint) -eq $CertificateThumbprint } |
|
||||
Select-Object -First 1
|
||||
if ($null -eq $StoreCertificate) {
|
||||
throw "The requested Windows code-signing certificate thumbprint was not found in Cert:\CurrentUser\My."
|
||||
}
|
||||
|
||||
$Config = @{
|
||||
bundle = @{
|
||||
windows = @{
|
||||
certificateThumbprint = $CertificateThumbprint
|
||||
digestAlgorithm = $DigestAlgorithm
|
||||
timestampUrl = $TimestampUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$ResolvedConfigPath = Resolve-Path -Path (Split-Path -Parent $ConfigPath) -ErrorAction SilentlyContinue
|
||||
if ($null -eq $ResolvedConfigPath) {
|
||||
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $ConfigPath) | Out-Null
|
||||
}
|
||||
|
||||
$Config | ConvertTo-Json -Depth 10 | Set-Content -Path $ConfigPath -Encoding utf8NoBOM
|
||||
|
||||
if (-not [string]::IsNullOrWhiteSpace($env:GITHUB_ENV)) {
|
||||
"WINDOWS_CODE_SIGNING_CERTIFICATE_THUMBPRINT=$CertificateThumbprint" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
||||
}
|
||||
|
||||
Write-Host "Prepared Windows Authenticode signing config at $ConfigPath."
|
||||
Reference in New Issue
Block a user