azure-pipelinescode-signing

Signing with .pfx in DevOps Pipeline - Error MSB3325


I am trying to create a pipeline for an old WinForms application to build the solution. There are a number of projects which are signed with a .pfx file within said solution. Below are relevant lines from the project files.

<SignAssembly>true</SignAssembly> <AssemblyOriginatorKeyFile>MySigningKeyFile.pfx</AssemblyOriginatorKeyFile>

I am using the windows-latest image on a Microsoft hosted agent in my pipeline, and am getting the following error.

Error MSB3325: Cannot import the following key file: D:\a\1\s\MySigningKeyFile.pfx. The key file may be password protected. To correct this, try to import the certificate again or manually install the certificate to the Strong Name CSP with the following key container name: VS_KEY_73E817AD0FB98BD9

Note this ID changes each run of the pipeline and I am unable to find a way to determine this prior to the build to install it?

How can I resolve this issue?

I have tried installing the .pfx file using Powershell (the .pfx is in the repo) using the following script within a Powershell task.

 $securePassword = ConvertTo-SecureString -String "$(SnKeyPwd)" -Force -AsPlainText
 Import-PfxCertificate -FilePath "MySigningKeyFile.pfx" -CertStoreLocation "Cert:\LocalMachine\My" -Password $securePassword

This task is successful as I can see in the logs of the pipeline the thumbprint of the certificate.

I am also passing the following msbuild args to the VSBuild task

/p:SignAssembly=true /p:AssemblyOriginatorKeyFile=MySigningKeyFile.pfx /p:SignAssemblyTimestampUrl=$(TimestampUrl)

But this gives the same issue. If I remove the signing all together then the build completely fails as all the references become broken.

I am building in Release for Any CPU.


Solution

  • Since you use Microsoft-hosted agents to run the build job that you will get a fresh VM for each job in the pipeline. The key container name generated for the .pfx file would be different on different machines.

    As a workaround, you can use a self-hosted agent installed on yourself local machine (or VM). Then use the following command to install the certificate to the CSP with the key container name reported in the error message when you first run the build job on the self-hosted agent. Also see the documentation about "Error MSB3325".

    sn.exe -i <pfx_file> <key_container_name_from_error_message>
    

    If you want to still use Microsoft-hosted agents to run the build job, you can try to add a CMD task to run the following command line to generate and install the key container name for the .pfx file before the build task in the job.

    SnInstallPfx.exe <pfx_file> <pfx_password>
    

    This command is from the SnInstallPfx tool, and you may also need to use the command line to download the SnInstallPfx.exe before running it.


    Here is the YAML for the various tasks.

    Firstly, Powershell to download the tool. Alternatively you could use a command line task or potentially a Download NuGet Release task. You could also store it in your repo.

    task: PowerShell@2
    displayName: 'Download SnInstallPfx'
    inputs:
    targetType: 'inline'
    script: |
      $downloadUrl = "https://github.com/honzajscz/SnInstallPfx/releases/download/0.1.2-beta/SnInstallPfx.exe"
      $destinationPath = "$(System.DefaultWorkingDirectory)\SnInstallPfx.exe"
      Invoke-WebRequest -Uri $downloadUrl -OutFile $destinationPath
    

    and secondly, the command line tool to invoke the tool. Note I have the password coming from a variable group so am using the variable.

    task: CmdLine@2
    displayName: 'Install SN Cert'
    inputs:
    script: 'SnInstallPfx.exe MyCert.pfx $(SnKeyPwd)'
    workingDirectory: '$(System.DefaultWorkingDirectory)'