From b0c5918c7cb9f6438feeb19211416af32401679e Mon Sep 17 00:00:00 2001 From: Keith Mosher Date: Thu, 9 Apr 2026 19:52:15 -0400 Subject: [PATCH] Migrate Windows code signing to Azure Trusted Signing (#811) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 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 --- Makefile | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 0fdd564..c6f9e2a 100644 --- a/Makefile +++ b/Makefile @@ -250,30 +250,32 @@ docs: $(shell find docs/yaml -type f) $(shell find ./provider/internal/embed -na go generate docs/generate.go @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_SECRET ?= AZURE_SIGNING_TENANT_ID ?= -AZURE_SIGNING_KEY_VAULT_URI ?= +AZURE_SIGNING_ACCOUNT_ENDPOINT ?= +AZURE_SIGNING_ACCOUNT_NAME ?= +AZURE_SIGNING_CERT_PROFILE_NAME ?= SKIP_SIGNING ?= -bin/jsign-6.0.jar: +bin/jsign-7.4.jar: @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-arm64: GORELEASER_ARCH := arm64 # Set the shell to bash to allow for the use of bash syntax. 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. @# 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. @set -e; \ if [[ "${SKIP_SIGNING}" != "true" ]]; then \ - if [[ "|${AZURE_SIGNING_CLIENT_ID}|${AZURE_SIGNING_CLIENT_SECRET}|${AZURE_SIGNING_TENANT_ID}|${AZURE_SIGNING_KEY_VAULT_URI}|" == *"||"* ]]; 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"; \ + 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_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"; \ if [[ "${CI}" == "true" ]]; then exit 1; fi; \ else \ @@ -284,12 +286,15 @@ sign-goreleaser-exe-%: bin/jsign-6.0.jar --password "${AZURE_SIGNING_CLIENT_SECRET}" \ --tenant "${AZURE_SIGNING_TENANT_ID}" \ --output none; \ - ACCESS_TOKEN=$$(az account get-access-token --resource "https://vault.azure.net" | jq -r .accessToken); \ - java -jar bin/jsign-6.0.jar \ - --storetype AZUREKEYVAULT \ - --keystore "PulumiCodeSigning" \ - --url "${AZURE_SIGNING_KEY_VAULT_URI}" \ + ACCESS_TOKEN=$$(az account get-access-token --resource "https://codesigning.azure.net" | jq -r .accessToken); \ + ENDPOINT_HOST="$${AZURE_SIGNING_ACCOUNT_ENDPOINT#https://}"; \ + ENDPOINT_HOST="$${ENDPOINT_HOST#http://}"; \ + ENDPOINT_HOST="$${ENDPOINT_HOST%/}"; \ + java -jar bin/jsign-7.4.jar \ + --storetype TRUSTEDSIGNING \ + --keystore "$${ENDPOINT_HOST}" \ --storepass "$${ACCESS_TOKEN}" \ + --alias "${AZURE_SIGNING_ACCOUNT_NAME}/${AZURE_SIGNING_CERT_PROFILE_NAME}" \ $${file}.unsigned; \ mv $${file}.unsigned $${file}; \ az logout; \