Sign Windows engine releases with Azure Artifact Signing (#742)

* Sign Windows engine releases with Azure Artifact Signing

Isolate OIDC signing behind a maintainer-approved release environment and publish only verified, timestamped company-signed Windows output.

AI assistance: implemented and verified with Codex under maintainer direction.

* Clarify same-run artifact permissions

Keep least-privilege tokens: the pinned artifact actions use ACTIONS_RUNTIME_TOKEN for same-run transfers. Guard against opting into cross-run downloads and use role-based reviewer wording.

AI assistance: prepared and verified with Codex under maintainer direction.
This commit is contained in:
Paul Bakaus
2026-09-05 15:38:55 -07:00
committed by GitHub
parent 707fb6061c
commit bb7663ecfb
4 changed files with 196 additions and 4 deletions
+52
View File
@@ -0,0 +1,52 @@
# Windows engine signing
Engine releases sign `impeccable.exe` with Azure Artifact Signing before
computing release checksums. The publisher is **Renaissance Geek, Inc.**
Existing release assets are immutable; never replace a shipped unsigned binary
with signed bytes under the same version.
## Access boundary
- Azure account: `impeccable-signing`, East US (`https://eus.codesigning.azure.net/`).
- Public Trust certificate profile: `impeccable-windows`.
- User-assigned managed identity: `impeccable-release-signing`, in the same resource group.
- Its only Azure role is **Artifact Signing Certificate Profile Signer**, scoped
to `impeccable-signing/certificateProfiles/impeccable-windows`, not the account
or subscription.
- Federated credential: `github-windows-signing`, issuer
`https://token.actions.githubusercontent.com`, audience `api://AzureADTokenExchange`,
subject `repo:pbakaus/impeccable:environment:windows-signing`.
- GitHub environment: `windows-signing`, restricted to **tags** matching
`engine-v*`, with `pbakaus` as required reviewer and administrator bypass off.
Self-review allows the required reviewer to approve releases they trigger.
- Environment variables `AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, and
`AZURE_SUBSCRIPTION_ID` contain public identifiers, not secrets. No client
secret, private key, or PFX is stored in GitHub.
## Release and verification
Run the normal `bun run release:engine` flow, then review and approve the
`windows-signing` deployment for that tag in GitHub Actions. Check the tag's
commit and workflow before approving: the environment approval grants that job
the ability to sign as the company.
The build job uploads Windows output as `unsigned-windows-x64`. A separate
Windows runner downloads that artifact from the same run, signs exactly
`impeccable.exe`, and requires a valid Authenticode signature, the expected
publisher, and a timestamp before uploading `impeccable-windows-x64`. That
runner does not check out repository code or execute the downloaded engine.
Only its job receives an OIDC token; only the publish job can write releases.
Publication waits for successful signing and downloads only `impeccable-*`
artifacts, so it cannot package the unsigned intermediate.
RFC 3161 timestamping is required because Azure issues short-lived signing
certificates. Don't pin a leaf certificate thumbprint: Azure rotates them.
If signing or verification fails, fix the cause and retry; don't add an
unsigned fallback or weaken the environment gate.
The workflow configuration is regression-tested by
`bun test tests/release-engine-workflow.test.js`. An actual protected engine
release is still needed to verify Azure OIDC and Authenticode end to end.
References: [Azure signing roles](https://learn.microsoft.com/en-us/azure/artifact-signing/tutorial-assign-roles),
[official signing action](https://github.com/Azure/artifact-signing-action).