@@ -79,43 +79,69 @@ if (-not (Get-Command wix -ErrorAction SilentlyContinue)) {
7979# UI extension provides WixUI_InstallDir
8080wix extension add - g WixToolset.UI.wixext | Out-Null
8181
82- # ---- (optional) sign the exe BEFORE packaging --------------------------------
83- function Invoke-TrustedSign ($file ) {
82+ # ---- (optional) code-sign a file --------------------------------------------
83+ # Supports TWO signing backends, no Azure required:
84+ # 1. A generic certificate (any CA — SSL.com, Certum, DigiCert, …) supplied as
85+ # a base64-encoded PFX in $env:WINDOWS_CERT_BASE64 + $env:WINDOWS_CERT_PASSWORD.
86+ # This is the simplest path: buy a code-signing cert from any vendor, export
87+ # it as .pfx, base64 it, drop it in a GitHub secret. (EV certs on hardware
88+ # tokens can't be exported — use the Azure path or the vendor's cloud signer.)
89+ # 2. Azure Trusted Signing, if $env:TRUSTED_SIGNING_ENDPOINT is set.
90+ # If neither is configured, the file is left unsigned (still a valid MSI).
91+ function Get-SignTool {
92+ $st = Get-ChildItem " ${env: ProgramFiles(x86)} \Windows Kits\10\bin\*\x64\signtool.exe" - ErrorAction SilentlyContinue |
93+ Sort-Object FullName | Select-Object - Last 1
94+ if (-not $st ) { throw " signtool.exe not found (install the Windows SDK)" }
95+ return $st.FullName
96+ }
97+
98+ function Invoke-Sign ($file ) {
8499 if (-not $Sign ) { return }
85- if (-not $env: TRUSTED_SIGNING_ENDPOINT ) {
86- Warn " signing requested but TRUSTED_SIGNING_* env not set — leaving $file unsigned"
100+
101+ # --- backend 1: generic PFX certificate (any CA) ---
102+ if ($env: WINDOWS_CERT_BASE64 ) {
103+ Info " code-signing $file with PFX certificate"
104+ $pfx = Join-Path $env: TEMP " codesign.pfx"
105+ [IO.File ]::WriteAllBytes($pfx , [Convert ]::FromBase64String($env: WINDOWS_CERT_BASE64 ))
106+ $signtool = Get-SignTool
107+ & $signtool sign / v / fd SHA256 `
108+ / f $pfx / p " $env: WINDOWS_CERT_PASSWORD " `
109+ / tr " http://timestamp.digicert.com" / td SHA256 `
110+ $file
111+ Remove-Item $pfx - Force - ErrorAction SilentlyContinue
112+ if ($LASTEXITCODE -ne 0 ) { throw " signtool failed on $file " }
113+ Ok " signed $file "
87114 return
88115 }
89- Info " code-signing $file via Azure Trusted Signing"
90-
91- # Trusted Signing dlib + metadata describe the cert profile to signtool.
92- $dlibDir = Join-Path $env: TEMP " tsdlib"
93- if (-not (Test-Path " $dlibDir \bin\x64\Azure.CodeSigning.Dlib.dll" )) {
94- New-Item - ItemType Directory - Force - Path $dlibDir | Out-Null
95- Info " fetching Microsoft.Trusted.Signing.Client"
96- nuget install Microsoft.Trusted.Signing.Client - Version 1.0 .60 `
97- - OutputDirectory $dlibDir - ExcludeVersion | Out-Null
116+
117+ # --- backend 2: Azure Trusted Signing ---
118+ if ($env: TRUSTED_SIGNING_ENDPOINT ) {
119+ Info " code-signing $file via Azure Trusted Signing"
120+ $dlibDir = Join-Path $env: TEMP " tsdlib"
121+ if (-not (Test-Path " $dlibDir \bin\x64\Azure.CodeSigning.Dlib.dll" )) {
122+ New-Item - ItemType Directory - Force - Path $dlibDir | Out-Null
123+ nuget install Microsoft.Trusted.Signing.Client - Version 1.0 .60 `
124+ - OutputDirectory $dlibDir - ExcludeVersion | Out-Null
125+ }
126+ $dlib = Get-ChildItem - Recurse $dlibDir - Filter " Azure.CodeSigning.Dlib.dll" | Select-Object - First 1
127+ $meta = Join-Path $env: TEMP " metadata.json"
128+ @ {
129+ Endpoint = $env: TRUSTED_SIGNING_ENDPOINT
130+ CodeSigningAccountName = $env: TRUSTED_SIGNING_ACCOUNT
131+ CertificateProfileName = $env: TRUSTED_SIGNING_PROFILE
132+ } | ConvertTo-Json | Set-Content - Path $meta - Encoding ASCII
133+ $signtool = Get-SignTool
134+ & $signtool sign / v / fd SHA256 / tr " http://timestamp.acs.microsoft.com" / td SHA256 `
135+ / dlib $dlib.FullName / dmdf $meta $file
136+ if ($LASTEXITCODE -ne 0 ) { throw " signtool failed on $file " }
137+ Ok " signed $file "
138+ return
98139 }
99- $dlib = Get-ChildItem - Recurse $dlibDir - Filter " Azure.CodeSigning.Dlib.dll" |
100- Select-Object - First 1
101- $meta = Join-Path $env: TEMP " metadata.json"
102- @ {
103- Endpoint = $env: TRUSTED_SIGNING_ENDPOINT
104- CodeSigningAccountName = $env: TRUSTED_SIGNING_ACCOUNT
105- CertificateProfileName = $env: TRUSTED_SIGNING_PROFILE
106- } | ConvertTo-Json | Set-Content - Path $meta - Encoding ASCII
107-
108- $signtool = Get-ChildItem " ${env: ProgramFiles(x86)} \Windows Kits\10\bin\*\x64\signtool.exe" |
109- Sort-Object FullName | Select-Object - Last 1
110- & $signtool.FullName sign `
111- / v / fd SHA256 / tr " http://timestamp.acs.microsoft.com" / td SHA256 `
112- / dlib $dlib.FullName / dmdf $meta `
113- $file
114- if ($LASTEXITCODE -ne 0 ) { throw " signtool failed on $file " }
115- Ok " signed $file "
140+
141+ Warn " signing requested but no certificate configured — leaving $file unsigned"
116142}
117143
118- Invoke-TrustedSign $Exe
144+ Invoke-Sign $Exe
119145
120146# ---- build the MSI -----------------------------------------------------------
121147Info " building $msi (WiX v4, $Arch )"
@@ -131,6 +157,6 @@ if ($LASTEXITCODE -ne 0) { throw "wix build failed" }
131157Ok " built $msi "
132158
133159# ---- sign the MSI ------------------------------------------------------------
134- Invoke-TrustedSign $msi
160+ Invoke-Sign $msi
135161
136162Ok " done: $msi "
0 commit comments