diff --git a/.buildkite/commands/package_windows.ps1 b/.buildkite/commands/package_windows.ps1 index e2fc28e3e..38f39edb7 100644 --- a/.buildkite/commands/package_windows.ps1 +++ b/.buildkite/commands/package_windows.ps1 @@ -1,41 +1,13 @@ # Stop script execution when a non-terminating error occurs $ErrorActionPreference = "Stop" -# Windows code signing defaults to Azure Artifact Signing. Set USE_PFX_CODE_SIGNING to use PFX. -$usePfx = -not [string]::IsNullOrEmpty($env:USE_PFX_CODE_SIGNING) -$useAzure = -not $usePfx - -If ($useAzure) { - Write-Host "--- :windows: Configure Azure Artifact Signing" - # From the CI toolkit; fails here with diagnostics if Azure credentials are wrong. - & "setup_azure_trusted_signing.ps1" - If ($LastExitCode -ne 0) { Exit $LastExitCode } -} - -If ($usePfx) { - Write-Host "--- :windows: Configure PFX code signing" - # From the CI toolkit; materializes certificate.pfx. - & "setup_windows_code_signing.ps1" - If ($LastExitCode -ne 0) { Exit $LastExitCode } - - # Read the PFX password from the process env, falling back to the machine-wide env. - $windowsCertPassword = [System.Environment]::GetEnvironmentVariable('WINDOWS_CODE_SIGNING_CERT_PASSWORD', [System.EnvironmentVariableTarget]::Process) - If ([string]::IsNullOrEmpty($windowsCertPassword)) { - $windowsCertPassword = [System.Environment]::GetEnvironmentVariable('WINDOWS_CODE_SIGNING_CERT_PASSWORD', [System.EnvironmentVariableTarget]::Machine) - } - If ([string]::IsNullOrEmpty($windowsCertPassword)) { - Write-Host "[!] WINDOWS_CODE_SIGNING_CERT_PASSWORD is not set in either process or machine environments." - Exit 1 - } - - $certPath = (Convert-Path .\certificate.pfx) - If (-not (Test-Path $certPath)) { - Write-Host "[!] Certificate file does not exist at given path $certPath." - Exit 1 - } - - # Import the cert so electron-builder's certificateSubjectName lookup finds it. - Import-PfxCertificate -FilePath $certPath -CertStoreLocation Cert:\LocalMachine\Root -Password (ConvertTo-SecureString -String $windowsCertPassword -AsPlainText -Force) +Write-Host "--- :windows: Configure Azure Artifact Signing" +# From the CI toolkit; fails here with diagnostics if Azure credentials are wrong. +& "setup_azure_trusted_signing.ps1" +If ($LastExitCode -ne 0) { Exit $LastExitCode } +If ([string]::IsNullOrEmpty($env:SIGNTOOL_PATH)) { + Write-Host "[!] SIGNTOOL_PATH is not set after Azure Trusted Signing setup." + Exit 1 } Write-Host "--- :windows: Installing make" @@ -54,21 +26,19 @@ Write-Host "--- :windows: Packaging for Windows" make package-win32 SKIP_BUILD=true If ($LastExitCode -ne 0) { Exit $LastExitCode } -If ($useAzure) { - Write-Host "--- :windows: Verify Azure signatures" - # Every NSIS installer must carry a valid Authenticode signature. The Store AppX is intentionally - # unsigned (re-signed by the Store), so it is not verified here. - $exes = Get-ChildItem release\*.exe - If ($exes.Count -eq 0) { - Write-Host "[!] No release\*.exe found to verify." - Exit 1 - } - ForEach ($exe in $exes) { - & $env:SIGNTOOL_PATH verify /pa /v $exe.FullName - If ($LastExitCode -ne 0) { - Write-Host "[!] Signature verification failed for $($exe.FullName)" - Exit $LastExitCode - } +Write-Host "--- :windows: Verify Azure signatures" +# Every NSIS installer must carry a valid Authenticode signature. The Store AppX is intentionally +# unsigned (re-signed by the Store), so it is not verified here. +$exes = Get-ChildItem release\*.exe +If ($exes.Count -eq 0) { + Write-Host "[!] No release\*.exe found to verify." + Exit 1 +} +ForEach ($exe in $exes) { + & $env:SIGNTOOL_PATH verify /pa /v $exe.FullName + If ($LastExitCode -ne 0) { + Write-Host "[!] Signature verification failed for $($exe.FullName)" + Exit $LastExitCode } - Write-Host "All Windows installers verified signed." } +Write-Host "All Windows installers verified signed." diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index ff08d1a35..b218a0751 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -85,25 +85,6 @@ steps: - release\*.blockmap - release\*.yml - # Validates the legacy PFX path alongside the default Azure build above. - - label: Package on Windows (PFX code signing) - key: package-windows-pfx - agents: - queue: windows - plugins: - - $CI_TOOLKIT_PLUGIN - - $NVM_PLUGIN - command: .buildkite/commands/package_windows.ps1 - env: - USE_PFX_CODE_SIGNING: 1 - CSC_FOR_PULL_REQUEST: true - PUBLISH: never - artifact_paths: - - release\*.exe - - release\*.appx - - release\*.blockmap - - release\*.yml - - label: Package on Linux key: package-linux plugins: diff --git a/Makefile b/Makefile index fa61ffc40..37b21fa16 100644 --- a/Makefile +++ b/Makefile @@ -139,14 +139,10 @@ win32: config-release build-if-changed .PHONY: package package: build-if-changed -# Windows signing: Azure Artifact Signing by default, or PFX when USE_PFX_CODE_SIGNING is set. In -# Azure mode the NSIS exe signs through the win.sign callback, and the Store AppX builds unsigned — -# `env -u` removes PFX cert vars so electron-builder skips its built-in /fd-less PFX call. The -# Store re-signs the AppX regardless. In PFX mode both keep native cert signing, unchanged. -ifndef USE_PFX_CODE_SIGNING +# Windows signing: Azure Artifact Signing via the win.sign callback. The Store AppX builds +# unsigned because Store re-signs the AppX regardless. WIN_NSIS_SIGN := -c.win.sign=./scripts/azure-sign.cjs APPX_NO_SIGN := env -u CSC_LINK -u CSC_KEY_PASSWORD -u WIN_CSC_LINK -u WIN_CSC_KEY_PASSWORD -endif .PHONY: package-win32 package-win32: diff --git a/electron-builder.json b/electron-builder.json index 021f9ab4b..b9e923512 100644 --- a/electron-builder.json +++ b/electron-builder.json @@ -48,7 +48,6 @@ }, "win": { "icon": "resources/images/simplenote.ico", - "certificateSubjectName": "Automattic, Inc.", "publisherName": ["Automattic, Inc.", "Automattic Inc."], "artifactName": "Simplenote-win-${version}-${arch}.${ext}", "target": [ diff --git a/scripts/azure-sign.cjs b/scripts/azure-sign.cjs index 03c9285b3..3f1253834 100644 --- a/scripts/azure-sign.cjs +++ b/scripts/azure-sign.cjs @@ -1,8 +1,4 @@ -// electron-builder `win.sign` callback for Azure Artifact Signing. -// -// Azure Artifact Signing is the default Windows signing path. Set `USE_PFX_CODE_SIGNING` to leave -// this callback unwired and use electron-builder's native `certificateSubjectName` PFX path instead. -// Reaching this callback means Azure is intended, so missing Azure env fails CI. +// electron-builder `win.sign` callback for Azure Artifact Signing, the sole Windows signing path. // // electron-builder calls this once per file per signing-hash algorithm, after `rcedit` rewrites // the PE resource directory (so signatures are not orphaned). Azure Artifact Signing is diff --git a/scripts/package-win32.test.js b/scripts/package-win32.test.js deleted file mode 100644 index db3a1d73f..000000000 --- a/scripts/package-win32.test.js +++ /dev/null @@ -1,51 +0,0 @@ -const childProcess = require('node:child_process'); -const path = require('node:path'); - -const repoRoot = path.resolve(__dirname, '..'); - -function packageWin32DryRun(envOverrides = {}) { - const env = { ...process.env, ...envOverrides }; - Object.keys(env).forEach((key) => { - if (env[key] === undefined) { - delete env[key]; - } - }); - - const result = childProcess.spawnSync( - 'make', - ['-n', 'package-win32', 'PUBLISH=never', 'SKIP_BUILD=true'], - { - cwd: repoRoot, - encoding: 'utf8', - env, - } - ); - - if (result.status !== 0) { - throw new Error( - `make dry-run failed with ${result.status}\n${result.stdout}\n${result.stderr}` - ); - } - - return `${result.stdout}\n${result.stderr}`; -} - -describe('package-win32 signing mode', () => { - it('uses Azure signing by default', () => { - const output = packageWin32DryRun({ USE_PFX_CODE_SIGNING: undefined }); - - expect(output).toContain('-c.win.sign=./scripts/azure-sign.cjs'); - expect(output).toContain( - 'env -u CSC_LINK -u CSC_KEY_PASSWORD -u WIN_CSC_LINK -u WIN_CSC_KEY_PASSWORD' - ); - }); - - it('uses native PFX signing when requested', () => { - const output = packageWin32DryRun({ USE_PFX_CODE_SIGNING: '1' }); - - expect(output).not.toContain('-c.win.sign=./scripts/azure-sign.cjs'); - expect(output).not.toContain( - 'env -u CSC_LINK -u CSC_KEY_PASSWORD -u WIN_CSC_LINK -u WIN_CSC_KEY_PASSWORD' - ); - }); -});