Signed Windows installer using our Azure Trusted Signing pipeline. Phase 1 scope: installs signed agent to Program Files, creates ProgramData dir, Apps & Features entry with proper publisher, clean install + uninstall. Phase 2 deferred: service registration, MSI properties for site-code injection, agent install/uninstall custom actions, firewall rules. Verified end-to-end on Windows workstation: - wix build produces 1.16 MB MSI - sign.ps1 signs it against gururmm-public-trust cert profile - msiexec /qn installs silently, signature chain verifies on installed binary - msiexec /x uninstalls cleanly, retains ProgramData Tooling prerequisites documented in installer/README.md. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
76 lines
2.8 KiB
PowerShell
76 lines
2.8 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Build + sign a GuruRMM Agent MSI installer.
|
|
|
|
.DESCRIPTION
|
|
Downloads the signed agent binary for the target version, packages it into
|
|
an MSI via WiX, signs the MSI with Azure Trusted Signing, and writes the
|
|
result to the current directory.
|
|
|
|
Requires:
|
|
- .NET SDK 8
|
|
- wix global tool (dotnet tool install --global wix --version 5.0.2)
|
|
- Azure Trusted Signing access via sign.ps1 at C:\tools\trusted-signing\
|
|
- az login session (DefaultAzureCredential)
|
|
|
|
.EXAMPLE
|
|
.\build-msi.ps1 -Version 0.6.1
|
|
.\build-msi.ps1 -Version 0.6.1 -SourceUrl https://rmm-api.azcomputerguru.com/downloads -SkipSign
|
|
#>
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Mandatory)] [string] $Version,
|
|
[string] $SourceUrl = 'https://rmm-api.azcomputerguru.com/downloads',
|
|
[string] $WixExe = "$env:USERPROFILE\.dotnet\tools\wix.exe",
|
|
[string] $SignScript = 'C:\tools\trusted-signing\sign.ps1',
|
|
[switch] $SkipSign,
|
|
[switch] $KeepSource
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
Set-Location $PSScriptRoot
|
|
|
|
if (-not (Test-Path $WixExe)) { throw "wix.exe not found at $WixExe" }
|
|
|
|
$srcDir = Join-Path $PSScriptRoot 'src'
|
|
if (-not (Test-Path $srcDir)) { New-Item -ItemType Directory -Path $srcDir | Out-Null }
|
|
|
|
$exePath = Join-Path $srcDir 'gururmm-agent.exe'
|
|
$downloadUrl = "$SourceUrl/gururmm-agent-windows-amd64-$Version.exe"
|
|
|
|
Write-Host "[1] Downloading signed agent $Version from $downloadUrl ..." -ForegroundColor Cyan
|
|
Invoke-WebRequest -Uri $downloadUrl -OutFile $exePath -UseBasicParsing
|
|
$sig = Get-AuthenticodeSignature $exePath
|
|
if ($sig.Status -ne 'Valid') {
|
|
throw "Downloaded agent has invalid or missing signature: $($sig.Status). Refusing to package an unsigned agent."
|
|
}
|
|
Write-Host " signed by: $($sig.SignerCertificate.Subject)" -ForegroundColor Gray
|
|
|
|
$msiName = "gururmm-agent-$Version.msi"
|
|
Write-Host "[2] Building $msiName via WiX ..." -ForegroundColor Cyan
|
|
& $WixExe build gururmm.wxs -arch x64 -o $msiName -d "Version=$Version"
|
|
if ($LASTEXITCODE -ne 0) { throw "wix build failed (exit $LASTEXITCODE)" }
|
|
|
|
if (-not $SkipSign) {
|
|
if (-not (Test-Path $SignScript)) { throw "sign.ps1 not found at $SignScript" }
|
|
Write-Host "[3] Signing $msiName ..." -ForegroundColor Cyan
|
|
& $SignScript -File (Join-Path $PSScriptRoot $msiName) `
|
|
-Description "GuruRMM Agent Installer v$Version" `
|
|
-Url 'https://www.azcomputerguru.com' `
|
|
-Verify
|
|
if ($LASTEXITCODE -ne 0) { throw "signing failed (exit $LASTEXITCODE)" }
|
|
}
|
|
|
|
if (-not $KeepSource) {
|
|
Remove-Item $exePath -ErrorAction SilentlyContinue
|
|
}
|
|
|
|
$msiPath = Join-Path $PSScriptRoot $msiName
|
|
$hash = (Get-FileHash $msiPath -Algorithm SHA256).Hash.ToLower()
|
|
$hash | Set-Content "$msiPath.sha256"
|
|
"$hash $msiName" | Set-Content "$msiPath.sha256"
|
|
Write-Host ""
|
|
Write-Host "[DONE]" -ForegroundColor Green
|
|
Write-Host " msi: $msiPath"
|
|
Write-Host " sha256: $hash"
|