Skip to content
| Marketplace
Sign in
Azure DevOps>Azure Pipelines>Trusted Signing
Trusted Signing

Trusted Signing

Microsoft

microsoft.com
|
1,015 installs
| (1) | Free
This task enables users to sign their files with the Trusted Signing service.
Get it free

Trusted Signing

The Trusted Signing Task allows you to digitally sign your files using a Trusted Signing certificate during an Azure Pipelines run.

Runner Requirements

This Task can only be executed on Windows runners. It is supported by the following GitHub hosted runners:

  • windows-2022
  • windows-2019

It is also possible to use self-hosted runners with the following requirements:

  • Windows 7+
  • PowerShell 5.1+
  • .NET runtime 6.0+

Example

trigger:
- main

pool:
  vmImage: 'windows-latest'

steps:
- task: UseDotNet@2
  displayName: Install .NET
  inputs:
    packageType: 'sdk'
    version: '8.0.x'

- task: Bash@3
  displayName: Install MAUI
  inputs:
    targetType: 'inline'
    script: |
      dotnet nuget locals all --clear 
      dotnet workload install maui --source https://aka.ms/dotnet6/nuget/index.json --source https://api.nuget.org/v3/index.json
      dotnet workload install android ios maccatalyst tvos macos maui wasm-tools --source https://aka.ms/dotnet6/nuget/index.json --source https://api.nuget.org/v3/index.json

- task: Bash@3
  displayName: Build MAUI App
  inputs:
    targetType: 'inline'
    script: |
      cd MauiApp1/MauiApp1
      dotnet publish -f net8.0-windows10.0.19041.0 -c Release

- task: TrustedSigning@0
  displayName: Sign with Trusted Signing
  inputs:
    AzureTenantID: '$(tenant-id)'
    AzureClientID: '$(client-id)'
    AzureClientSecret: '$(client-secret)'
    Endpoint: 'https://eus.codesigning.azure.net/'
    TrustedSigningAccountName: 'my-codesigning-account'
    CertificateProfileName: 'my-certificate-profile'
    FilesFolder: '$(Build.SourcesDirectory)/MauiApp1/MauiApp1/bin/Release/net8.0-windows10.0.19041.0/win10-x64/AppPackages/'
    FilesFolderFilter: 'msix'
    FilesFolderRecurse: true
    FilesFolderDepth: 1
    FileDigest: 'SHA256'
    TimestampRfc3161: 'http://timestamp.acs.microsoft.com'
    TimestampDigest: 'SHA256'

Support

For support, head over to Q & A. Please review Common error codes and mitigations before asking a question.

Authentication

Behind the scenes, the Task uses DefaultAzureCredential as the primary method of authentication to Azure. The EnvironmentCredential variables are exposed as inputs and then set to Task-scoped environment variables. Each credential type supported by DefaultAzureCredential can be disabled using the Task inputs.

Trusted Signing Certificate Profile Signer role is required to successfully sign with Trusted Signing

OpenID Connect

It is reccomended to use OpenID Connect with Federated Credentials for authentication with the Trusted Signing service. Follow the steps below to authenticate with Open ID Connect:

  1. Create a Microsoft Entra application and service principal
  2. Add federated credentials
  3. Create a service connection in Azure DevOps authenticated in Microsoft Entra ID using federated credentials
  4. Assign the Trusted Signing Certificate Profile Signer role to your service principal.
    1. Open your Trusted Signing Account in the Azure portal.
      1. Note: You can assign the role from your Resource Group or Subscription if you have multiple Trusted Signing accounts.
    2. Navigate to the Access Control (IAM) tab.
    3. Click 'Add role assignment'.
    4. Select 'Trusted Signing Certificate Profile Signer'.
    5. Next.
    6. Assign access to your 'User, group, or service principal' or 'Managed identity'.
      1. Note: You will need to search for, and select, the service principal you created above. Only users will be listed by default.
    7. Review + assign.
  5. Adapt the following yaml to your pipeline:
    steps:
    - task: AzureCLI@2
      displayName: 'Azure CLI'
      inputs:
        azureSubscription: '<name of service connection here>'
        scriptType: 'bash'
        scriptLocation: 'inlineScript'
        inlineScript: |
          echo "##vso[task.setvariable variable=ARM_CLIENT_ID;issecret=true]$servicePrincipalId" 
          echo "##vso[task.setvariable variable=ARM_ID_TOKEN;issecret=true]$idToken"
          echo "##vso[task.setvariable variable=ARM_TENANT_ID;issecret=true]$tenantId"
        addSpnToEnvironment: true
    
    - bash: |
        az login --service-principal -u $(ARM_CLIENT_ID) --tenant $(ARM_TENANT_ID) --allow-no-subscriptions --federated-token $(ARM_ID_TOKEN)
      displayName: 'Azure Login'
    
    - task: TrustedSigning@0
      displayName: Sign with Trusted Signing
      inputs:
        ...
        ExcludeEnvironmentCredential: true
        ExcludeWorkloadIdentityCredential: true
        ExcludeManagedIdentityCredential: true
        ExcludeSharedTokenCacheCredential: true
        ExcludeVisualStudioCredential: true
        ExcludeVisualStudioCodeCredential: true
        ExcludeAzureCliCredential: false
        ExcludeAzurePowershellCredential: true
        ExcludeAzureDeveloperCliCredential: true
        ExcludeInteractiveBrowserCredential: true
    

File Specification

Files List

This strategy allows you to specify a comma or newline separated list of files to be signed.

# A comma or newline separated list of absolute paths to the files being signed. Can be combined with the FilesFolder and FileCatalog inputs.
Files: '$(Build.SourcesDirectory)\files\app.dll,$(Build.SourcesDirectory)\files\app.exe'

Files: |
  $(Build.SourcesDirectory)\files\app.dll
  $(Build.SourcesDirectory)\files\app.exe

Files Folder

This strategy allows you to specify a folder that contains all the files you want signed. There are options available for narrowing the focus as well. For example, you can use the FilesFolderFilter input to specify that you only want exe files to be signed. See about_Wildcards for more information on using wildcards with the FilesFolderFilter input.

# The folder containing files to be signed. Can be combined with the Files and FileCatalog inputs.
FilesFolder: '$(Build.SourcesDirectory)\App\App\bin\Release\net8.0-windows'

# A comma separated list of file extensions that determines which types of files will be signed in the folder specified by the FilesFolder input. Any file type not included in this list will not be signed. If this input is not used, all files in the folder will be signed. Supports wildcards for matching multiple file names with a pattern.
FilesFolderFilter: 'dll,exe,msix'

# A boolean value (true/false) that indicates if the folder specified by the FilesFolder input should be searched recursively. The default value is false.
FilesFolderRecurse: true

# An integer value that indicates the depth of the recursive search toggled by the FilesFolderRecurse input. By default there is no limit to the depth of the search.
FilesFolderDepth: 2

Given the following directory structure:

C:.
└───files
        System.dll
        Foo.Bar.Core.dll
        Foo.Bar.Utilities.dll
        Foo.Bar.exe
        LICENSE.md

Here is an example of inputs that can be used to specify that only the Foo.Bar.* files are signed:

FilesFolder: '$(Build.SourcesDirectory)\files'
FilesFolderFilter: 'Foo.Bar.*.dll,*.exe'
FilesFolderRecurse: false
FilesFolderDepth: 1

Files Catalog

This strategy allows you to specify a precise list of files to be signed.

# A file containing a list of relative paths to the files being signed. The paths should be relative to the location of the catalog file. Each file path should be on a separate line. Can be combined with the FilesFolder input.
FilesCatalog: '$(Build.SourcesDirectory)\catalog.txt'

Given the following directory structure:

C:.
│   catalog.txt
│
└───files
        System.dll
        Foo.Bar.Core.dll
        Foo.Bar.Utilities.dll
        Foo.Bar.exe
        LICENSE.md

Here is an example of a catalog.txt file that can be used to specify that only the Foo.Bar.* files are signed:

./files/Foo.Bar.Core.dll
./files/Foo.Bar.Utilities.dll
./files/Foo.Bar.exe

Best Practices

ClickOnce

Generally you will want to sign an entire package and all its contents i.e. the deployment manifest (.application or .vsto), application manifest (.exe.manifest or .dll.manifest) and the underlying .exe and .dll files themselves. To do this, ensure that the entire contents of the package are available (i.e. the whole publish folder from your build) and pass the deployment manifest (.application or .vsto) as the file to sign - the rest of the files will be detected and signed in the proper order automatically.

In the example below, it is only necessary to pass ClickOnceApp.application and setup.exe to the Trusted Signing Task. The remaining "Application Files" will be signed automatically.

C:\TEST\ASSETS\SAMPLE-FILES\CLICKONCE
│   ClickOnceApp.application
│   setup.exe
└───Application Files
    └───ClickOnceApp_1_0_0_0
            ClickOnceApp.deps.json.deploy
            ClickOnceApp.dll.deploy
            ClickOnceApp.dll.manifest
            ClickOnceApp.exe.deploy
            ClickOnceApp.runtimeconfig.json.deploy
            Launcher.exe.deploy

The following inputs are ignored when signing ClickOnce files:

  • AppendSignature
  • GenerateDigestPath
  • GenerateDigestXml
  • IngestDigestPath
  • SignDigest
  • GeneratePageHashes
  • SuppressPageHashes
  • GeneratePkcs7
  • Pkcs7Options
  • Pkcs7Oid
  • EnhancedKeyUsage

Timestamping

The files must be signed with timestamping enabled in order for the signatures to be valid for longer than 3 days. It is recommended to use the Trusted Signing timestamp server:

TimestampRfc3161: 'http://timestamp.acs.microsoft.com'
TimestampDigest: 'SHA256'

Authentication

This Task performs authentication using DefaultAzureCredential which attempts a series of authentication methods in order. If one method fails, it will attempt the next one until authentication is successful.

Each authentication method can be disabled individually so that no time is wasted attempting to authenticate with methods that will never pass.

For example, when authenticating with EnvironmentCredential specifically, disable the other credentials with the following inputs:

ExcludeEnvironmentCredential: false
ExcludeWorkloadIdentityCredential: true
ExcludeManagedIdentityCredential: true
ExcludeSharedTokenCacheCredential: true
ExcludeVisualStudioCredential: true
ExcludeVisualStudioCodeCredential: true
ExcludeAzureCliCredential: true
ExcludeAzurePowershellCredential: true
ExcludeAzureDeveloperCliCredential: true
ExcludeInteractiveBrowserCredential: true

This can make the Task fail faster if for some reason the EnvironmentCredential fails. Similarly, if using for example an AzureCliCredential , then we want to skip over attempting to authenticate with the several methods that come before it in order.

Release Notes

0.5.4

  • Fix issue where the dependencies are not being installed correctly under certain circumstances.

0.5.2

  • Fix issue where ClickOnce inputs aren't appearing in UI.

0.5.1

  • Add support for signing ClickOnce files.

0.4.4

  • Deprecate CodeSigningAccountName input in favor of TrustedSigningAccountName.
  • Add ExcludeWorkloadIdentityCredential input for authentication optimization.
  • Add ExcludeAzureDeveloperCliCredential input for authentication optimization.
  • Add Trace input for controlling trace logging.
  • Add Files input for signing specific files.
  • Package the Trusted Signing module with the task instead of downloading at runtime.

0.3.16

  • Update to latest version of Trusted Signing dlib and Windows SDK build tools.

0.3.1

  • Remove .NET runtime installation as the 2019 and 2022 images already have the necessary .NET runtime installed.

0.2.27

  • Fix an exception that occurs when filtering files without a file extension.
  • Add support for new BatchSize parameter.

0.2.22

  • Add default value 'None' to PKCS7Options parameter to support legacy pipelines.
  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2025 Microsoft