Skip to content

ci(release): sign Windows with Azure Artifact Signing over OIDC - #104

Merged
its-janghoon merged 2 commits into
developfrom
feature/windows-signing-oidc
Oct 14, 2026
Merged

its-janghoon merged 2 commits into
developfrom
feature/windows-signing-oidc

Conversation

@its-janghoon

@its-janghoon its-janghoon commented Oct 14, 2026 •

Copy link
Copy Markdown
Member

Summary

Hardens Windows code signing to Azure Artifact Signing authenticated with the job's OpenID Connect token, the same shape as redrob-launcher #20 and redrob-cad #45.

  • sign-windows runs in environment: release with permissions: contents: read, id-token: write.
  • azure/login@v3 (AZURE_CLIENT_ID / AZURE_TENANT_ID / AZURE_SUBSCRIPTION_ID, if: env.AZURE_CLIENT_ID != '') runs after the artifact download and immediately before each signing step; a second login precedes the installer signing since the installer build sits between them. GitHub's OIDC token lives minutes.
  • script/sign-windows.ps1 is rewritten: signtool + the Microsoft.ArtifactSigning.Client dlib (Azure.CodeSigning.Dlib.dll, x64) with a metadata.json whose ExcludeCredentials lists InteractiveBrowser, ManagedIdentity, SharedTokenCache, VisualStudio, VisualStudioCode, AzurePowerShell, AzureDeveloperCli and WorkloadIdentity, so a missing login fails in seconds instead of waiting on a browser. It reads back every file with signtool verify /pa /v and Get-AuthenticodeSignature (Status must be Valid) and prints <file> signed by <Subject>.
  • Detection looks at ARTIFACT_SIGNING_ENDPOINT, ARTIFACT_SIGNING_ACCOUNT, ARTIFACT_SIGNING_CERT_PROFILE only. All unset: unsigned with a warning (unchanged behaviour). Some set: error. This is what tripped the v0.6.4 release yesterday with the old six-name check.
  • Removed: the PFX fallback (WIN_CSC_LINK, WIN_CSC_KEY_PASSWORD), the AZURE_ARTIFACT_SIGNING_* names, azure/artifact-signing-action, and the NotTrusted / UnknownError allowance. The workflow verify steps additionally require the signer to be CN=McKinley Rice, Inc..
  • Release notes name Azure Artifact Signing; docs/BRANCHING.md describes the new setup and secret names.

The release environment was created on the repository (it had none).

Verification

Dry run of the release workflow from this branch (dry_run: true, bump: patch): run 38578721967. The sign-windows job is green end to end; its log shows, for each of redrob-windows-x64, redrob-windows-x64-baseline, redrob-windows-arm64 redrob.exe and redrob-code-x64-setup.exe:

<file> signed by CN="McKinley Rice, Inc.", O="McKinley Rice, Inc.", L=Gangnam-gu, S=Seoul, C=KR
##[notice]Windows binaries signed via azure and verified
##[notice]Windows installer signed via azure and verified

An earlier dry run (38577750093) signed the same files but the read-back rejected the signer because the Subject renders the CN quoted; the second commit compares the parsed CN instead.

The sign-windows job now runs in the `release` environment with
`id-token: write`, logs in with azure/login right before each signing
step (the OIDC token lives minutes), and signs with signtool and the
Microsoft.ArtifactSigning.Client dlib through script/sign-windows.ps1.
The dlib metadata excludes every credential a runner cannot satisfy, so
a missing login fails in seconds instead of waiting on a browser.

Detection reads ARTIFACT_SIGNING_ENDPOINT, ARTIFACT_SIGNING_ACCOUNT and
ARTIFACT_SIGNING_CERT_PROFILE alone: all unset leaves the binaries
unsigned with a warning, a partial set is an error. The PFX fallback
(WIN_CSC_LINK / WIN_CSC_KEY_PASSWORD) and the AZURE_ARTIFACT_SIGNING_*
names are gone, as is the NotTrusted/UnknownError allowance: every file
is read back with `signtool verify /pa /v` and Get-AuthenticodeSignature
must be Valid with signer CN=McKinley Rice, Inc., logged as
`<file> signed by <Subject>`.

Mirrors redrob-launcher #20 and redrob-cad #45.
The first dry run signed every file but the read-back rejected the
signer: the Subject renders as `CN="McKinley Rice, Inc.", O=...`
(quoted, because the name contains a comma), so a regex over the raw
string never matched and the job recorded the binaries as unsigned.
GetNameInfo(SimpleName) yields the CN value itself.
@its-janghoon
its-janghoon merged commit bcb8af0 into develop Oct 14, 2026
29 of 34 checks passed
@its-janghoon
its-janghoon deleted the feature/windows-signing-oidc branch October 14, 2026 14:37

This branch was successfully deployed

1 active deployment
release — 4aaffba6 Deployed Oct 14, 2026 by its-janghoon via sign-windows #34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant