Jump to content
Angus Robertson

Microsoft Trusted Signing service

Recommended Posts

I tried it and it still feels very "previewish". After being able to create the signing account, getting my identity validated and creating a first certificate, I'm currently stuck at properly submitting my credentials while trying to sign an exe with SignTool.exe.

The available documentation still lacks a lot of important details and it's still too new to find suitable help at stackoverflow or similar.

 

It might work better if you use it via Azure DevOps or GitHub. But so far it still needs some finetuning - especially the documentation - before it can be used with SignTool.exe.

 

With the tool available at https://docs.rs/crate/trusted-signing-cli/0.2.0 I came the closest so far with simple signing an exe file - but still get errors I can't get any further explanation for.

Share this post


Link to post

Got it working with the help of the documentation available at Code signing on Windows with Azure Trusted Signing · Melatonin 

 

Most related documents currently online (including Microsofts documentation) still have a major error in the description of the metadata.json format. Instead of using the "TrustedCodeSigningAccount" entry you will need the entry "CodeSignigAcccountName" and set it to the name of the Trusted Signing Account in Azure -, not your e-mail address you use for logging into Azure or other Microsoft services.

Share this post


Link to post

Thanks for all the useful comments, I'll try it myself when I have time later in the week.  

 

Got another eight months left before my code signing certificate expires, but looks like I can avoid dongle hell.  I've had an Azure account for years, although perhaps not the correct type of account. 

 

Angus

 

Share this post


Link to post

This is interesting, particularly since I spent the last few months working on a code signing server product that takes the hassle out of using dongles  (working on the admin ui, signing part is all done) 😞

 

So code signing for USD$120 per year vs $299 - I bet digicert & co are peeved about this. Microsoft are about to take $100M(*) a year out of their pockets. 

 

* plucked that out of thin air, but given what they charge and how many software vendors there are, it's quite possibly more than that.

Share this post


Link to post

I'll be happy not needing to deal with Digicert, Sectigo and co, particularly with their massive price increases in recent years.  Let's Encrypt stopped most of their web certificate business.

 

Microsoft does have a history of looking after developers, for many years there was a web page that allowed buying heavily discounted certificates from the major vendors at the time, it disappeared a few years ago. 

 

Angus

 

Share this post


Link to post

This looks very interesting to me and a nice move for code signing. My current certificate is valid till the end of 2025 so I can only hope that this service will improve till then 🤞

Share this post


Link to post
1 hour ago, Angus Robertson said:

I'll be happy not needing to deal with Digicert, Sectigo and co, particularly with their massive price increases in recent years.

Yeah I can see them losing code signing completely in the future. 

 

I did sign up for this - 10 hours so far and all I have had is a confirm email address - status us still "in progress"

Share this post


Link to post
Quote

10 hours so far and all I have had is a confirm email address

Probably handled manually in USA business hours until full launch.

 

Angus

 

Share this post


Link to post
3 hours ago, Vincent Parrett said:

I did sign up for this - 10 hours so far and all I have had is a confirm email address - status us still "in progress"

Our Trusted Signing validation took about 30 minutes from creating the validation request until successful validation. But we are also Microsoft Partner for many years and this might have produced already enough interaction between Microsoft and us for giving them enough material for speedy validation.
If the related documentation is correct, Trusted Signing is still in preview and is currently open only to companies that are registered more than 3 years with an Azure account.

Share this post


Link to post

Not sure exactly how old my Azure account its, must be at least 10 years though. Still "in progress" 

Share this post


Link to post
Posted (edited)

In the progress of getting this working, setting anything up in Azure is horrible, I've got OAuth2 stuff, now waiting for company identity validation.  I've had MSDN and partner accounts for 30 years, used to get a box of CDs each quarter before the internet. 

 

Worth mentioning that if you have a partner MAPS account and pay annually (UK £350) to get all the MS OS and apps, you get $100 of Azure credit each month, which I assume can be used for code signing.

 

Two minutes later, validation pass.

 

Angus

 

Edited by Angus Robertson

Share this post


Link to post
10 hours ago, Angus Robertson said:

setting anything up in Azure is horrible

Yep, need a degree in nonsense to understand how anything works in azure. A few years ago we evaluated all the major cloud providers when considering moving everything to the cloud, trying to compare pricing etc - azure dropped out of the running pretty quickly as we all found it too confusing to use. Anytime you need to configure something, it sends you off on a bunch of side hussles to configure something else with zero explaination, and when something goes wrong it's very difficult to figure out what you need to do. Bloated, over architected monstrosity. 

  • Like 1

Share this post


Link to post
2 hours ago, Vincent Parrett said:

Yep, need a degree in nonsense to understand how anything works in azure. A few years ago we evaluated all the major cloud providers when considering moving everything to the cloud, trying to compare pricing etc - azure dropped out of the running pretty quickly as we all found it too confusing to use. Anytime you need to configure something, it sends you off on a bunch of side hussles to configure something else with zero explaination, and when something goes wrong it's very difficult to figure out what you need to do. Bloated, over architected monstrosity. 

Yes, you have it, "Side hussles".  

Share this post


Link to post

Setting up MTS/ATS for Windows is not trivial, Azure command line interface, new signing tool, Azure signing DLL, .net8 runtime, environmental variables, Azure commands, etc. 

 

Not helped by the Microsoft web site code and Json examples all using non-breaking spaces (xA0) which have to be replaced by real spaces to do anything useful.

 

Once installed, it attempts to sign my program, but fails with OAuth2 login using a browser, and with incorrect secrets, so many to choose from in Azure. 

 

So the documentation needs much clearer information of how Azure authentication should be set up for Windows apps.

 

Angus

 

 

 

 

Share this post


Link to post
8 minutes ago, Angus Robertson said:

So the documentation needs much clearer information of how Azure authentication should be set up for Windows apps.

There are two places where you need to provide credential information:

 

You need to set Windows environment variables:

set AZURE_TENANT_ID=(enter your azure tenant ID here)
set AZURE_CLIENT_ID=(this is the client ID of the app you have set up for authentication)
set AZURE_CLIENT_SECRET =(thats the client secret value of the prepared app)

Best place would be in a batch file that also contains calls to SignTool etc.. Make sure you  strictly limit access to this batch file.

 

Then you need to create the metadata.json file to be used with SignTool and the Azure Trusted Signing DLL:

 

{
  "Endpoint": "correct URL for your area",
  "CertificateProfileName": "name of the certificate in your trusted signing account",
  "CodeSigningAccountName": "name of your Trusted Signing account, NOT your e-mail address or other user ID"
 }

If the details are set correct, you should be able to authorize against the Azure Trusted Signing service and sign your files with SignTool.

 

Setting more variables than the ones mentioned above may confuse the authorization process and may cause the internal selection of another authorization method (there are many) that might not work for your case.

 

  • Like 1

Share this post


Link to post
On 5/3/2024 at 10:21 AM, Fred Ahrens said:

Then you need to create the metadata.json file to be used with SignTool and the Azure Trusted Signing DLL:


{
  "Endpoint": "correct URL for your area",
  "CertificateProfileName": "name of the certificate in your trusted signing account",
  "CodeSigningAccountName": "name of your Trusted Signing account, NOT your e-mail address or other user ID"
 }

 

Hello,

 

Thought I had it all set up but no joy so looking at everything, get this:

 

The following certificates were considered:
After EKU filter, 0 certs were left.
After expiry filter, 0 certs were left.
SignTool Error: No certificates were found that met all the given criteria.

 

"CodeSigningAccountName"

 

The name under the green:

 

image.png.6f65e951b25c5ac40e4afce5b8dd664e.png

 

Thanks,

 

Mark

 

Share this post


Link to post
Posted (edited)

OK, got it to at least try and sign the exe.

Still not sure about " CodeSigningAccountName"

Trusted Signing

Version: 1.0.59

"Metadata": {
  "Endpoint": "https://eus.codesigning.azure.net/",
  "CodeSigningAccountName": "TheName",
  "CertificateProfileName": "TheCert",
  "ExcludeCredentials": [
    "ManagedIdentityCredential",
    "EnvironmentCredential",
    "WorkloadIdentityCredential",
    "SharedTokenCacheCredential",
    "VisualStudioCredential",
    "VisualStudioCodeCredential",
    "AzurePowerShellCredential",
    "AzureDeveloperCliCredential",
    "InteractiveBrowserCredential"
  ]
}

Submitting digest for signing...
Unhandled managed exception
Azure.Identity.CredentialUnavailableException: Azure CLI not installed
   at Azure.Identity.DefaultAzureCredential.GetTokenFromSourcesAsync(TokenCredential[] sources, TokenRequestContext requestContext, Boolean async, CancellationToken cancellationToken)
   at Azure.Identity.DefaultAzureCredential.GetTokenImplAsync(Boolean async, TokenRequestContext requestContext, CancellationToken cancellationToken)
   at Azure.Identity.CredentialDiagnosticScope.FailWrapAndThrow(Exception ex, String additionalMessage, Boolean isCredentialUnavailable)
   at Azure.Identity.DefaultAzureCredential.GetTokenImplAsync(Boolean async, TokenRequestContext requestContext, CancellationToken cancellationToken)
   at Azure.Identity.DefaultAzureCredential.GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)
   at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.AccessTokenCache.GetHeaderValueFromCredentialAsync(TokenRequestContext context, Boolean async, CancellationToken cancellationToken)
   at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.AccessTokenCache.GetHeaderValueAsync(HttpMessage message, TokenRequestContext context, Boolean async)
   at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.AccessTokenCache.GetHeaderValueAsync(HttpMessage message, TokenRequestContext context, Boolean async)
   at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.AuthenticateAndAuthorizeRequestAsync(HttpMessage message, TokenRequestContext context)
   at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
   at Azure.Core.Pipeline.RedirectPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
   at Azure.Core.Pipeline.RetryPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
   at Azure.Core.Pipeline.RetryPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
   at Azure.CodeSigning.CertificateProfileRestClient.SignAsync(String codeSigningAccountName, String certificateProfileName, SignRequest body, String xCorrelationId, String clientVersion, CancellationToken cancellationToken)
   at Azure.CodeSigning.CertificateProfileClient.StartSignAsync(String codeSigningAccountName, String certificateProfileName, SignRequest body, String xCorrelationId, String clientVersion, CancellationToken cancellationToken)
   at Azure.CodeSigning.Dlib.Core.DigestSigner.SignAsync(UInt32 algorithm, Byte[] digest, SafeFileHandle safeFileHandle, CancellationToken cancellationToken)
   at Azure.CodeSigning.Dlib.Core.DigestSigner.Sign(UInt32 algorithm, Byte[] digest, SafeFileHandle safeFileHandle)
   at AuthenticodeDigestSignExWithFileHandleManaged(_CRYPTOAPI_BLOB* pMetadataBlob, UInt32 digestAlgId, Byte* pbToBeSignedDigest, UInt32 cbToBeSignedDigest, Void* hFile, _CRYPTOAPI_BLOB* pSignedDigest, _CERT_CONTEXT** ppSignerCert, Void* hCertChainStore)

SignTool Error: An unexpected internal error has occurred.
Error information: "Error: SignerSign() failed." (-2147467259/0x80004005)

And this:

Azure.Identity.CredentialUnavailableException: Azure CLI not installed

"not installed"?

Edited by Mark-

Share this post


Link to post

It looks like you did exclude all available authentication methods via "ExcludeCredentials". If you leave this parameter empty and provide authentication details via environment variables, you should be able to use your certificate.

 

As long as the authentication doesn't work, you may get a lot of misleading error messages - like "Azure CLI not installed". Actually, Azure CLI is not needed at all. Without authentication SignTool will also not be able to find a valid certificate.

 

I should mention: I assume you try to set up a simple batch file that does the code signing for you. If not, let me know your planned code signing process.

Share this post


Link to post
1 hour ago, Fred Ahrens said:

It looks like you did exclude all available authentication methods via "ExcludeCredentials". If you leave this parameter empty and provide authentication details via environment variables, you should be able to use your certificate.

 

As long as the authentication doesn't work, you may get a lot of misleading error messages - like "Azure CLI not installed". Actually, Azure CLI is not needed at all. Without authentication SignTool will also not be able to find a valid certificate.

 

I should mention: I assume you try to set up a simple batch file that does the code signing for you. If not, let me know your planned code signing process.

Thanks for the response.

 

I added the "ExcludeCredentials" after it did not work when I read on SO someone say adding them worked from them.

Yes, I am using a batch file.

Where I am getting the "CodeSigningAccountName" is the correct location?

 

I removed the "ExcludeCredentials" from the json file and ran it again. Took awhile to complete. The results are much different, same error code: SignerSign() failed." (-2147467259/0x80004005)

 

I see this: "Original exception: AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID,..."

 

Sticks out. I know the secret is correct and it appears it can not be changed in Azure. I assume I will need to generate another cert? Or look for...?

 

 

Share this post


Link to post

The "client secrect" is related to the app used for doing the signing. You should check at https://melatonin.dev/blog/code-signing-on-windows-with-azure-trusted-signing/#step-4-create-an-app-registration if you have created the app needed for doing the signing.

 

This "app" part was initially hard to understand for me. This app is just a placeholder without a real executable or service endpoint. The only purpose is to give it the access right for signing your files. The client secret of this app will be used on top of your other credentials for identifying the app to be used.

The client secret of the app is the "Value" entry in section "Certificates & secrets" - not "Secret ID" (it's visible only for a short time; if it's no longer visible and you don't know the value, you'll need to create a new client secret). BTW: That's also the first place to check if the signing suddenly stops working. Usually it's caused by an expired client secret.

Share this post


Link to post
5 hours ago, Fred Ahrens said:

The client secret of the app is the "Value" entry in section "Certificates & secrets" - not "Secret ID" (it's visible only for a short time; if it's no longer visible and you don't know the value, you'll need to create a new client secret). BTW: That's also the first place to check if the signing suddenly stops working. Usually it's caused by an expired client secret.

Thank you.

 

I recreated the client secret and the error changed. 🙂

Not sure what it means. Perhaps Azure is having a problem at the moment?

 

Trusted Signing

Version: 1.0.59

"Metadata": {
  "Endpoint": "https://eus.codesigning.azure.net/",
  "CodeSigningAccountName": "NameZ",
  "CertificateProfileName": "ProfileZ",
  "ExcludeCredentials": []
}

Submitting digest for signing...
Unhandled managed exception
Azure.RequestFailedException: Service request failed.
Status: 403 (Forbidden)

Headers:
Date: Fri, 31 May 2024 12:15:50 GMT
Connection: keep-alive
Strict-Transport-Security: REDACTED
x-azure-ref: REDACTED
X-Cache: REDACTED
Content-Length: 0

   at Azure.CodeSigning.CertificateProfileRestClient.SignAsync(String codeSigningAccountName, String certificateProfileName, SignRequest body, String xCorrelationId, String clientVersion, CancellationToken cancellationToken)
   at Azure.CodeSigning.CertificateProfileClient.StartSignAsync(String codeSigningAccountName, String certificateProfileName, SignRequest body, String xCorrelationId, String clientVersion, CancellationToken cancellationToken)
   at Azure.CodeSigning.Dlib.Core.DigestSigner.SignAsync(UInt32 algorithm, Byte[] digest, SafeFileHandle safeFileHandle, CancellationToken cancellationToken)
   at Azure.CodeSigning.Dlib.Core.DigestSigner.Sign(UInt32 algorithm, Byte[] digest, SafeFileHandle safeFileHandle)
   at AuthenticodeDigestSignExWithFileHandleManaged(_CRYPTOAPI_BLOB* pMetadataBlob, UInt32 digestAlgId, Byte* pbToBeSignedDigest, UInt32 cbToBeSignedDigest, Void* hFile, _CRYPTOAPI_BLOB* pSignedDigest, _CERT_CONTEXT** ppSignerCert, Void* hCertChainStore)

SignTool Error: An unexpected internal error has occurred.
Error information: "Error: SignerSign() failed." (-2147467259/0x80004005)

 

Share this post


Link to post

Are the values shown for "CodeSigningAccountName" and "CertificateProfileName" correct? If yes, those values should be redacted in your post. If not, you need to update your metadata file.

Share this post


Link to post
4 minutes ago, Fred Ahrens said:

Are the values shown for "CodeSigningAccountName" and "CertificateProfileName" correct? If yes, those values should be redacted in your post. If not, you need to update your metadata file.

I changed them for the post.

The actual ones are correct, as far as I know.

The "CodeSigningAccountName"  from here:

 

image.png.59e36dac57697f449ff8e6e0ba04bd4b.png

 

"CertificateProfileName" from here:

 

image.png.78005ad958d53a9f1ca269f1f1fcc377.png

Share this post


Link to post

Looks good.

 

Have you set the environment variables AZURE_TENANT_ID, AZURE_CLIENT_ID and AZURE_CLIENT_SECRET?

 

In Azure, if you go to the home page of your Trusted Signing Account: Under "Access control (IAM)" > "Role assignments": Is your app listed with having the right "Trusted Signing Certificate Profile Signer"?

 

azure1.png

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×