This project aims to make it easier to integrate secure code signing into a CI pipeline by using cloud-based hardware security module(HSM)-protected keys. This project is part of the .NET Foundation and operates under their code of conduct. It is licensed under MIT (an OSI approved license).
Given an initial file path or glob pattern, this tool recursively searches directories and containers to find signable files and containers. For each signable artifact, the tool uses an implementation of System.Security.Cryptography.RSA
that delegates the signing operation to Azure Key Vault. The tool computes a digest (or hash) of the to-be-signed content and submits the digest --- not the original content --- to Azure Key Vault for digest signing. The returned raw signature value is then incorporated in whatever signature format is appropriate for the file type. Signable content is not sent to Azure Key Vault.
While the current version is limited to RSA and Azure Key Vault, it is desirable to support ECDSA and other cloud providers in the future.
.msi
,.msp
,.msm
,.cab
,.dll
,.exe
,.appx
,.appxbundle
,.msix
,.msixbundle
,.sys
,.vxd
,.ps1
,.psm1
, and any portable executable (PE) file (via AzureSignTool).vsix
via OpenOpcSignTool- ClickOnce
.application
and.vsto
(viaMage
). Special instructions below. .nupkg
via NuGetKeyVaultSignTool
ClickOnce files can be signed with this tool, but it requires an extra step -- you must zip up the publish
directory containing the setup.exe
, foo.application
or foo.vsto
files along with the Application Files
directory. The Application Files
must only have a single subdirectory (version you want to sign). Zip these and then rename the extension to .clickonce
before submitting to the tool. Once done, you can extract the signed files wherever you'd like for publication. If the name
parameter is supplied, it's used in the Mage
name to update the Product
in the manifests. If the descriptionUrl
parameter is supplied, it's used as the supportUrl
in the manifests.
You should also use the filter
parameter with the file list to sign, something like this:
**/ProjectAddIn1.*
**/setup.exe
- Create a ServicePrincipal with minimum permissions. Note that you do not need to assign any subscription-level roles to this identity. Only access to Key Vault is required.
- Follow Best practices for using Azure Key Vault. The Premium SKU is required for code signing certificates to meet key storage requirements.
- Configure an Azure Key Vault access policy for your signing account to have minimal permissions:
- Key permissions
- Cryptographic Operations
- Sign
- Cryptographic Operations
- Certificate permissions
- Certificate Management Operations
- Get
- Certificate Management Operations
- Key permissions
- Isolate signing operations in a separate leg of your build pipeline.
- Ensure that this CLI and all files to be signed are in a directory under your control.
- Execute this CLI as a standard user. Elevation is not required.
- Use OIDC authentication from your GitHub Action to Azure.
Code signing is a complex process that may involve multiple signing formats and artifact types. Some artifacts are containers that contain other signable file types. For example, NuGet Packages (.nupkg
) frequently contain .dll
files. The signing tool will sign all files inside-out, starting with the most nested files and then the outer files, ensuring everything is signed in the correct order.
Signing .exe
/.dll
files, and other Authenticode file types is only possible on Windows at this time. The recommended solution is to build on one agent and sign on another using jobs or stages where the signing steps run on Windows. Running code signing on a separate stage to ensure secrets aren't exposed to the build stage.
The following information is needed for the signing build:
Tenant Id
Azure AD tenantClient Id
/Application Id
ServicePrincipal identifierKey Vault Url
Url to Key Vault. Must be a Premium Sku for EV code signing certificates and all certificates issued after June 2023Certificate Id
Id of the certificate in Key Vault.Client Secret
for Azure DevOps PipelinesSubscription Id
for GitHub Actions
Code signing certificates must use the RSA-HSM
key type to ensure the private keys are stored in a FIPS 140-2 compliant manner. While you can import a certificate from a PFX file, if available, the most secure option is to create a new Certificate Signing Request to provide to your certificate authority, and then merge in the public certificate they issue. Detailed steps are available here.
If you've been using the legacy code signing service, using SignClient.exe
to upload files for signing, you can use your existing certificate and Key Vault with this new tool. You will need to create a new ServicePrincipal and assign it permissions as described above.