Task
I have an Microsoft Office Excel plugin application that historically has been deployed using ClickOnce publishing. The app that has been running for several years without changes. Now some changes were requested by the customer, and I had to figure out how to sign the ClickOnce application considering the changes the industry has made over the last couple of years for certificates.
I was no longer able to use the UI in Visual Studio IDE for ClickOnce Signing.
CodeSigning certificates are not cheap, so I wanted to explore Azure Trusted Signing and if it could be used to sign ClickOnce Office plugin applications.
I managed in the end, but it was not as simple as I thought at all.
Why the Code Signing Process Changed
The primary motivation was to enhance security and prevent the widespread misuse of compromised private keys, which were often easily stolen when stored as software files (like PFX) on potentially insecure development machines. The new requirements became effective on June 1, 2023. All major Certificate Authorities (CAs), such as DigiCert, Sectigo, and GlobalSign, agreed to adhere to these new rules. They now issue all new standard (OV/IV) and EV code signing certificates with the private keys generated and stored on secure hardware devices, such as USB tokens or Hardware Security Modules (HSMs), that meet specific security standards (FIPS 140-2 Level 2 or Common Criteria EAL 4+).
See GlobalSign's notice here
Prerequisites: Azure Trusted Signing setup
Follow steps 1-7 from https://melatonin.dev/blog/code-signing-on-windows-with-azure-trusted-signing/.
- Create an Azure account if you do not have one
- Create a Subscription
- Create a “Trusted Signing Account”
- Create a new registration under Azure "App registrations"
- Add “identity verifier” role to your Azure account
- Add the signer role to your “App Registration” user
- Identity Validation
- Create a Certificate Profile
- Azure Trusted Signing for plugin developers
- Automatically Signing a Windows EXE with Azure Trusted Signing, dotnet sign, and GitHub Actions
Proces for Signing ClickOnce Office/Excel Plugin using Azure Trusted Signing
- Open Powershell as Administrator
- Log in on the relevant Azure account where you have created the above subscription and Trusted Signing via the powershell command line
az login - My output on the command line was something like the below
Select the account you want to log in with. For more information on login with Azure CLI, see https://go.microsoft.com/fwlink/?linkid=2271136
Retrieving tenants and subscriptions for the selection...
[Tenant and subscription selection]
No Subscription name Subscription ID Tenant
----- ------------------------------ ------------------------------------ -------------
[1] * ABCCodeSigningSubscription 12345678-1234-1234-1234-123456789012 ABC
The default is marked with an *; the default tenant is 'ABC' and subscription is 'ABCCodeSigningSubscription' (12345678-1234-1234-1234-123456789012).
Select a subscription and tenant (Type a number or Enter for no changes): 1
Tenant: ABCTenant
Subscription: ABCCodeSigningSubscription (12345678-1234-1234-1234-123456789012)
[Announcements]
With the new Azure CLI login experience, you can select the subscription you want to use more easily. Learn more about it and its configuration at https://go.microsoft.com/fwlink/?linkid=2271236
If you encounter any problem, please open an issue at https://aka.ms/azclibug
[Warning] The login output has been updated. Please be aware that it no longer displays the full list of available subscriptions by default. - Install the Sign CLI (for this blog post I used https://github.com/dotnet/sign version 0.9.1-beta.25379.1+ba6e717abf74a693f0f9c5e891c0e3ef624956b3)
dotnet tool install --tool-path . --prerelease sign - By reviewing the codechanges in https://github.com/dotnet/sign/pull/716/files and using the commandline help for trusted signing
Description:
Use Trusted Signing.
Usage:
sign code trusted-signing <file(s)>... [options]
Arguments:
<file(s)> File(s) to sign.
Options:
-tse, --trusted-signing-endpoint <trusted-signing-endpoint> (REQUIRED) The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in.
-tsa, --trusted-signing-account <trusted-signing-account> (REQUIRED) The Trusted Signing Account name.
-tscp, --trusted-signing-certificate-profile <trusted-signing-certificate-profile> (REQUIRED) The Certificate Profile name.
-act, --azure-credential-type <azure-cli|azure-powershell|managed-identity|workload-identity> Azure credential type that will be used. This defaults to DefaultAzureCredential.
-mici, --managed-identity-client-id <managed-identity-client-id> The client id of a user assigned ManagedIdentity.
-miri, --managed-identity-resource-id <managed-identity-resource-id> The resource id of a user assigned ManagedIdentity.
-an, --application-name <application-name> Application name (ClickOnce).
-d, --description <description> Description of the signing certificate.
-u, --description-url <description-url> Description URL of the signing certificate.
-b, --base-directory <base-directory> Base directory for files. Overrides the current working directory. [default: D:\]
-o, --output <output> Output file or directory. If omitted, input files will be overwritten.
-pn, --publisher-name <publisher-name> Publisher name (ClickOnce).
-fl, --file-list <file-list> Path to file containing paths of files to sign or to exclude from signing.
-rc, --recurse-containers Sign container contents. [default: True]
-fd, --file-digest <file-digest> Digest algorithm to hash files with. Allowed values are 'sha256', 'sha384', and 'sha512'. [default: SHA256]
-t, --timestamp-url <timestamp-url> RFC 3161 timestamp server URL. [default: http://timestamp.acs.microsoft.com/]
-td, --timestamp-digest <timestamp-digest> Digest algorithm for the RFC 3161 timestamp server. Allowed values are sha256, sha384, and sha512. [default: SHA256]
-m, --max-concurrency <max-concurrency> Maximum concurrency. [default: 4]
-v, --verbosity <Critical|Debug|Error|Information|None|Trace|Warning> Sets the verbosity level. Allowed values are 'none', 'critical', 'error', 'warning', 'information', 'debug', and 'trace'.
[default: Warning]
-?, -h, --help Show help and usage information - I ended up with the following command
& ./sign code trusted-signing "D:\ClickOncePublishDirectory\ABCApp.vsto" -tse https://weu.codesigning.azure.net -tsa ABCCodeSigning -tscp ABCCodeSigningCertificate -an ABCApp -pn ABC -t "http://timestamp.acs.microsoft.com" -v debug - I had problems signing the ClickOnce initially due to having quite a few older versions under the "Application Files" directory, once I removed the older versions and only had the lastest build it worked fine

No comments:
Post a Comment