Skip to content

ci: sign nupkgs against Azure Key Vault using NuGetKeyVaultSignTool#1274

Merged
anaiberta merged 5 commits into
masterfrom
feat/azure-keyvault-signing
Apr 27, 2026
Merged

ci: sign nupkgs against Azure Key Vault using NuGetKeyVaultSignTool#1274
anaiberta merged 5 commits into
masterfrom
feat/azure-keyvault-signing

Conversation

@anaiberta

@anaiberta anaiberta commented Apr 25, 2026

Copy link
Copy Markdown
Contributor

Code signing requirements now mandate HSM-compatible certificate storage: local PFX files are no longer viable. The certificate has moved to an Azure Key Vault, so the workflow needs a tool that can sign nupkgs using a remote key — dotnet nuget sign only supports local PFX paths.

Replace the PFX-based dotnet nuget sign step with NuGetKeyVaultSignTool 3.2.3, pinned via a new .config/dotnet-tools.json manifest. The workflow restores the tool, acquires an access token for https://vault.azure.net through a client_credentials grant against Entra ID, and signs every produced nupkg using the remote certificate.

Required GitHub configuration:

  • vars.AZURE_CODE_SIGNING_VAULT_URL
  • vars.AZURE_CODE_SIGNING_CERT_NAME
  • vars.AZURE_CODE_SIGNING_TIMESTAMP_SERVER
  • vars.AZURE_CODE_SIGNING_TENANT
  • vars.AZURE_CODE_SIGNING_APP_ID
  • secrets.AZURE_CODE_SIGNING_APP_PASSWORD

Once validated, the legacy secrets can be removed:

  • secrets.CODE_SIGN_CERTIFICATE_BASE64
  • secrets.CODE_SIGN_CERTIFICATE_PASSWORD
  • secrets.CODE_SIGN_CERTIFICATE_TIMESTAMPER_URL

Issue:208489

Code signing requirements now mandate HSM-compatible certificate storage:
local PFX files are no longer viable. The certificate has moved to an
Azure Key Vault, so the workflow needs a tool that can sign nupkgs using
a remote key — `dotnet nuget sign` only supports local PFX paths.

Replace the PFX-based `dotnet nuget sign` step with NuGetKeyVaultSignTool
3.2.3, pinned via a new .config/dotnet-tools.json manifest. The workflow
restores the tool, acquires an access token for https://vault.azure.net
through a client_credentials grant against Entra ID, and signs every
produced nupkg using the remote certificate.

Required GitHub configuration:
- vars.AZURE_CODE_SIGNING_VAULT_URL
- vars.AZURE_CODE_SIGNING_CERT_NAME
- vars.AZURE_CODE_SIGNING_TIMESTAMP_SERVER
- vars.AZURE_CODE_SIGNING_TENANT
- vars.AZURE_CODE_SIGNING_APP_ID
- secrets.AZURE_CODE_SIGNING_APP_PASSWORD

Once validated, the legacy secrets can be removed:
- secrets.CODE_SIGN_CERTIFICATE_BASE64
- secrets.CODE_SIGN_CERTIFICATE_PASSWORD
- secrets.CODE_SIGN_CERTIFICATE_TIMESTAMPER_URL
@anaiberta anaiberta temporarily deployed to external-storage-tests April 25, 2026 19:43 — with GitHub Actions Inactive
@anaiberta anaiberta temporarily deployed to kafka-integration-tests April 25, 2026 19:43 — with GitHub Actions Inactive
Updated environment variable references to use secrets for Azure code signing.
@anaiberta anaiberta temporarily deployed to external-storage-tests April 25, 2026 20:01 — with GitHub Actions Inactive
@anaiberta anaiberta temporarily deployed to kafka-integration-tests April 25, 2026 20:01 — with GitHub Actions Inactive
Add a new "Sign assemblies" step between Test and Pack so that the dlls
shipped inside each .nupkg carry an Authenticode signature, not just the
package container. Pin AzureSignTool 6.0.0 in the local tool manifest
alongside NuGetKeyVaultSignTool.

Discovery filter: only sign dlls whose filename matches a .csproj under
dotnet/src/. This intentionally skips third-party dlls that NuGet copies
into bin/ so we don't overwrite their authors' original signatures.

Both signing steps temporarily drop the SHOULD_DEPLOY gate so the new
configuration can be exercised on this branch before merging. The
SHOULD_DEPLOY check stays on the publish steps so feeds aren't polluted
during testing. The TODOs in the workflow mark where the gate must be
put back before this lands on master.
@anaiberta anaiberta temporarily deployed to kafka-integration-tests April 25, 2026 20:45 — with GitHub Actions Inactive
@anaiberta anaiberta temporarily deployed to external-storage-tests April 25, 2026 20:45 — with GitHub Actions Inactive
Two issues hit the first run with 817 dlls landing on AzureSignTool:

1. The filter matched any dll across all bin/$Configuration trees whose name
   coincided with any csproj. Project A that references B will copy B.dll
   into A's bin folder, so B.dll showed up multiple times. Restrict the
   scan to each project's own bin/$Configuration tree (-Recurse covers
   target framework subdirectories) so each project signs only its own
   output.

2. Even after deduplication the path list can easily exceed Windows's ~32k
   command line limit (CreateProcess fails with "filename or extension is
   too long"). AzureSignTool's -ifl flag takes a file containing newline-
   separated paths, sidestepping the limit entirely. Write the discovered
   list to $RUNNER_TEMP/files-to-sign.txt and pass that.
@anaiberta anaiberta temporarily deployed to external-storage-tests April 25, 2026 20:57 — with GitHub Actions Inactive
@anaiberta anaiberta temporarily deployed to kafka-integration-tests April 25, 2026 20:57 — with GitHub Actions Inactive
Validated assembly signing on this branch but rolling it back to keep the
signing change tight: just the nupkg signing migration. This way the patch
stays small and clean to backport to other branches.

- Remove the "Sign assemblies" step from Build.yml
- Drop azuresigntool from .config/dotnet-tools.json (only NuGetKeyVaultSignTool stays)
- Restore the SHOULD_DEPLOY gate on "Sign packages"
@anaiberta anaiberta temporarily deployed to kafka-integration-tests April 25, 2026 22:04 — with GitHub Actions Inactive
@anaiberta anaiberta temporarily deployed to external-storage-tests April 25, 2026 22:04 — with GitHub Actions Inactive
@anaiberta anaiberta marked this pull request as ready for review April 25, 2026 22:18
@anaiberta anaiberta requested a review from a team April 25, 2026 22:18
@genexusbot

Copy link
Copy Markdown
Contributor
Cherry pick to beta success

@anaiberta anaiberta merged commit 7700101 into master Apr 27, 2026
14 checks passed
@anaiberta anaiberta deleted the feat/azure-keyvault-signing branch April 27, 2026 15:27
claudiamurialdo pushed a commit that referenced this pull request May 8, 2026
…1274)

Code signing requirements now mandate HSM-compatible certificate storage: local PFX files are no longer viable. The certificate has moved to an Azure Key Vault, so the workflow needs a tool that can sign nupkgs using a remote key — `dotnet nuget sign` only supports local PFX paths.

Issue:208489
(cherry picked from commit 7700101)
claudiamurialdo pushed a commit that referenced this pull request May 25, 2026
…1274)

Code signing requirements now mandate HSM-compatible certificate storage: local PFX files are no longer viable. The certificate has moved to an Azure Key Vault, so the workflow needs a tool that can sign nupkgs using a remote key — `dotnet nuget sign` only supports local PFX paths.

Issue:208489
(cherry picked from commit 7700101)
claudiamurialdo pushed a commit that referenced this pull request May 29, 2026
…1274)

Code signing requirements now mandate HSM-compatible certificate storage: local PFX files are no longer viable. The certificate has moved to an Azure Key Vault, so the workflow needs a tool that can sign nupkgs using a remote key — `dotnet nuget sign` only supports local PFX paths.

Issue:208489
claudiamurialdo added a commit that referenced this pull request Jun 3, 2026
…1274) (#1290)

Code signing requirements now mandate HSM-compatible certificate storage: local PFX files are no longer viable. The certificate has moved to an Azure Key Vault, so the workflow needs a tool that can sign nupkgs using a remote key — `dotnet nuget sign` only supports local PFX paths.

Issue:208489

Co-authored-by: Ana Berta <31777352+anaiberta@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants