
Split packaging on Windows into dedicated jobs that run with access to
an EV signing certificate.
Prior to commit 0929221ca3
(gitlab-ci: Simplify Windows packaging
pipeline, 2023-02-28, v3.26.0-rc5~3^2~3) we had separate packaging jobs,
but they did not run in release packaging pipelines. Restore them, and
run them in both nightly and release packaging pipelines.
95 lines
3.4 KiB
PowerShell
95 lines
3.4 KiB
PowerShell
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
# file LICENSE.rst or https://cmake.org/licensing for details.
|
|
|
|
# Run this script on a Windows host in a CMake single-config build tree.
|
|
|
|
param (
|
|
[string]$signtool = 'signtool',
|
|
[string]$cpack = 'bin\cpack',
|
|
[string]$pass = $null
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
# Cleanup temporary file(s) on exit.
|
|
$null = Register-EngineEvent PowerShell.Exiting -Action {
|
|
if ($certFile) {
|
|
Remove-Item $certFile -Force
|
|
}
|
|
}
|
|
|
|
# If the passphrase was not provided on the command-line,
|
|
# check for a GitLab CI variable in the environment.
|
|
if (-not $pass) {
|
|
$pass = $env:SIGNTOOL_PASS
|
|
|
|
# If the environment variable looks like a GitLab CI file-type variable,
|
|
# replace it with the content of the file.
|
|
if ($pass -and
|
|
$pass.EndsWith("SIGNTOOL_PASS") -and
|
|
(Test-Path -Path "$pass" -IsValid) -and
|
|
(Test-Path -Path "$pass" -PathType Leaf)) {
|
|
$pass = Get-Content -Path "$pass"
|
|
}
|
|
}
|
|
|
|
# Collect signtool arguments to specify a certificate.
|
|
$cert = @()
|
|
|
|
# Select a signing certificate to pass to signtool.
|
|
if ($certX509 = Get-ChildItem -Recurse -Path "Cert:" -CodeSigningCert |
|
|
Where-Object { $_.PublicKey.Oid.FriendlyName -eq "RSA" } |
|
|
Select-Object -First 1) {
|
|
# Identify the private key provider name and container name.
|
|
if ($certRSA = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($certX509)) {
|
|
# $certRSA -is [System.Security.Cryptography.RSACng]
|
|
# Cryptography Next Generation (CNG) implementation
|
|
$csp = $certRSA.Key.Provider
|
|
$kc = $certRSA.Key.KeyName
|
|
} elseif ($certRSA = $certX509.PrivateKey) {
|
|
# $certRSA -is [System.Security.Cryptography.RSACryptoServiceProvider]
|
|
$csp = $certRSA.CspKeyContainerInfo.ProviderName
|
|
$kc = $certRSA.CspKeyContainerInfo.KeyContainerName
|
|
}
|
|
|
|
# Pass the selected certificate to signtool.
|
|
$certFile = New-TemporaryFile
|
|
$certBase64 = [System.Convert]::ToBase64String($certX509.RawData, [System.Base64FormattingOptions]::InsertLineBreaks)
|
|
$certPEM = "-----BEGIN CERTIFICATE-----", $certBase64, "-----END CERTIFICATE-----" -join "`n"
|
|
$certPEM | Out-File -FilePath "$certFile" -Encoding Ascii
|
|
$cert += "-f","$certFile"
|
|
|
|
# Tell signtool how to find the certificate's private key.
|
|
if ($csp) {
|
|
$cert += "-csp","$csp"
|
|
}
|
|
if ($kc) {
|
|
if ($pass) {
|
|
# The provider offers a syntax to encode the token passphrase in the key container name.
|
|
# https://web.archive.org/web/20250315200813/https://stackoverflow.com/questions/17927895/automate-extended-validation-ev-code-signing-with-safenet-etoken
|
|
$cert += "-kc","[{{$pass}}]=$kc"
|
|
$pass = $null
|
|
} else {
|
|
$cert += "-kc","$kc"
|
|
}
|
|
}
|
|
} else {
|
|
$cert += @("-a")
|
|
}
|
|
|
|
# Sign binaries with SHA-1 for Windows 7 and below.
|
|
& $signtool sign -v $cert -t http://timestamp.digicert.com -fd sha1 bin\*.exe
|
|
if (-not $?) { Exit $LastExitCode }
|
|
|
|
# Sign binaries with SHA-256 for Windows 8 and above.
|
|
& $signtool sign -v $cert -tr http://timestamp.digicert.com -fd sha256 -td sha256 -as bin\*.exe
|
|
if (-not $?) { Exit $LastExitCode }
|
|
|
|
# Create packages.
|
|
& $cpack -G "ZIP;WIX"
|
|
if (-not $?) { Exit $LastExitCode }
|
|
|
|
# Sign installer with SHA-256.
|
|
& $signtool sign -v $cert -tr http://timestamp.digicert.com -fd sha256 -td sha256 -d "CMake Windows Installer" cmake-*-win*.msi
|
|
if (-not $?) { Exit $LastExitCode }
|