Nuke-build sign assemblies with Certificate from Azure Key Vault

301 Views Asked by At

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.

1

There are 1 best solutions below

0
On BEST ANSWER

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.