Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
69 lines
3.5 KiB
PowerShell
69 lines
3.5 KiB
PowerShell
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Mandatory = $true)][string]$DistDirectory,
|
|
[Parameter(Mandatory = $true)][string]$SevenZipExecutable,
|
|
[Parameter(Mandatory = $true)][string]$ExpectedPublisher
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
$ErrorActionPreference = 'Stop'
|
|
$dist = [IO.Path]::GetFullPath($DistDirectory)
|
|
$sevenZip = [IO.Path]::GetFullPath($SevenZipExecutable)
|
|
if ([string]::IsNullOrWhiteSpace($ExpectedPublisher)) {
|
|
throw 'ExpectedPublisher is required for signed Windows packages.'
|
|
}
|
|
|
|
function Assert-AuthenticodeBoundary {
|
|
param([Parameter(Mandatory = $true)][string]$Path, [Parameter(Mandatory = $true)][string]$Role)
|
|
$signature = Get-AuthenticodeSignature -LiteralPath $Path
|
|
$subject = if ($null -ne $signature.SignerCertificate) { $signature.SignerCertificate.Subject } else { '' }
|
|
$timestampSubject = if ($null -ne $signature.TimeStamperCertificate) { $signature.TimeStamperCertificate.Subject } else { '' }
|
|
if ($signature.Status -ne 'Valid') {
|
|
throw "Windows package boundary '$Role' has invalid Authenticode status '$($signature.Status)'."
|
|
}
|
|
if ($subject.IndexOf($ExpectedPublisher, [StringComparison]::OrdinalIgnoreCase) -lt 0) {
|
|
throw "Windows package boundary '$Role' signer '$subject' does not match '$ExpectedPublisher'."
|
|
}
|
|
if ([string]::IsNullOrWhiteSpace($timestampSubject)) {
|
|
throw "Windows package boundary '$Role' has no timestamp certificate."
|
|
}
|
|
}
|
|
|
|
$installers = @(Get-ChildItem -LiteralPath $dist -File -Filter '*.exe')
|
|
if ($installers.Count -ne 1) {
|
|
throw "Expected exactly one Windows NSIS installer, found $($installers.Count)."
|
|
}
|
|
Assert-AuthenticodeBoundary -Path $installers[0].FullName -Role 'installer'
|
|
|
|
$extractionRoot = Join-Path $env:RUNNER_TEMP ('tutti-certum-' + [Guid]::NewGuid().ToString('N'))
|
|
$outer = Join-Path $extractionRoot 'outer'
|
|
$inner = Join-Path $extractionRoot 'inner'
|
|
New-Item -ItemType Directory -Force -Path $outer, $inner | Out-Null
|
|
try {
|
|
& $sevenZip x -y "-o$outer" $installers[0].FullName | Out-Null
|
|
if ($LASTEXITCODE -ne 0) { throw "Extracting the NSIS installer failed with exit code $LASTEXITCODE." }
|
|
|
|
$outerExecutables = @(Get-ChildItem -LiteralPath $outer -Recurse -File -Filter '*.exe')
|
|
if ($outerExecutables.Count -eq 0) { throw 'The NSIS installer does not contain a signed embedded uninstaller.' }
|
|
foreach ($executable in $outerExecutables) {
|
|
$role = [IO.Path]::GetRelativePath($outer, $executable.FullName).Replace('\', '/')
|
|
Assert-AuthenticodeBoundary -Path $executable.FullName -Role $role
|
|
}
|
|
|
|
$appArchives = @(Get-ChildItem -LiteralPath $outer -Recurse -File -Filter 'app-64.7z')
|
|
if ($appArchives.Count -ne 1) { throw "Expected one app-64.7z in the NSIS installer, found $($appArchives.Count)." }
|
|
& $sevenZip x -y "-o$inner" $appArchives[0].FullName | Out-Null
|
|
if ($LASTEXITCODE -ne 0) { throw "Extracting app-64.7z failed with exit code $LASTEXITCODE." }
|
|
|
|
$applicationExecutables = @(Get-ChildItem -LiteralPath $inner -Recurse -File -Filter '*.exe')
|
|
if ($applicationExecutables.Count -eq 0) { throw 'The packaged application contains no Windows executables.' }
|
|
foreach ($executable in $applicationExecutables) {
|
|
$role = [IO.Path]::GetRelativePath($inner, $executable.FullName).Replace('\', '/')
|
|
Assert-AuthenticodeBoundary -Path $executable.FullName -Role $role
|
|
}
|
|
Write-Output "Verified $($applicationExecutables.Count) application executables and $($outerExecutables.Count) NSIS executables."
|
|
}
|
|
finally {
|
|
Remove-Item -LiteralPath $extractionRoot -Recurse -Force -ErrorAction SilentlyContinue
|
|
}
|