Mac Tahoe (in Beta as of the time of this writing) has this new function known as Edge Mild that mainly places a shiny image of an Edge Mild round your display and mainly makes use of the ability of OLED to offer you a digital ring gentle. So I used to be like, why cannot we even have good issues? I wrote (vibed, with GitHub Copilot and Claude Sonnet 4.5) a Home windows Edge Mild App (supply code at https://github.com/shanselman/WindowsEdgeLight and you will get the most recent launch right here https://github.com/shanselman/WindowsEdgeLight/releases or the app will verify for brand spanking new releases and autoupdate with Updatum).
Nevertheless, as is with all suss unfastened executables on the web, once you run random stuff you will typically get the Window Defender ‘new telephone, who dis’ warning which is frightening. After a number of downloads and no viruses or complaints, my executable will finally achieve popularity with the Home windows Defender Sensible Display service, however having a Code Signing Certificates is alleged to assist with that. Nevertheless, code signing certs are costly and a trouble to handle and renew.
Somebody instructed me that Azure Trusted Signing was considerably much less of a trouble – it is much less, nevertheless it’s nonetheless non-trivial. I learn this put up from Rick (his weblog is gold and has been for years) earlier within the 12 months and a few of it was tremendous helpful and different stuff has been made easier over time.
I wrote 80% of this weblog put up, however since I simply spent an hour getting code signing to work and GitHub Copilot was going by and logging all the pieces I did, I did use Claude 4.5 to assist set up a few of this. I’ve reviewed all of it and re-written components I did not like, so any errors are mine.
Azure Trusted Signing is Microsoft’s cloud-based code signing service that:
- No {hardware} tokens – All the pieces occurs within the cloud
- Automated certificates administration – Certificates are issued and renewed robotically
- GitHub Actions integration – Signal throughout your CI/CD pipeline. I used GH Actions.
- Kinda Affortable – About $10/month for small tasks. I would love it if this had been $10 a 12 months. That is cheaper than a yearly cert, nevertheless it’ll add up after some time so I am all the time searching for cheaper/simpler choices.
- Trusted by Home windows – Makes use of the identical certificates authority as Microsoft’s personal apps, so it’s best to get your EXE trusted quicker
Stipulations
Earlier than beginning, you will want:
- Azure subscription
- Azure CLI – Set up from right here
- Identification validation paperwork – Driver’s license or passport for particular person builders. Observe that I am within the US, so your mileage might range however I mainly arrange the account, scanned a QR code, took an image of my license, then did a selfie, then waited.
- Home windows PC – For native signing (elective) however I ended up utilizing the dotnet signal instrument. There are
- GitHub repository – For automated signing (elective)
Half 1: Setting Up Azure Trusted Signing
Step 1: Register the Useful resource Supplier
First, I must allow the Azure Trusted Signing service in my subscription. This may be completed within the Portal, or on the CLI.
# Login to Azure
az login
# Register the Microsoft.CodeSigning useful resource supplier
az supplier register --namespace Microsoft.CodeSigning
# Look forward to registration to finish (takes 2-3 minutes)
az supplier present --namespace Microsoft.CodeSigning --query "registrationState"
Wait till the output exhibits "Registered".
Step 2: Create a Trusted Signing Account
Now create the precise signing account. You are able to do this by way of Azure Portal or CLI.
Choice A: Azure Portal (Simpler for first-timers)
- Go to Azure Portal
- Seek for “Trusted Signing Accounts”
- Click on Create
- Fill in:
- Subscription: Your subscription
- Useful resource Group: Create new or use current (e.g., “MyAppSigning”)
- Account Title: A singular title (e.g., “myapp-signing”)
- Area: Select closest to you (e.g., “West US 2”)
- SKU: Fundamental (ample for many apps)
- Click on Evaluation + Create, then Create
Choice B: Azure CLI (Sooner in case you are a CLI particular person or wish to drive stick shift)
# Create a useful resource group
az group create --name MyAppSigning --location westus2
# Create the Trusted Signing account
az trustedsigning create
--resource-group MyAppSigning
--account-name myapp-signing
--location westus2
--sku-name Fundamental
Essential: Observe your area endpoint. Frequent ones are:
- East US:
https://eus.codesigning.azure.web/ - West US 2:
https://wus2.codesigning.azure.web/ - Your particular area: Verify in Azure Portal beneath your account’s Overview web page
I completely flaked on this and messed round for 10 min earlier than I spotted that this URL issues and is particular to your account. Bear in mind this endpoint.
Step 3: Full Identification Validation
That is crucial step. Microsoft must confirm you are an actual particular person/group.
- In Azure Portal, go to your Trusted Signing Account
- Click on Identification validation within the left menu
- Click on Add identification validation
- Select validation kind:
- Particular person: For solo builders (makes use of driver’s license/passport)
- Group: For firms (makes use of enterprise registration paperwork)
- For Particular person validation:
- Add a transparent picture of your government-issued ID
- Present your full authorized title (should match ID precisely)
- Present your e mail deal with
- Submit and anticipate approval
Approval Time:
- Particular person: Normally 1-3 enterprise days
- Group: 3-5 enterprise days
- Me: This took about 4 hours, so once more, YMMV. I used my private account and my private Azure (do not belief MSFT of us with limitless Azure credit, I pay for my very own) in order that they did not understand it was me. I went by the common line, not the Pre-check line LOL.
You may obtain an e mail when accepted. You can’t signal any code till that is accepted.
Step 4: Create a Certificates Profile
As soon as your identification is validated, create a certificates profile. That is what truly points the signing certificates.
- In your Trusted Signing Account, click on Certificates profiles
- Click on Add certificates profile
- Fill in:
- Profile title: Descriptive title (e.g., “MyAppProfile”)
- Profile kind: Select Public Belief (required to stop SmartScreen)
- Identification validation: Choose your accepted identification
- Certificates kind: Code Signing
- Click on Add
Essential: Solely “Public Belief” profiles stop SmartScreen warnings. “Personal Belief” is for inner apps solely. This took me a second to understand additionally as it isn’t an intuitive title.
Step 5: Confirm Your Setup
# Record your Trusted Signing accounts
az trustedsigning present
--resource-group MyAppSigning
--account-name myapp-signing
# Ought to present standing: "Succeeded"
Write down these values – you will want them later:
- Account Title:
myapp-signing - Certificates Profile Title:
MyAppProfile - Endpoint URL:
https://wus2.codesigning.azure.web/(or your area) - Subscription ID: Present in Azure Portal
- Useful resource Group:
MyAppSigning
Half 2: Native Code Signing
Now let’s signal an executable in your my machine. You do not NEED to do that, however I wished to attempt it regionally to keep away from a bunch of CI/CD runs, and I wished to right-click the EXE and see the cert in Properties earlier than I took all of it to the cloud. The great half about this was that I did not must mess with any certificates.
Step 1: Assign Your self the Signing Function
You want permission to truly use the signing service.
Choice A: Azure Portal
- Go to your Trusted Signing Account
- Click on Entry management (IAM)
- Click on Add → Add position project
- Seek for and choose Trusted Signing Certificates Profile Signer. That is essential. I looked for “code” and located nothing. Seek for “Trusted”
- Click on Subsequent
- Click on Choose members and discover your consumer account
- Click on Choose, then Evaluation + assign
Choice B: Azure CLI
# Get your consumer object ID
$userId = az advert signed-in-user present --query id -o tsv
# Assign the position
az position project create
--role "Trusted Signing Certificates Profile Signer"
--assignee-object-id $userId
--scope /subscriptions/YOUR_SUBSCRIPTION_ID/resourceGroups/MyAppSigning/suppliers/Microsoft.CodeSigning/codeSigningAccounts/myapp-signing
Substitute YOUR_SUBSCRIPTION_ID together with your precise subscription ID.
Step 2: Login with the Appropriate Scope
That is essential – you might want to login with the precise codesigning scope.
# Logout first to clear previous tokens
az logout
# Login with codesigning scope
az login --use-device-code --scope "https://codesigning.azure.web/.default"
This offers you a code to enter at https://microsoft.com/devicelogin. Comply with the prompts.
Why machine code circulation? As a result of Azure CLI’s default authentication can battle with Visible Studio credentials in my expertise. System code circulation is extra dependable for code signing.
Step 3: Obtain the Signal Instrument
Choice A: Set up Globally (Advisable for normal use)
# Set up as a worldwide instrument (out there in every single place)
dotnet instrument set up --global --prerelease signal
# Confirm set up
signal --version
Choice B: Set up Domestically (Challenge-specific)
# Set up to present listing
dotnet instrument set up --tool-path . --prerelease signal
# Use with .signal.exe
Which ought to I exploit?
- World: In the event you’ll signal a number of tasks or signal incessantly
- Native: If you wish to preserve the instrument with a particular challenge or don’t desire it in your PATH
Step 4: Signal Your Executable
Observe once more that code signing URL is particular to you. The tscp is your Trusted Signing Certificates Profile title and the tsa is your Trusted Signing Account title. I set *.exe to signal all of the EXEs within the folder and be aware that the -b base listing is an absolute path, not a relative one. For me it was d:githubWindowsEdgeLightpublish, and your mileage will range.
# Navigate to your challenge folder
cd C:MyProject
# Signal the executable
.signal.exe code trusted-signing `
-b "C:MyProjectpublish" `
-tse "https://wus2.codesigning.azure.web" `
-tscp "MyAppProfile" `
-tsa "myapp-signing" `
*.exe `
-v Info
Parameters defined:
-b: Base listing containing recordsdata to signal-tse: Trusted Signing endpoint (your area)-tscp: Certificates profile title-tsa: Trusted Signing account title*.exe: Sample to match recordsdata to signal-v: Verbosity degree (Hint, Info, Warning, Error)
Anticipated output:
information: Signing WindowsEdgeLight.exe succeeded.
Accomplished in 2743 ms.
Step 5: Confirm the Signature
You are able to do this in PowerShell:
# Verify the signature
Get-AuthenticodeSignature ".publishMyApp.exe" | Format-Record
# Search for:
# Standing: Legitimate
# SignerCertificate: CN=Your Title, O=Your Title, ...
# TimeStamperCertificate: Ought to be current
Proper-click the EXE → Properties → Digital Signatures tab:
- It is best to see your signature
- “This digital signature is OK”
Frequent Native Signing Points
I hit all of those lol
Subject: “Please run ‘az login’ to arrange account”
- Trigger: Not logged in with the fitting scope
- Repair: Run
az logoutthenaz login --use-device-code --scope "https://codesigning.azure.web/.default"
Subject: “403 Forbidden”
- Trigger: Flawed endpoint, account title, or lacking permissions
- Repair:
- Confirm endpoint matches your area (wus2, eus, and so forth.)
- Confirm account title is precise (case-sensitive)
- Confirm you might have “Trusted Signing Certificates Profile Signer” position
Subject: “Consumer account doesn’t exist in tenant”
- Trigger: Azure CLI making an attempt to make use of Visible Studio credentials
- Repair: Use machine code circulation (see Step 2)
Half 3: Automated Signing with GitHub Actions
That is the place the magic occurs. I wish to robotically signal each launch. I am utilizing GitVersion so I simply must tag a commit and GitHub Actions will kick off a run. You may go take a look at an actual run intimately at https://github.com/shanselman/WindowsEdgeLight/actions/runs/19775054123
Step 1: Create a Service Principal
GitHub Actions wants its personal identification to signal code. We’ll create a service principal (like a robotic account). That is VERY totally different than your native signing setup.
Essential: You want Proprietor or Consumer Entry Administrator position in your subscription to do that. If you do not have it, ask your Azure admin or a buddy.
# Create service principal with signing permissions
az advert sp create-for-rbac
--name "MyAppGitHubActions"
--role "Trusted Signing Certificates Profile Signer"
--scopes /subscriptions/YOUR_SUBSCRIPTION_ID/resourceGroups/MyAppSigning/suppliers/Microsoft.CodeSigning/codeSigningAccounts/myapp-signing
--json-auth
This outputs JSON like this:
{
"clientId": "12345678-1234-1234-1234-123456789abc",
"clientSecret": "super-secret-value-abc123",
"tenantId": "87654321-4321-4321-4321-cba987654321",
"subscriptionId": "abcdef12-3456-7890-abcd-ef1234567890"
}
SAVE THESE VALUES IMMEDIATELY! You may’t retrieve the clientSecret once more. That is tremendous essential.
Various: Azure Portal Methodology
If CLI would not work:
- Azure Portal → App registrations → New registration
- Title: “MyAppGitHubActions”
- Click on Register
- Copy the Utility (shopper) ID – that is
AZURE_CLIENT_ID - Copy the Listing (tenant) ID – that is
AZURE_TENANT_ID - Go to Certificates & secrets and techniques → New shopper secret
- Description: “GitHub Actions”
- Expiration: 24 months (max)
- Click on Add and instantly copy the Worth – that is
AZURE_CLIENT_SECRET - Go to your Trusted Signing Account → Entry management (IAM)
- Add position project → Trusted Signing Certificates Profile Signer
- Choose members → Seek for “MyAppGitHubActions”
- Evaluation + assign
Step 2: Add GitHub Secrets and techniques
Go to your GitHub repository:
- Settings → Secrets and techniques and variables → Actions
- Click on New repository secret for every:
AZURE_CLIENT_ID– From service principal output or App registrationAZURE_CLIENT_SECRET -From service principal output or Certificates & secrets and techniquesAZURE_TENANT_ID– From service principal output or App registrationAZURE_SUBSCRIPTION_ID– Azure Portal → Subscriptions
Safety Observe: These secrets and techniques are encrypted and by no means seen in logs. Solely your workflow can entry them. You may by no means see them once more.
Step 3: Replace Your GitHub Workflow
This can be a little complicated because it’s YAML, which is Devil’s markup, nevertheless it’s what we’ve got sunk to as a society.
Observe the dotnet-version beneath. Yours may be 8 or 9, and so forth. Additionally, I’m constructing each x64 and ARM variations and I’m utilizing GitVersion so in order for you a extra full construct.yml, you may go right here https://github.com/shanselman/WindowsEdgeLight/blob/grasp/.github/workflows/construct.yml I’m additionally zipping mine up and prepping my releases so my unfastened EXE lives in a ZIP file.
Add signing steps to your .github/workflows/construct.yml:
title: Construct and Signal
on:
push:
tags:
- 'v*'
workflow_dispatch:
permissions:
contents: write
jobs:
construct:
runs-on: windows-latest
steps:
- title: Checkout code
makes use of: actions/checkout@v4
with:
fetch-depth: 0
- title: Setup .NET
makes use of: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
- title: Restore dependencies
run: dotnet restore MyApp/MyApp.csproj
- title: Construct
run: |
dotnet publish MyApp/MyApp.csproj `
-c Launch `
-r win-x64 `
--self-contained
# === SIGNING STEPS START HERE ===
- title: Azure Login
makes use of: azure/login@v2
with:
creds: '{"clientId":"${{ secrets and techniques.AZURE_CLIENT_ID }}","clientSecret":"${{ secrets and techniques.AZURE_CLIENT_SECRET }}","subscriptionId":"${{ secrets and techniques.AZURE_SUBSCRIPTION_ID }}","tenantId":"${{ secrets and techniques.AZURE_TENANT_ID }}"}'
- title: Signal executables with Trusted Signing
makes use of: azure/trusted-signing-action@v0
with:
azure-tenant-id: ${{ secrets and techniques.AZURE_TENANT_ID }}
azure-client-id: ${{ secrets and techniques.AZURE_CLIENT_ID }}
azure-client-secret: ${{ secrets and techniques.AZURE_CLIENT_SECRET }}
endpoint: https://wus2.codesigning.azure.web/
trusted-signing-account-name: myapp-signing
certificate-profile-name: MyAppProfile
files-folder: ${{ github.workspace }}MyAppbinReleasenet10.0-windowswin-x64publish
files-folder-filter: exe
files-folder-recurse: true
file-digest: SHA256
timestamp-rfc3161: http://timestamp.acs.microsoft.com
timestamp-digest: SHA256
# === SIGNING STEPS END HERE ===
- title: Create Launch
if: startsWith(github.ref, 'refs/tags/')
makes use of: softprops/action-gh-release@v2
with:
recordsdata: MyApp/bin/Launch/net10.0-windows/win-x64/publish/MyApp.exe
env:
GITHUB_TOKEN: ${{ secrets and techniques.GITHUB_TOKEN }}
Key factors:
endpoint: Use YOUR area’s endpoint (wus2, eus, and so forth.)trusted-signing-account-name: Your account title (precise, case-sensitive)certificate-profile-name: Your certificates profile title (precise, case-sensitive)files-folder: Path to your compiled executablesfiles-folder-filter: File sorts to signal (exe, dll, and so forth.)files-folder-recurse: Signal recordsdata in subfolders
Step 4: Take a look at the Workflow
Now set off the workflow. You’ve two choices:
Choice A: Guide Set off (Most secure for testing)
For the reason that workflow consists of workflow_dispatch:, you may set off it manually with out making a tag:
# Set off manually by way of GitHub CLI
gh workflow run construct.yml
# Or go to GitHub internet UI:
# Actions tab → "Construct and Signal" workflow → "Run workflow" button
That is supreme for testing as a result of:
- No tag required
- Will not create a launch
- Can check a number of instances
- Straightforward to debug points
Choice B: Create a Tag (For precise releases)
# Ensure you're in your major department with no uncommitted adjustments
git standing
# Create and push a tag
git tag v1.0.0
git push origin v1.0.0
Use this once you’re able to create an precise launch with signed binaries. That is what I’m doing on my aspect.
Step 5: Monitor the Construct
Watch the progress with GitHub CLI:
# See newest runs
gh run checklist --limit 5
# Watch a particular run
gh run watch
# View detailed standing
gh run view --log
Or go to: https://github.com/YOUR_USERNAME/YOUR_REPO/actions
Search for:
- Azure Login – Ought to full in ~5 seconds
- Signal executables with Trusted Signing – Ought to full in ~10-30 seconds
- Create Launch – Your signed executable is now out there in /releases in your GitHib challenge
Frequent GitHub Actions Points
I hit a couple of of those, natch.
Subject: “403 Forbidden” throughout signing
- Trigger: Service principal would not have permissions
- Repair:
- Go to Azure Portal → Trusted Signing Account → Entry management (IAM)
- Confirm “MyAppGitHubActions” has “Trusted Signing Certificates Profile Signer” position
- If not, add it manually
Subject: “No recordsdata matched the sample”
- Trigger: Flawed
files-folderpath or construct artifacts in incorrect location - Repair:
- Add a debug step earlier than signing:
- run: Get-ChildItem -Recurse - Discover the place your EXE is definitely situated
- Replace
files-folderto match
- Add a debug step earlier than signing:
Subject: Secrets and techniques not working
- Trigger: Typo in secret title or worth not saved
- Repair:
- Confirm secret names EXACTLY match (case-sensitive)
- Re-create secrets and techniques if uncertain
- Ensure no further areas in values
Subject: “DefaultAzureCredential authentication failed”
- Trigger: Normally incorrect tenant ID or shopper ID
- Repair: Confirm all 4 secrets and techniques are right from service principal output
Half 4: Understanding the Certificates
Certificates Lifecycle
Azure Trusted Signing makes use of short-lived certificates (usually 3 days). This freaked me out however they are saying that is truly a safety function:
- If a certificates is compromised, it expires rapidly
- You by no means handle certificates recordsdata or passwords
- Automated renewal – you do not have to do something
However will not my signature break after 3 days?
No, evidently’s what timestamping is for. If you signal a file:
- Azure points a 3-day certificates
- The file is signed with that certificates
- A timestamp server information “this file was signed on DATE”
- Even after the certificates expires, the signature stays legitimate as a result of the timestamp proves it was signed when the certificates was legitimate
That is why each native and GitHub Actions signing embrace:
timestamp-rfc3161: http://timestamp.acs.microsoft.com
What the Certificates Comprises
Your signed executable has a certificates with:
- Topic: Your title (e.g., “CN=John Doe, O=John Doe, L=Seattle, S=Washington, C=US”)
- Issuer: Microsoft ID Verified CS EOC CA 01
- Legitimate Dates: 3-day window
- Key Measurement: 3072-bit RSA (very safe)
- Enhanced Key Utilization: Code Signing
Confirm Certificates on Any Machine
# Utilizing PowerShell
Get-AuthenticodeSignature "MyApp.exe" | Choose-Object -ExpandProperty SignerCertificate | Format-Record
# Utilizing Home windows UI
# Proper-click EXE → Properties → Digital Signatures tab → Particulars → View Certificates
This complete factor took me about an hour to 75 minutes. It was detailed, however not deeply troublesome. Misspellings, case-sensitivity, and some account points with Function-Based mostly Entry Management did gradual me down. Hope this helps!
Used Assets
Written in November 2025 primarily based on real-world implementation for WindowsEdgeLight. Your setup would possibly range barely relying on Azure area and account kind. Issues change, be stoic.
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, guide, father, diabetic, and Microsoft worker. He’s a failed stand-up comedian, a cornrower, and a e-book creator.


![8 steps to construct your account-based advertising and marketing technique [+ recommended tools]](https://blog.aimactgrow.com/wp-content/uploads/2025/06/account-based-marketing.webp-120x86.webp)







