Azure Key Vault Code Signing: setup guide
This guide walks you through setting up Azure Key Vault Premium for Code Signing, from creating the vault to signing your first file with AzureSignTool. Works with both OV and EV Code Signing certificates from DigiCert and GlobalSign.
Prerequisites
- ✓ Azure subscription (any tier, including free)
- ✓ .NET 8 SDK or later (for AzureSignTool). Download from dotnet.microsoft.com ↗
- ✓ A Code Signing certificate from FairSSL (DigiCert or GlobalSign, OV or EV). See products below
Only DigiCert and GlobalSign certificates work with Azure Key Vault. Sectigo/Comodo certificates are not compatible because Azure Key Vault does not support their key attestation format.
Step 1: Create an Azure Key Vault (Premium)
Go to the Azure portal and create a new Key Vault resource. The critical setting is the pricing tier.
Key Vault settings
- Pricing tier:
Premium(required for HSM-backed keys. Standard cannot create RSA-HSM keys) - Region: Choose a region close to your signing infrastructure
- Permission model: Azure role-based access control (RBAC) (recommended)
- Soft-delete: Enabled (default, cannot be disabled)
- Purge protection: Recommended to enable (prevents accidental permanent deletion)
Azure CLI alternative
az keyvault create \ --name your-codesign-vault \ --resource-group your-resource-group \ --location westeurope \ --sku premium \ --enable-purge-protection true
Step 2: Configure RBAC permissions
Azure Key Vault uses a separate permission model for data plane operations. Having Owner or Contributor on the subscription does not automatically give you access to keys and certificates inside the vault.
Required roles for your user account (setup)
- ✓ Key Vault Administrator on the Key Vault resource
Assign via: Key Vault resource → Access control (IAM) → Add role assignment → Key Vault Administrator → select your user.
Required roles for AzureSignTool (signing)
The service principal or managed identity used by AzureSignTool needs these three roles:
- ✓ Key Vault Crypto User (perform signing operations)
- ✓ Key Vault Certificate User (read certificate metadata)
- ✓ Key Vault Secrets User (read certificate chain)
Azure CLI
# Assign Key Vault Administrator to yourself
az role assignment create \
--role "Key Vault Administrator" \
--assignee your-email@example.com \
--scope /subscriptions/{sub-id}/resourceGroups/{rg}/providers/Microsoft.KeyVault/vaults/{vault-name} Step 3: Generate key and CSR
In the Azure portal, navigate to your Key Vault → Certificates → Generate/Import.
Certificate creation settings
- Method: Generate
- Certificate Name: e.g.
codesign-2026(your internal reference) - Type of CA: Certificate issued by a non-integrated CA
- Subject:
CN=Your Company Name(must match the name registered with the CA)
Advanced Policy Configuration
- Extended Key Usages (EKUs):
1.3.6.1.5.5.7.3.3(Code Signing) - Key Type: RSA-HSM
- Key Size: 4096
- Content Type: PEM
- Exportable Private Key: No
- Enable Certificate Transparency: No (not required for Code Signing)
Click Create. The certificate will appear in the list with status "In progress". Click on it, then click Certificate Operation → Download CSR to get the CSR file.
The private key is generated inside the HSM and never leaves it. The CSR contains only the public key. This is what you submit to FairSSL/the CA for signing.
Step 4: Order certificate and submit CSR
- 1 Order a Code Signing certificate from FairSSL. Choose DigiCert or GlobalSign, OV or EV. Select "Azure Key Vault" as the delivery method. See products below.
- 2 Submit the CSR you downloaded from Azure Key Vault. Paste the PEM content when prompted during the order process.
- 3 Complete organisation validation. FairSSL performs the initial OV validation for GlobalSign in Danish, Swedish and English (often completed same day). The CA then performs an independent second check.
- 4 Receive the signed certificate from the CA. You will typically get several files: your Code Signing certificate, an intermediate certificate and a root certificate. Combine them into a single PEM file (see step 5).
Step 5: Import the signed certificate into Key Vault
We recommend combining all certificates into a single PEM file: your Code Signing certificate first, then the intermediate certificate, and finally the root certificate. This order ensures Azure Key Vault can validate the full certificate chain.
Create the combined PEM file
Open a text editor and paste the certificates in this order (or use the command below):
-----BEGIN CERTIFICATE----- (your Code Signing certificate) -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- (intermediate certificate from the CA) -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- (root certificate from the CA) -----END CERTIFICATE-----
Using the command line, you can concatenate the files directly:
cat codesign.pem intermediate.pem root.pem > fullchain.pem
Upload to Key Vault
Go back to your Key Vault → Certificates → click on the pending certificate → Certificate Operation → Merge Signed Request.
Upload the combined PEM file (fullchain.pem). Azure Key Vault will merge the certificate chain
with the private key that was generated in step 3.
After merging, the certificate status changes to "Completed" and is ready for signing.
Azure CLI alternative
az keyvault certificate pending merge \ --vault-name your-codesign-vault \ --name codesign-2026 \ --file fullchain.pem
Note the certificate name (e.g. codesign-2026). You will need this for AzureSignTool's
-kvc parameter.
Step 6: Create a service principal for signing
AzureSignTool authenticates to Key Vault using a service principal (Azure AD app registration) or a managed identity. For CI/CD pipelines on non-Azure infrastructure, use a service principal.
Create the app registration
- Go to Azure Active Directory → App registrations → New registration
- Name it something descriptive (e.g. "CodeSign-Pipeline")
- Note the Application (client) ID and Directory (tenant) ID
- Go to Certificates & secrets → New client secret → create a secret and note the value
Assign Key Vault roles to the service principal
Go to your Key Vault → Access control (IAM) → Add role assignment. Assign all three roles to the service principal:
- Key Vault Crypto User
- Key Vault Certificate User
- Key Vault Secrets User
Azure CLI
# Create app registration
az ad app create --display-name "CodeSign-Pipeline"
# Create service principal
az ad sp create --id {app-id}
# Create client secret
az ad app credential reset --id {app-id} --years 2
# Assign roles (repeat for each role)
az role assignment create \
--role "Key Vault Crypto User" \
--assignee {service-principal-id} \
--scope /subscriptions/{sub-id}/resourceGroups/{rg}/providers/Microsoft.KeyVault/vaults/{vault-name} Store the client secret securely. In CI/CD pipelines, use secret variables or a vault. Never commit secrets to source control.
Step 7: Install AzureSignTool
AzureSignTool ↗ is a free, open-source drop-in replacement for signtool.exe that signs directly from Azure Key Vault.
dotnet tool install --global AzureSignTool
Requires .NET 8 SDK or later. After installation, AzureSignTool is available as a global command.
Alternative: Jsign (cross-platform)
Jsign ↗ is a Java-based signing tool that also supports Azure Key Vault. Jsign runs on Windows, macOS and Linux, and can sign .exe, .msi, .dll, PowerShell, Office macros and Java/Android apps (as a bridge to jarsigner).
jsign --storetype AZUREKEYVAULT \ --storepass "YOUR_CLIENT_ID|YOUR_CLIENT_SECRET|YOUR_TENANT_ID" \ --keystore your-codesign-vault \ --alias codesign-2026 \ --tsaurl http://timestamp.digicert.com \ MyApplication.exe
Jsign is a good alternative if you do not have .NET installed, or if you sign from macOS/Linux.
Step 8: Sign your first file
AzureSignTool sign \ -kvu https://your-codesign-vault.vault.azure.net \ -kvc codesign-2026 \ -kvt YOUR_TENANT_ID \ -kvi YOUR_CLIENT_ID \ -kvs YOUR_CLIENT_SECRET \ -fd sha256 \ -tr http://timestamp.digicert.com \ -td sha256 \ "MyApplication.exe"
Parameter reference
-kvuKey Vault URL (found on Key Vault overview page)-kvcCertificate name in Key Vault (the name you chose in step 3)-kvtAzure tenant (directory) ID-kviApplication (client) ID of your service principal-kvsClient secret value-fdFile digest algorithm (always usesha256)-trRFC 3161 timestamp server URL-tdTimestamp digest algorithm (always usesha256)
Verify the signature
signtool verify /pa /v "MyApplication.exe"
The output should show "Successfully verified" with your company name and a valid timestamp.
CI/CD integration
AzureSignTool runs in any CI/CD pipeline that supports .NET. Store your Key Vault credentials as secret pipeline variables.
Azure DevOps (YAML)
- task: DotNetCoreCLI@2
displayName: 'Install AzureSignTool'
inputs:
command: 'custom'
custom: 'tool'
arguments: 'install --global AzureSignTool'
- script: |
AzureSignTool sign \
-kvu $(KeyVaultUrl) \
-kvc $(CertificateName) \
-kvt $(TenantId) \
-kvi $(ClientId) \
-kvs $(ClientSecret) \
-fd sha256 \
-tr http://timestamp.digicert.com \
-td sha256 \
"$(Build.ArtifactStagingDirectory)\**\*.exe"
displayName: 'Sign executables' GitHub Actions
- name: Install AzureSignTool
run: dotnet tool install --global AzureSignTool
- name: Sign executables
run: |
AzureSignTool sign \
-kvu ${{ secrets.KEY_VAULT_URL }} \
-kvc ${{ secrets.CERT_NAME }} \
-kvt ${{ secrets.AZURE_TENANT_ID }} \
-kvi ${{ secrets.AZURE_CLIENT_ID }} \
-kvs ${{ secrets.AZURE_CLIENT_SECRET }} \
-fd sha256 \
-tr http://timestamp.digicert.com \
-td sha256 \
"output/*.exe" GitLab CI
sign:
image: mcr.microsoft.com/dotnet/sdk:8.0
script:
- dotnet tool install --global AzureSignTool
- export PATH="$PATH:$HOME/.dotnet/tools"
- AzureSignTool sign
-kvu $KEY_VAULT_URL
-kvc $CERT_NAME
-kvt $AZURE_TENANT_ID
-kvi $AZURE_CLIENT_ID
-kvs $AZURE_CLIENT_SECRET
-fd sha256
-tr http://timestamp.digicert.com
-td sha256
"output/*.exe" Managed identity: On Azure-hosted agents, replace -kvt, -kvi and -kvs
with -kvm (use managed identity). This eliminates the need for client secrets entirely.
Timestamping
Always include an RFC 3161 timestamp when signing. This ensures your signatures remain valid after the certificate expires. Code Signing certificates have a maximum validity of 459 days, but timestamped signatures are valid indefinitely.
Recommended timestamp servers
http://timestamp.digicert.com(recommended, most stable)http://timestamp.globalsign.com/tsa/r6advanced1
Troubleshooting
"Forbidden" or "Access denied" when signing
The service principal is missing Key Vault RBAC roles. Verify that all three roles are assigned: Key Vault Crypto User, Key Vault Certificate User, and Key Vault Secrets User. RBAC role assignments can take up to 10 minutes to propagate.
"SKU does not support HSM-backed keys"
You created a Standard tier Key Vault. You need Premium. Create a new Key Vault with Premium SKU, or upgrade the existing vault (only possible via CLI).
"Certificate operation is not complete"
You have not yet merged the signed certificate from the CA. Go to Key Vault → Certificates → click the pending certificate → Certificate Operation → Merge Signed Request.
Timestamp fails
Try the alternative timestamp server. Also verify that the signing machine has internet access and can reach the timestamp URL on port 80. Some firewalls block outbound HTTP.
Code Signing certificates for Azure Key Vault
OV Code Signing
DigiCert CodeSign OV
DigiCert OV Code Signing. Works with Azure Key Vault.
GlobalSign CodeSign
GlobalSign OV Code Signing. Works with Azure Key Vault.
EV Code Signing
Frequently asked questions
Find answers to the most common questions about SSL certificates and FairSSL.
Ready to sign from Azure Key Vault?
Create a free account and issue your first certificate in under 10 minutes.