2

We have developed for the client Microsoft Office extension, and they do require to be code signed.

For development I have made a .pfx in VS -> Project properties -> Signing -> Create Test Certificate. Put empty password, dumped .pfx into source control and it was building for the whole company while developing.

For the release of the addon, things are different, we need to sign an extension with the clients .pfx and they want to add a step in the Azure DevOps build a pipeline to do it automatically. The thing is they can't use cloud solutions, so as I understand Azure Key Vault is out of the picture. They do have a local trusted machine that we could put their .pfx for signing.

I couldn't find a way how to do a signing in Azure Pipelines, that would not involve Azure Key Vault, or Azure Secure Files but I would expect there to be a mechanism for this as it seems like a quite common thing to do.

What is the preferred solution to .pfx sign code using local machine in Azure Devops Pipelines?

Matas Vaitkevicius
  • 58,075
  • 31
  • 238
  • 265

1 Answers1

0

We ended up with following:

Added .pfx on local build machine.

Added hidden variable to Azure build pipeline pfxPassword

enter image description here

enter image description here

Then added following build steps tp Azure build pipeline:

trigger:
- main

pool:
  name: 'XXX Build Pool'

variables:
  solution: '**/*.sln'
  buildPlatform: 'Any CPU'
  buildConfiguration: 'Release'
  #change to actual directory where signtool is.
  pathToSignTool: "\"C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.19041.0\\x64\\signtool.exe\"" 
  pathToPfx: "C:\\XXX\\Install\\XXX_Applications.pfx" 
  pathToBuildDirectory: "\\XXXYYY\\bin\\Release\\" 
  pathToMageTool: "\"C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v10.0A\\bin\\NETFX 4.8 Tools\\mage.exe\""
  pathToContinousDeployment: "C:\\ContinousDeployment\\YYY\\"

name: $(MajorVersion).$(MinorVersion).$(date:yy)$(DayOfYear)$(rev:.r)
steps:
- task: Assembly-Info-NetFramework@2
  inputs:
    Path: '$(Build.SourcesDirectory)'
    FileNames: |
      **\AssemblyInfo.cs
    InsertAttributes: true
    FileEncoding: 'auto'
    WriteBOM: false
    VersionNumber: '$(Build.BuildNumber)'
    FileVersionNumber: '$(Build.BuildNumber)'
    InformationalVersion: '$(Build.BuildNumber)'
    LogLevel: 'verbose'
    FailOnWarning: false
    DisableTelemetry: false

- task: VSBuild@1
  inputs:
    solution: '$(solution)'
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'

- task: VSTest@2
  inputs:
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'


- script: 
      $(pathToMageTool) -s $(Build.Repository.LocalPath)$(pathToBuildDirectory)XXXYYY.vsto -cf $(pathToPfx) -pwd %MAPPEDPASS%
  env:
    MAPPEDPASS: $(pfxPassword)

- script: 
      $(pathToMageTool) -s $(Build.Repository.LocalPath)$(pathToBuildDirectory)XXXYYY.dll.manifest -cf $(pathToPfx) -pwd %MAPPEDPASS%
  env:
    MAPPEDPASS: $(pfxPassword)

- script: 
      $(pathToSignTool) sign /f $(pathToPfx) /p %MAPPEDPASS% $(Build.Repository.LocalPath)$(pathToBuildDirectory)XXXYYY.dll
  env:
    MAPPEDPASS: $(pfxPassword)

- task: CopyFiles@2
  inputs:
    SourceFolder: '$(Build.Repository.LocalPath)$(pathToBuildDirectory)'
    Contents: '**'
    TargetFolder: '$(pathToContinousDeployment)'
    OverWrite: true
Matas Vaitkevicius
  • 58,075
  • 31
  • 238
  • 265