Migrate Windows code signing to Azure Trusted Signing (#811)

## Summary

Migrates Windows binary signing from Azure Key Vault (`jsign --storetype
AZUREKEYVAULT`) to [Azure Trusted
Signing](https://learn.microsoft.com/en-us/azure/trusted-signing/). The
previous AKV code-signing cert expired, breaking the release pipeline.
Trusted Signing issues short-lived Microsoft-managed certs so there's
nothing to rotate.

- `Makefile` / `scripts/crossbuild.mk`: bump `jsign` 6.0 → 7.4, switch
`--storetype` to `TRUSTEDSIGNING`, use the
`https://codesigning.azure.net` token audience, derive the keystore host
from `AZURE_SIGNING_ACCOUNT_ENDPOINT`, pass account/profile via
`--alias`, update the `SKIP_SIGNING` guard and error message.
- `.github/workflows/{build,release,prerelease,build_provider}.yml`:
replace the `AZURE_SIGNING_KEY_VAULT_URI` env passthrough with the three
new `AZURE_SIGNING_ACCOUNT_*` outputs and update the `SKIP_SIGNING`
expression.

Companion to pulumi/ci-mgmt#2126, pulumi/pulumi-command#1200, and
pulumi/pulumi-provider-boilerplate#1236. The ESC environment already
exposes the new variables and the signing SP has the `Artifact Signing
Certificate Profile Signer` role on the
`pulumi-code-signing/pulumi-code-signing` profile. Verified end-to-end
against pulumi-command, pulumi-random, and pulumi-provider-boilerplate.

## Test plan

- [ ] CI release build produces a Windows binary with a valid Trusted
Signing certificate chain
This commit is contained in:
Keith Mosher
2026-04-09 19:52:15 -04:00
committed by GitHub
parent 00ec8e3ebe
commit b0c5918c7c

View File

@@ -250,30 +250,32 @@ docs: $(shell find docs/yaml -type f) $(shell find ./provider/internal/embed -na
go generate docs/generate.go go generate docs/generate.go
@touch docs @touch docs
# Set these variables to enable signing of the windows binary # Set these variables to enable signing of the windows binary with Azure Trusted Signing.
AZURE_SIGNING_CLIENT_ID ?= AZURE_SIGNING_CLIENT_ID ?=
AZURE_SIGNING_CLIENT_SECRET ?= AZURE_SIGNING_CLIENT_SECRET ?=
AZURE_SIGNING_TENANT_ID ?= AZURE_SIGNING_TENANT_ID ?=
AZURE_SIGNING_KEY_VAULT_URI ?= AZURE_SIGNING_ACCOUNT_ENDPOINT ?=
AZURE_SIGNING_ACCOUNT_NAME ?=
AZURE_SIGNING_CERT_PROFILE_NAME ?=
SKIP_SIGNING ?= SKIP_SIGNING ?=
bin/jsign-6.0.jar: bin/jsign-7.4.jar:
@mkdir -p bin @mkdir -p bin
wget https://github.com/ebourg/jsign/releases/download/6.0/jsign-6.0.jar --output-document=bin/jsign-6.0.jar wget https://github.com/ebourg/jsign/releases/download/7.4/jsign-7.4.jar --output-document=bin/jsign-7.4.jar
sign-goreleaser-exe-amd64: GORELEASER_ARCH := amd64_v1 sign-goreleaser-exe-amd64: GORELEASER_ARCH := amd64_v1
sign-goreleaser-exe-arm64: GORELEASER_ARCH := arm64 sign-goreleaser-exe-arm64: GORELEASER_ARCH := arm64
# Set the shell to bash to allow for the use of bash syntax. # Set the shell to bash to allow for the use of bash syntax.
sign-goreleaser-exe-%: SHELL:=/bin/bash sign-goreleaser-exe-%: SHELL:=/bin/bash
sign-goreleaser-exe-%: bin/jsign-6.0.jar sign-goreleaser-exe-%: bin/jsign-7.4.jar
@# Only sign windows binary if fully configured. @# Only sign windows binary if fully configured.
@# Test variables set by joining with | between and looking for || showing at least one variable is empty. @# Test variables set by joining with | between and looking for || showing at least one variable is empty.
@# Move the binary to a temporary location and sign it there to avoid the target being up-to-date if signing fails. @# Move the binary to a temporary location and sign it there to avoid the target being up-to-date if signing fails.
@set -e; \ @set -e; \
if [[ "${SKIP_SIGNING}" != "true" ]]; then \ if [[ "${SKIP_SIGNING}" != "true" ]]; then \
if [[ "|${AZURE_SIGNING_CLIENT_ID}|${AZURE_SIGNING_CLIENT_SECRET}|${AZURE_SIGNING_TENANT_ID}|${AZURE_SIGNING_KEY_VAULT_URI}|" == *"||"* ]]; then \ if [[ "|${AZURE_SIGNING_CLIENT_ID}|${AZURE_SIGNING_CLIENT_SECRET}|${AZURE_SIGNING_TENANT_ID}|${AZURE_SIGNING_ACCOUNT_ENDPOINT}|${AZURE_SIGNING_ACCOUNT_NAME}|${AZURE_SIGNING_CERT_PROFILE_NAME}|" == *"||"* ]]; then \
echo "Can't sign windows binaries as required configuration not set: AZURE_SIGNING_CLIENT_ID, AZURE_SIGNING_CLIENT_SECRET, AZURE_SIGNING_TENANT_ID, AZURE_SIGNING_KEY_VAULT_URI"; \ echo "Can't sign windows binaries as required configuration not set: AZURE_SIGNING_CLIENT_ID, AZURE_SIGNING_CLIENT_SECRET, AZURE_SIGNING_TENANT_ID, AZURE_SIGNING_ACCOUNT_ENDPOINT, AZURE_SIGNING_ACCOUNT_NAME, AZURE_SIGNING_CERT_PROFILE_NAME"; \
echo "To rebuild with signing delete the unsigned windows exe file and rebuild with the fixed configuration"; \ echo "To rebuild with signing delete the unsigned windows exe file and rebuild with the fixed configuration"; \
if [[ "${CI}" == "true" ]]; then exit 1; fi; \ if [[ "${CI}" == "true" ]]; then exit 1; fi; \
else \ else \
@@ -284,12 +286,15 @@ sign-goreleaser-exe-%: bin/jsign-6.0.jar
--password "${AZURE_SIGNING_CLIENT_SECRET}" \ --password "${AZURE_SIGNING_CLIENT_SECRET}" \
--tenant "${AZURE_SIGNING_TENANT_ID}" \ --tenant "${AZURE_SIGNING_TENANT_ID}" \
--output none; \ --output none; \
ACCESS_TOKEN=$$(az account get-access-token --resource "https://vault.azure.net" | jq -r .accessToken); \ ACCESS_TOKEN=$$(az account get-access-token --resource "https://codesigning.azure.net" | jq -r .accessToken); \
java -jar bin/jsign-6.0.jar \ ENDPOINT_HOST="$${AZURE_SIGNING_ACCOUNT_ENDPOINT#https://}"; \
--storetype AZUREKEYVAULT \ ENDPOINT_HOST="$${ENDPOINT_HOST#http://}"; \
--keystore "PulumiCodeSigning" \ ENDPOINT_HOST="$${ENDPOINT_HOST%/}"; \
--url "${AZURE_SIGNING_KEY_VAULT_URI}" \ java -jar bin/jsign-7.4.jar \
--storetype TRUSTEDSIGNING \
--keystore "$${ENDPOINT_HOST}" \
--storepass "$${ACCESS_TOKEN}" \ --storepass "$${ACCESS_TOKEN}" \
--alias "${AZURE_SIGNING_ACCOUNT_NAME}/${AZURE_SIGNING_CERT_PROFILE_NAME}" \
$${file}.unsigned; \ $${file}.unsigned; \
mv $${file}.unsigned $${file}; \ mv $${file}.unsigned $${file}; \
az logout; \ az logout; \