I am trying to use a certificate from Azure Key Vault to sign my assemblies.
Until now I have copied the ceritficate from a local server into my build directory and signed with:
SignToolSettings settings = new SignToolSettings()
.SetFileDigestAlgorithm("SHA256")
.SetFile(CertFileNameAndPath)
.SetFiles(fileNames)
.SetPassword(password)
.SetTimestampServerDigestAlgorithm("SHA256")
.SetRfc3161TimestampServerUrl("http://timestamp.globalsign.com/tsa/r6advanced1");
SignToolTasks.SignTool(settings);
I am able to download the certificate from Azure Key Vault with this Nuke setup:
[KeyVaultSettings(
BaseUrlParameterName = nameof(KeyVaultBaseUrl),
ClientIdParameterName = nameof(KeyVaultClientId),
ClientSecretParameterName = nameof(KeyVaultClientSecret))]
readonly KeyVaultSettings KeyVaultSettings;
[KeyVault] readonly KeyVault KeyVault;
[Parameter] readonly string KeyVaultBaseUrl;
[Parameter] readonly string KeyVaultClientId;
[Parameter] readonly string KeyVaultClientSecret;
[KeyVaultCertificate("MyCertificateIdentifier")] KeyVaultCertificate Certificate;
The Certificate.Cer now contains 1276 bytes of 'something'.
I have tried to save that 1276 bytes as my certificate.pfx, but that does not work as a code signing certificate.
In Powershell I can do this:
$vaultName = "MyStorage"
$certificateName = "MyCertificate"
$pfxPath = ".\$certificateName.pfx"
$password = "MyPassword"
Connect-AzureRmAccount
$pfxSecret = Get-AzureKeyVaultSecret -VaultName $vaultName -Name $certificateName
$pfxUnprotectedBytes = [Convert]::FromBase64String($pfxSecret.SecretValueText)
$pfx = New-Object Security.Cryptography.X509Certificates.X509Certificate2
$pfx.Import($pfxUnprotectedBytes, $null, [Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)
$pfxProtectedBytes = $pfx.Export([Security.Cryptography.X509Certificates.X509ContentType]::Pkcs12, $password)
[IO.File]::WriteAllBytes($pfxPath, $pfxProtectedBytes)
So I tried to do the same to the Certificate received with Nuke (it does not look like base64 encoded, so I skipped the decoding):
var pfx = new System.Security.Cryptography.X509Certificates.X509Certificate2(Certificate.Cer, (string)null, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.Exportable);
var pfxProtectedBytes = pfx.Export(System.Security.Cryptography.X509Certificates.X509ContentType.Pkcs12, "MyPassword");
File.WriteAllBytes(CertFileNameAndPath, pfxProtectedBytes);
But still no luck.
The saving to a disk file is an option of course, but better yet would be if the SignToolSettings would accept a KeyVaultCertificate
directly.
My solution to this was really a workaround.
Instead of referencing the certificate with:
[KeyVaultCertificate("MyCertificateIdentifier")] KeyVaultCertificate Certificate;
I reference it as a string:
[KeyVaultSecret("MyCertificateIdentifier")] string CertificateBase64;
This string can be Base64 decoded and saved to a local file, that I can use with my standard SignTool.
N.B. There is a dedicated AzureSignTool, that works directly of Azure, so you don't need to download the certificate at all. Haven't tried that yet though.