Skip to content

feat(build): migrate Windows code signing to Azure Trusted Signing#2021

Merged
samuv merged 5 commits intomainfrom
azure-signin
Apr 16, 2026
Merged

feat(build): migrate Windows code signing to Azure Trusted Signing#2021
samuv merged 5 commits intomainfrom
azure-signin

Conversation

@samuv
Copy link
Copy Markdown
Collaborator

@samuv samuv commented Apr 16, 2026

The Windows code signing pipeline has been on DigiCert KeyLocker, which requires storing client cert files + API keys as repo secrets and shells out to smctl.exe from a custom @electron/windows-sign hook. This PR migrates Windows signing to Azure Trusted Signing, authenticated via OIDC workload identity federation (no client secret stored anywhere). DigiCert is kept as a runtime fallback so on-release.yml keeps working until the new path is validated end-to-end via /build-test --sign-windows.

  • Add utils/windows-sign-azure.ts returning an @electron/windows-sign config (signWithParams + Azure Code Signing DLib + metadata.json), following the official Electron Forge Trusted Signing guide; env-driven, returns undefined when not configured so it's safe to call unconditionally
  • Add a getWindowsSignConfig() helper in forge.config.ts that prefers Azure and falls back to the existing DigiCert hook when only SM_HOST + SM_API_KEY are set; both packagerConfig.windowsSign and the maker-squirrel windowsSign use it
  • Add .github/actions/setup-azure-trusted-signing composite action: azure/login@v2.3.0 (OIDC), nuget install Microsoft.Trusted.Signing.Client into C:\azsign\ (no-space path to avoid electron/windows-sign#45), locate the latest x64 signtool.exe in the Windows SDK, write metadata.json, export AZURE_CODE_SIGNING_DLIB / AZURE_METADATA_JSON / SIGNTOOL_PATH to GITHUB_ENV
  • Wire the new action into pr-build-test.yml with the 6 AZURE_ARTIFACT_SIGNING_* env-scoped secrets; conditionally activate the artifact-signing GitHub environment (environment: ${{ ... && 'artifact-signing' || '' }}) so the OIDC federated credential subject repo:stacklok/toolhive-studio:environment:artifact-signing is satisfied only when signing is requested — unsigned PR builds are unaffected
  • Document the new flow in docs/README.md (OIDC, environment-scoped secrets, composite action, how to test) and demote the DigiCert section to a legacy fallback note

Not changed in this PR (deliberate, follow-up):

  • on-release.yml still signs production releases via DigiCert; the follow-up will add environment: artifact-signing to its build job, swap to the Azure composite action, and remove the DigiCert hook + setup-windows-codesign action.

samuv added 3 commits April 16, 2026 18:16
Introduce `utils/windows-sign-azure.ts`, which returns an
`@electron/windows-sign` config using `signWithParams` with the
Azure Code Signing DLib and metadata.json, following the official
Electron Forge guide.

Wire it into `forge.config.ts` via a `getWindowsSignConfig()` helper
that prefers Azure Trusted Signing and falls back to the existing
DigiCert KeyLocker hook when only the legacy `SM_*` env vars are
set, so production releases keep working until the migration is
validated.
Add the `setup-azure-trusted-signing` composite action that logs in
to Azure via OIDC (azure/login@v2.3.0), installs the Azure Code
Signing DLib via NuGet under `C:\azsign\` (no-space path required
by electron/windows-sign#45), locates `signtool.exe` in the Windows
SDK, writes `metadata.json`, and exports `AZURE_CODE_SIGNING_DLIB`,
`AZURE_METADATA_JSON`, and `SIGNTOOL_PATH` for Electron Forge.

Update `pr-build-test.yml` to use it when `--sign-windows` is set
and conditionally activate the `artifact-signing` GitHub
environment so the OIDC federated credential subject
(`repo:stacklok/toolhive-studio:environment:artifact-signing`) is
satisfied. Unsigned builds are unaffected since the environment
gate only activates with the flag.
Replace the Windows signing section to describe the Azure Trusted
Signing flow (OIDC, environment-scoped secrets, the composite
action, and how to test on a PR with `/build-test --sign-windows`)
and demote the DigiCert KeyLocker section to a legacy fallback
note.
Copilot AI review requested due to automatic review settings April 16, 2026 16:21
@samuv samuv self-assigned this Apr 16, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Migrates the Windows code signing path from DigiCert KeyLocker (cert + API-key based) toward Azure Trusted Signing using OIDC workload identity federation, while keeping DigiCert as a fallback in the Forge config during the transition.

Changes:

  • Added an Azure Trusted Signing @electron/windows-sign config helper and wired it into forge.config.ts with DigiCert fallback.
  • Introduced a composite GitHub Action to authenticate to Azure via OIDC, install the Trusted Signing client DLib, generate metadata.json, and export required env vars.
  • Updated the PR build-test workflow and docs to support /build-test --sign-windows using the new Azure signing flow.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
utils/windows-sign-azure.ts Adds env-driven Azure Trusted Signing config for @electron/windows-sign.
forge.config.ts Centralizes Windows signing config resolution (prefer Azure, fallback to DigiCert).
.github/actions/setup-azure-trusted-signing/action.yml New composite action to setup Azure Trusted Signing (OIDC login + DLib + metadata + signtool).
.github/workflows/pr-build-test.yml Switches PR Windows signing setup to Azure Trusted Signing and conditionally selects an environment.
docs/README.md Documents Azure Trusted Signing flow and demotes DigiCert to legacy fallback.

Comment thread .github/workflows/pr-build-test.yml Outdated
Comment thread .github/workflows/pr-build-test.yml Outdated
Comment thread .github/actions/setup-azure-trusted-signing/action.yml
samuv added 2 commits April 16, 2026 18:31
The \`environment\` keyword applies to the whole job, so every matrix
row (Linux/macOS/Windows) was entering \`artifact-signing\` whenever
\`--sign-windows\` was set. That leaks environment-scoped secrets to
non-Windows builds and can gate them behind environment approvals for
no reason.

Add \`matrix.platform == 'win32'\` to the \`environment\` expression so
only the Windows row runs in \`artifact-signing\`; Linux and macOS
builds stay outside the environment entirely, exactly as they did
before the Azure Trusted Signing migration.

Flagged by Copilot review on #2021.
The composite action previously ran \`nuget install\` without
\`-Version\`, so every build pulled whatever NuGet considered current.
That makes the signing toolchain non-reproducible and a future package
release that reorganises the DLib layout (e.g. moves
\`Azure.CodeSigning.Dlib.dll\` out of \`bin\x64\\`) would silently
break Windows signing with no code change on our side.

Pin to 1.0.95 (latest on nuget.org, includes the signtool x86
regression fix) and document the upgrade path so bumps are explicit
and always exercised end-to-end via \`/build-test --sign-windows\`.

Flagged by Copilot review on #2021.
@samuv samuv merged commit a26d673 into main Apr 16, 2026
15 of 17 checks passed
@samuv samuv deleted the azure-signin branch April 16, 2026 16:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants