mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-19 05:31:04 +00:00
Sign Windows release builds with the SignPath release certificate
Release-branch builds sign every unsigned executable, DLL and Python module in the x64 and arm64 portable bundles and installers, after approval in SignPath. The binaries and installer now carry OrcaSlicer version information.
This commit is contained in:
1 parent
40761ec6e2
commit
948e6637fb
12 files changed
+298
-116
No files matched your search
@@ -0,0 +1,40 @@
|
||||
# Copies the files SignPath signed back over the originals in the portable bundle they
|
||||
# were staged from with stage-for-signpath.ps1 -Bundle: the root of the signed artifact
|
||||
# holds OrcaSlicer's own binaries, third-party/ the other files under their paths in the
|
||||
# bundle.
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateScript({ Test-Path -LiteralPath $_ -PathType Container })]
|
||||
[string]$SignedDirectory,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateScript({ Test-Path -LiteralPath $_ -PathType Container })]
|
||||
[string]$Bundle
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$signedRoot = (Resolve-Path -LiteralPath $SignedDirectory).Path.TrimEnd('\', '/')
|
||||
$thirdPartyPrefix = "third-party" + [IO.Path]::DirectorySeparatorChar
|
||||
$files = Get-ChildItem -LiteralPath $signedRoot -Recurse -File
|
||||
if (-not $files) {
|
||||
throw "No signed files found in '$signedRoot'."
|
||||
}
|
||||
|
||||
foreach ($file in $files) {
|
||||
$relative = $file.FullName.Substring($signedRoot.Length + 1)
|
||||
if ($relative.StartsWith($thirdPartyPrefix, [StringComparison]::OrdinalIgnoreCase)) {
|
||||
$relative = $relative.Substring($thirdPartyPrefix.Length)
|
||||
}
|
||||
|
||||
# Every signed file replaces one that was staged, so a file without an original means
|
||||
# the artifact does not have the layout stage-for-signpath.ps1 produces.
|
||||
$target = Join-Path $Bundle $relative
|
||||
if (-not (Test-Path -LiteralPath $target -PathType Leaf)) {
|
||||
throw "Signed file '$relative' has no original in '$Bundle'."
|
||||
}
|
||||
Copy-Item -LiteralPath $file.FullName -Destination $target -Force
|
||||
}
|
||||
|
||||
Write-Host "Restored $($files.Count) signed files into '$Bundle'."
|
||||
@@ -0,0 +1,81 @@
|
||||
# Copies the files a SignPath signing request covers into the directory that request
|
||||
# uploads, after checking their version information. SignPath refuses to sign a file
|
||||
# whose ProductName or ProductVersion differs from its artifact configuration (see
|
||||
# signpath/), and reports it only once the request has been approved, so the check runs
|
||||
# before anything is submitted.
|
||||
#
|
||||
# -Path stages the given files at the root of -Destination.
|
||||
#
|
||||
# -Bundle stages a portable OrcaSlicer bundle for signpath/windows-binaries-v1.xml:
|
||||
# OrcaSlicer's own binaries (-OwnBinaries) at the root, where their version information
|
||||
# is checked, and every other executable, DLL and Python extension module that carries no
|
||||
# signature under third-party/, at its path in the bundle. Files signed by their vendor,
|
||||
# such as the Microsoft runtime, keep that signature. restore-from-signpath.ps1 copies the
|
||||
# signed files back.
|
||||
[CmdletBinding(DefaultParameterSetName = "Path")]
|
||||
param(
|
||||
[Parameter(Mandatory = $true, ParameterSetName = "Path")]
|
||||
[string[]]$Path,
|
||||
|
||||
[Parameter(Mandatory = $true, ParameterSetName = "Bundle")]
|
||||
[ValidateScript({ Test-Path -LiteralPath $_ -PathType Container })]
|
||||
[string]$Bundle,
|
||||
|
||||
[Parameter(ParameterSetName = "Bundle")]
|
||||
[string[]]$OwnBinaries = @("orca-slicer.exe", "OrcaSlicer.dll"),
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Destination,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$ProductVersion,
|
||||
|
||||
[string]$ProductName = "OrcaSlicer"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
function Test-VersionInfo {
|
||||
param([string]$File)
|
||||
|
||||
if (-not (Test-Path -LiteralPath $File -PathType Leaf)) {
|
||||
throw "File to sign was not found: $File"
|
||||
}
|
||||
|
||||
$info = [Diagnostics.FileVersionInfo]::GetVersionInfo((Resolve-Path -LiteralPath $File).Path)
|
||||
if ($info.ProductName -ne $ProductName -or $info.ProductVersion -ne $ProductVersion) {
|
||||
throw "'$File' has ProductName '$($info.ProductName)' and ProductVersion '$($info.ProductVersion)'; SignPath expects '$ProductName' and '$ProductVersion'."
|
||||
}
|
||||
}
|
||||
|
||||
New-Item -ItemType Directory -Force -Path $Destination | Out-Null
|
||||
|
||||
if ($PSCmdlet.ParameterSetName -eq "Path") {
|
||||
foreach ($file in $Path) {
|
||||
Test-VersionInfo $file
|
||||
Copy-Item -LiteralPath $file -Destination $Destination -Force
|
||||
Write-Host "Staged $(Split-Path -Leaf $file) ($ProductName $ProductVersion)"
|
||||
}
|
||||
exit 0
|
||||
}
|
||||
|
||||
$bundleRoot = (Resolve-Path -LiteralPath $Bundle).Path.TrimEnd('\', '/')
|
||||
foreach ($name in $OwnBinaries) {
|
||||
$file = Join-Path $bundleRoot $name
|
||||
Test-VersionInfo $file
|
||||
Copy-Item -LiteralPath $file -Destination $Destination -Force
|
||||
Write-Host "Staged $name ($ProductName $ProductVersion)"
|
||||
}
|
||||
|
||||
$thirdParty = Get-ChildItem -LiteralPath $bundleRoot -Recurse -File |
|
||||
Where-Object { $_.Extension -in ".exe", ".dll", ".pyd" } |
|
||||
Where-Object { $_.DirectoryName -ne $bundleRoot -or $_.Name -notin $OwnBinaries } |
|
||||
Where-Object { (Get-AuthenticodeSignature -LiteralPath $_.FullName).Status -eq "NotSigned" }
|
||||
|
||||
foreach ($file in $thirdParty) {
|
||||
$relative = $file.FullName.Substring($bundleRoot.Length + 1)
|
||||
$target = Join-Path (Join-Path $Destination "third-party") $relative
|
||||
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $target) | Out-Null
|
||||
Copy-Item -LiteralPath $file.FullName -Destination $target -Force
|
||||
}
|
||||
Write-Host "Staged $(@($thirdParty).Count) unsigned third-party files under third-party/"
|
||||
@@ -4,17 +4,15 @@ param(
|
||||
[ValidateScript({ Test-Path -LiteralPath $_ -PathType Container })]
|
||||
[string]$ArtifactDirectory,
|
||||
|
||||
[string[]]$Files = @(
|
||||
"orca-slicer.exe",
|
||||
"OrcaSlicer.dll"
|
||||
),
|
||||
# Paths relative to -ArtifactDirectory. Without them every executable, DLL and Python
|
||||
# extension module under it is verified.
|
||||
[string[]]$Files,
|
||||
|
||||
[string]$SignToolPath,
|
||||
|
||||
# Accept signatures whose certificate chain terminates in an untrusted root.
|
||||
# Required for the SignPath test certificate (self-signed). Do NOT pass this
|
||||
# once a production CA-issued certificate is in use, so release builds enforce
|
||||
# a fully trusted chain.
|
||||
# with the release certificate, so release builds enforce a fully trusted chain.
|
||||
[switch]$AllowUntrustedRoot
|
||||
)
|
||||
|
||||
@@ -57,11 +55,20 @@ function Resolve-SignToolPath {
|
||||
throw "signtool.exe was not found. Install the Windows SDK or pass -SignToolPath."
|
||||
}
|
||||
|
||||
$artifactRoot = (Resolve-Path -LiteralPath $ArtifactDirectory).Path
|
||||
$artifactRoot = (Resolve-Path -LiteralPath $ArtifactDirectory).Path.TrimEnd('\', '/')
|
||||
$signtool = Resolve-SignToolPath -ExplicitPath $SignToolPath
|
||||
|
||||
if (-not $Files) {
|
||||
$Files = Get-ChildItem -LiteralPath $artifactRoot -Recurse -File |
|
||||
Where-Object { $_.Extension -in ".exe", ".dll", ".pyd" } |
|
||||
ForEach-Object { $_.FullName.Substring($artifactRoot.Length + 1) }
|
||||
if (-not $Files) {
|
||||
throw "No executables or DLLs found in '$artifactRoot'."
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Using SignTool: $signtool"
|
||||
Write-Host "Verifying Authenticode signatures in: $artifactRoot"
|
||||
Write-Host "Verifying Authenticode signatures of $(@($Files).Count) files in: $artifactRoot"
|
||||
|
||||
foreach ($relativePath in $Files) {
|
||||
$filePath = Join-Path $artifactRoot $relativePath
|
||||
@@ -69,8 +76,6 @@ foreach ($relativePath in $Files) {
|
||||
throw "Expected signed file was not found: $filePath"
|
||||
}
|
||||
|
||||
Write-Host "Verifying $relativePath"
|
||||
|
||||
# Capture signtool output without letting native stderr (redirected via 2>&1)
|
||||
# raise a terminating NativeCommandError under $ErrorActionPreference = 'Stop'.
|
||||
$previousErrorActionPreference = $ErrorActionPreference
|
||||
@@ -83,9 +88,9 @@ foreach ($relativePath in $Files) {
|
||||
$ErrorActionPreference = $previousErrorActionPreference
|
||||
}
|
||||
|
||||
$output | ForEach-Object { Write-Host $_ }
|
||||
|
||||
$signature = Get-AuthenticodeSignature -LiteralPath $filePath
|
||||
if ($exitCode -eq 0) {
|
||||
Write-Host "Verified $relativePath ($($signature.SignerCertificate.Subject))"
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -95,15 +100,16 @@ foreach ($relativePath in $Files) {
|
||||
# structured Get-AuthenticodeSignature result instead: accept only when the
|
||||
# file is genuinely signed and the sole problem is that the chain terminates
|
||||
# in an untrusted root (i.e. the self-signed SignPath test certificate).
|
||||
$signature = Get-AuthenticodeSignature -LiteralPath $filePath
|
||||
$isSigned = ($signature.SignatureType -eq "Authenticode") -and ($null -ne $signature.SignerCertificate)
|
||||
$untrustedRootOnly = $signature.StatusMessage -match "terminated in a root certificate which is not trusted"
|
||||
if ($isSigned -and $untrustedRootOnly) {
|
||||
Write-Host " Accepted: '$relativePath' is signed but its certificate chains to an untrusted root (expected for the SignPath test certificate)."
|
||||
Write-Host "Accepted $relativePath ($($signature.SignerCertificate.Subject)): signed, but its certificate chains to an untrusted root (expected for the SignPath test certificate)."
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
# The full chain and error details only for a file that did not verify.
|
||||
$output | ForEach-Object { Write-Host " $_" }
|
||||
throw "SignTool verification failed for '$relativePath' with exit code $exitCode."
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user