Microsoft Trusted Code Signing - Steps to set it up

Here is the process which I’m guessing you need to follow for Trusted Signing (FAQ)

It’s from memory, and I had a LOT of mis-steps along the way so please help me to refine these steps

I started from scratch, Create a new email (forwarder)

Create a new Microsoft Account (MSA)

  • make sure to add a phone number
    but do NOT add it as an alternate number

Create an Azure Account using the new MSA

  • https://portal.azure.com (I’ll just call this azure in the future)
    I went in and added some indenty information about the new user
    I have no idea if this matters.

GENERAL TIPS on the Azure Portal:

  • Some UI opens a modal window, there will be a little x in the upper right corner
    that you can use to close (back out of) the window

  • Often buttons are disabled
    I’m told that sometimes it helps to logout and back in again
    it would be nice if they explained why a button is disabled, but no.


Azure Portal

  • Trusted Signing Accounts
    :heavy_plus_sign: Create

    • Project Details:

      • Resource group
        • Create New
          Give it a name
          I appended -RG to the end of my name to indicate it’s a Resource Group
          for this walkthrough I’ll call it LearnTrustedSigning-RG
    • Instance Details:

      • Account name:
        Click on the :information_source: button for restrictions in naming
        I believe this name must be globally unique
        this is the name that will be passed into signtool when you want to sign
        For this walkthrough I’ll call it LearnTrustedSigning-Instance

      • Region
        note: I don’t believe that all regions in the world support trusted signing yet
        I assume that all mentioned in the drop down do support it
        note: the Region you select here, will alter the endpoint passed into signtool

      • Pricing Tier
        see https://azure.microsoft.com/en-us/pricing/details/trusted-signing/
        I used Basic

    • NEXT BUTTON takes you to Tags
      I didn’t add any tags

    • NEXT BUTTON takes you to Review and Create

  • At some point, I was asked to add something to hold secrets
    - I don’t recall where that was
    I was likely lead there by an OVERVIEW pane somewhere
    maybe that was the Resource Group mentioned above

  • Now go into your new Trusted Signing Account - LearnTrustedSigning-Instance

    • Access Control (IAM)
      - :heavy_plus_sign: Add
      • Leave it on Tab[ Job function roles]
        - Search for “Trust”
        • Select “Trusted Signing Identity Verifier”
        • Press NEXT
        • :heavy_plus_sign: Select Members
          Select yourself, the Global Administrator
          (you can select mutliple users here, if you have multiple users
          note: later I will add another “internal” “organizational” user
          which is used for the actual signing
        • PRESS SELECT
        • PRESS Review + Assign
  • Back on Home → LearnTrustedSigning-Instance

    • PRESS Identity validation
      • :heavy_plus_sign: New Identity
        Select Public or Private – I selected Public
        :warning:NOTE they are expecting a website with https://
        if that’s an issue for you, please solve that first

        • NOTE: the business identifier is pre-selected to duns number
          I you don’t have a dun and bradstreet number
          or it has outdated information (our duns had an old address)
          then select a different way to identify your business
          I used a Tax Id and used our EIN

        • from prior experience with Sectigo (Comodo)
          carefully fill out the New Organization validation form
          make sure it’s 100% accurate
          down to each comma and apostrophe

        • PRESS Create

        • Check Email - find the email, and verify the email

        • Wait for them to complete the identity validation
          ours took about 30 mintues !!!
          the subject of the email was: “Trusted Signing identity validation status”

  • Once validated

  • Azure > Trusted Signing Accounts > LearnTrustedSigning-Instance
    - press Certificate profile
    :heavy_plus_sign: Create

    • There are several types
      Public: Public Trust| VBS Enclave|Public Trust Test
      Private: Private Trust| Private Trust CI Policy
      I chose Public Trust

      • Fill in the form
        sorry I can’t open the form right now as the Basic subscription allows only 1 certificate profile

        • You’ll give the certificate a name
          this name will be passed to Signtool
          Let’s call ours LearnTrustedSigning-Cert

          Other fields will include the name of your Organization
          and a street or postal address

      • PRESS Create

  • Click on “Microsoft Azure” upper left to go “Home”

    • Click On Microsoft Entra ID
      (you may need to click on All Services first)
      (later Entra ID is shown as Home > Default Directory)
      • Click on Manage > Users
        • :heavy_plus_sign: New user
          Create new user (to create a new internal user in your organization)
          it will need an email address that does NOT match an existing user that Azure knows about
          I created a new email forwarder for this
          • fill out the rest of form including display name and password
            note the password will need to be replaced shortly
            - I think it might be important to fill in the phone number
            as later you’ll be asked to use the microsoft authentication app on your phone
          • save your login and password to your password database (of course)
          • Press Review+Create
  • Click on Home

  • Click on Trusted Signing Accounts
    - Click on LearnTrustedSigning-Instance (so it shows Home > LearnTrustedSigning-Instance at the top)
    - Access Control (IAM)

    • :heavy_plus_sign: Add (add role assingment)
      Leave it on Tab[ Job function roles]
      • Search for “Trust”
        • Select “Trusted Signing Certificate Profile Signer”
        • Press NEXT
        • :heavy_plus_sign: Select Members
          • Select the new internal user we just created
            FYI: you can select mutliple users here, if you have multiple users
          • PRESS SELECT
          • PRESS Review + Assign

  from admin powershell
  cd to desired folder to install your tools
  PS C:\> Invoke-WebRequest -Uri https://dist.nuget.org/win-x86-commandline/latest/nuget.exe -OutFile .\nuget.exe
         
 .\nuget.exe install Microsoft.Windows.SDK.BuildTools -Version 10.0.22621.3233 -x
 .\nuget.exe install Microsoft.Trusted.Signing.Client -Version 1.0.53 -x    
     
  • your json file (I named my TSI_CodeSign.json as TSI is my client)
    will look like this
       {
            "Endpoint": "https://eus.codesigning.azure.net",
            "CodeSigningAccountName": "LearnTrustedSigning-Instance",
            "CertificateProfileName": "LearnTrustedSigning-Cert",
            "CorrelationId": ""
        }
  • note the endpoint will be different if you used a different region than East US
    to check your region, Azure > LearnTrustedSigning-Instance > Overview > location
    see url in the batch file for see a list of pairs of regions and endpoints

  • To sign a file
    • from the same folder as the CallCodeSign.cmd
      C:.…> CallCodeSign TheFilesToSign
      Note: TheFilesToSign can be one file, or a list, can can use wild cards

    • Now, the first time you call SignTool with this configuration

      • a browser tab will open, and you’ll be asked to login
        Select the Internal user we created towards the end of our process
        and fill in the password
        at this point it said since this is the first time logging in
        that I needed to change the password
        do, so, and save your password to your password database (of course)

      • THEN It wanted to have me add the user to the Microsoft Authenication app on my phone
        Open the App on your phone
        Press + at the top
        Select Work or school account
        Scan the QR code on your screen

        • At some point you’ll probably need a thumbprint
          Then they wanted to test the authenticator
          select (or maybe it was type) the number on the screen in the browser into the app
          and press approve
    • If I recall correct, that first code sign failed

    • Try it again, and it worked for me

    • Find someone to celebrate the hard fought victory :partying_face::partying_face::partying_face::partying_face:



see this clarionHub topic for notes on how to use Microsoft Trusted Code Signing with SetupBuilder prior the SetupBuilder 2025 which Friedrich said should be released February 6, 2025


CallCodeSign.cmd —v

:: Created 2025-Jan-22 by Mark Goldberg

@IF .%1.==.. Goto Error

Set SignTool=".\Microsoft.Windows.SDK.BuildTools\bin\10.0.22621.0\x64\signtool.exe"
Set dlib=".\Microsoft.Trusted.Signing.Client\bin\x64\Azure.CodeSigning.Dlib.dll"
Set JsonConfig=".\TSI_CodeSign.json"

%SignTool% sign /v /debug /fd SHA256 /tr "http://timestamp.acs.microsoft.com" /td SHA256 /dlib %dlib% /dmdf %JsonConfig% %*

:: verify is optional
:: %SignTool% verify /v /debug /pa %*

@Goto Done

:: NOTES: ============================================
:: see https://learn.microsoft.com/en-us/azure/trusted-signing/how-to-signing-integrations
::
:: to get the tools you need:
::   from admin powershell
::   cd to desired folder to install your tools
::     PS C:\> Invoke-WebRequest -Uri https://dist.nuget.org/win-x86-commandline/latest/nuget.exe -OutFile .\nuget.exe
::
::     .\nuget.exe install Microsoft.Windows.SDK.BuildTools -Version 10.0.22621.3233 -x
::     .\nuget.exe install Microsoft.Trusted.Signing.Client -Version 1.0.53 -x
::
:: contents of the file pointed to by %JsonConfig% 
:: {
::     "Endpoint": "https://eus.codesigning.azure.net",
::     "CodeSigningAccountName": "<replace with the name of your Trusted Signing Account>",
::     "CertificateProfileName": "<replace with the name of your Certificate Profile>",
::     "CorrelationId": ""
:: }
::
:: "Endpoint":choose the Endpoint URI value that matches the region you selected when you created the Trusted Signing account that you'll specify next (CSAN)
::    https://learn.microsoft.com/en-us/azure/trusted-signing/how-to-signing-integrations#:~:text=Region%20class%20fields-,Endpoint%20URI%20value,-East%20US
::
:: "CodeSigningAccountName":
::   is the (globally unique) name you gave your Trusted Signing Account
::   portal.azure > trusted signing accounts > use the name from an item in this list (I only have one)
::
:: "CertificateProfileName"
::   portal.azure > trusted signing accounts > click on the name selected above > certificate profile > use the name from an item in this list (I only have one)

:Error
@Echo ===================================================
@Echo ERROR: You must pass in the file(s) to sign
@Echo wild cards are acceptable
@Echo ===================================================

@Goto Done

:Done```
6 Likes

Excellent, Mark. What a memory!
Mine is a haze of muddles and the eventual surprise of success.

One thing I’d add… I was a bit unhappy that specifying the “identity” for the code-signing required a street address. But when you create the certificate profile afterwards the default is not to include the detailed address information.

1 Like

This is a really nice write-up Mark! I’ll report back when I have a chance to try it out.

Thanks @MarkGoldberg, your guide helped clear up a few things and I finally got it working. I initially could not get code signing to work when trying to use the personal Microsoft Account username/password during the browser flow, but your instruction regarding “Users” helped me find a solution, one that doesn’t actually require a second/dummy user. Read on for my slight tweaks to your very thorough guide!

A few things worth noting, during the quoted step below…

…you can alternatively click the “Organization” dropdown and opt for “Individual” here if you want an individual identity, associated only with yourself, e.g. your name, and a house address. Don’t worry, even with a “Public” identity/certificate, when setting up a “Certificate profile” later, you can conceal that address. You will then follow through identity verification like submitting a picture of your ID and a recent billing statement with your name and address on it.

Now, here’s the other slight tweak compared with your approach, which allowed me to avoid creating a second alt/dummy user. This has to do with a “mirror account” that already exists and is tied to your personal Microsoft account, and can be logged into using the “user principal name” found in Azure (which differs from your actual email/password login).

Here is the relevant section of your guide…

and here is how I would modify it…

  • Click On Microsoft Entra ID
    (you may need to click on All Services first)
    (later Entra ID is shown as Home > Default Directory)
    • Click on Manage > Users
      • Click on yourself, the only user
      • Click the “copy to clipboard” icon on the User principal name entry
      • Open an Incognito window to https://login.microsoftonline.com/ and sign in with that username, e.g. [email protected]. When prompted with a password, click “forgot” and proceed to reset your password via email to your primary email address (this is and will be a different, unique password from your Microsoft account password!)
      • Configure 2FA, again this will be a unique 2FA method independent of the one for your personal Microsoft account
      • Complete the login flow, save the username/password for logging in to sign your software later!

Then, when assigning roles to myself, the only user (as opposed to your two-user flow), I gave myself BOTH of the “Trusted Signing Identity Verifier” and “Trusted Signing Certificate Profile Signer” roles.

I would also specify some ExcludeCredentials in the JSON, modifying yours to be…

{
  "Endpoint": "https://eus.codesigning.azure.net",
  "CodeSigningAccountName": "LearnTrustedSigning-Instance",
  "CertificateProfileName": "LearnTrustedSigning-Cert",
  "CorrelationId": "UNIQUE-MACHINE-NAME-IF-DESIRED-OR-EMPTY-STRING"
  "ExcludeCredentials": [
    "AzureCliCredential",
    "AzureDeveloperCliCredential",
    "AzurePowerShellCredential",
    "EnvironmentCredential",
    "ManagedIdentityCredential",
    "SharedTokenCacheCredential",
    "VisualStudioCodeCredential",
    "VisualStudioCredential",
    "WorkloadIdentityCredential"
  ]
}

Though your endpoint may vary, e.g. wus or something. Also, it’s notable that wus3 supports Azure Trusted Signing despite one of their official help articles suggesting maybe it doesn’t.

Most of those ExcludeCredentials entries speeds up the signing flow, and we omit InteractiveBrowserCredential so that we can force that one. Notice that SharedTokenCacheCredential seems to sort of magically cache your signing key, not sure for how long and how it gets invalidated, but it’s probably best to exclude that one too! That way you’re always forced through the browser flow when signing (which should be an infrequent but very security-sensitive action).

Anyways this took me all day to sort out, so I’m really glad I found your guide. It’s awesome that code signing is now available to any individual for $10/mo. but clearly there’s still a ton of very devops/IT flaming hoops to jump through, and easy to get burned.

1 Like