Azure artifact signing with new az-sign command#595
Conversation
Build Metrics ReportBinary Sizes
Test Results✅ 1581 passed, 1 skipped out of 1582 tests in 425.1s (+36 tests, +9.6s vs. baseline) Test Coverage❌ 18.3% line coverage, 37.4% branch coverage · ✅ +0.3% vs. baseline CLI Startup Time43ms median (x64, Updated 2026-07-08 01:40:59 UTC · commit |
There was a problem hiding this comment.
Pull request overview
This PR adds a new winapp az-sign command that code-signs .exe, .msix, or .msixbundle files using Azure Trusted Signing (a cloud-managed signing identity), complementing the existing local-certificate winapp sign command. The feature is decomposed into three DI-registered, interface-backed services and reuses the shared BuildToolsService.RunBuildToolAsync runner (which is hardened here to drain stdout/stderr concurrently and kill on cancellation, fixing a latent deadlock for all build-tool callers). It integrates cleanly with the CLI help groups, the npm SDK wrapper, the VS Code extension, and the auto-generated docs/skills pipeline.
Changes:
- New
az-signcommand +AzureAuthService(credential chain with interactiveaz loginfallback and tenant validation),AzureSigningService(NativeAOT-friendly ARM REST discovery), andAzureSignToolService(pinned Trusted Signing dlib + architecture-matched signtool). RunBuildToolAsyncgains atoolPathOverride+environmentparameter and concurrent pipe draining/kill-on-cancel; all callers, implementers, and test fakes updated.- Comprehensive unit tests, a new
Azure.Identitydependency, and synced docs (usage, skills, agent files, cli-schema, npm wrapper, VS Code command).
Reviewed changes
Copilot reviewed 31 out of 31 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
Commands/AzSignCommand.cs |
New command: flag validation, resource discovery/selection, metadata generation/cleanup, signing orchestration |
Services/AzureAuthService.cs (+IAzureAuthService.cs) |
Credential chain, tenant validation, az login fallback with hardened process handling |
Services/AzureSigningService.cs (+IAzureSigningService.cs) |
Raw-HTTP ARM discovery of subscriptions/accounts/profiles + records |
Services/AzureSignToolService.cs (+IAzureSignToolService.cs) |
Acquires pinned dlib, arch-matches signtool, drives signing |
Services/BuildToolsService.cs (+IBuildToolsService.cs) |
New overload; concurrent stream draining + kill-on-cancel |
Helpers/HostBuilderExtensions.cs, Commands/WinAppRootCommand.cs |
DI + command registration and help grouping |
Directory.Packages.props, WinApp.Cli.csproj |
Add Azure.Identity 1.21.0 |
WinApp.Cli.Tests/* |
New tests (command/auth/signing) + fake signature updates |
src/winapp-VSC/*, src/winapp-npm/src/winapp-commands.ts |
VS Code azSign command + npm SDK wrapper |
docs/*, .github/plugin/*, .claude/*, scripts/generate-llm-docs.ps1 |
Docs/skills/agent + schema updates |
Notes for the author (beyond the inline comments): the README.md "Certificates & Signing" curated command list still shows only sign and was not updated for az-sign (that file isn't part of this diff, so no inline comment could be attached). This is a draft touching security-sensitive signing, Azure auth/network calls, and a shared build-tool runner used by every signtool/makeappx/makepri caller.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Add
winapp az-sign— Azure Trusted Signing supportfixes #359
Summary
Adds a new
winapp az-signcommand that code-signs an.exe,.msix, or.msixbundleusing Azure Trusted Signing — a cloud-managed signing identity, so no private key/PFX
ever lives on the machine. Complements the existing local-certificate
winapp signcommandand works both interactively and in CI/CD.
Screen.Recording.2026-06-30.183250.mp4
What's new for users
Auth: uses Azure's standard DefaultAzureCredential chain (env/service-principal, OIDC,
managed identity). Interactively, if no credentials are found and the Azure CLI is installed,
it runs az login for you. Requires a Trusted Signing account + certificate profile and the
Trusted Signing Certificate Profile Signer role.
Architecture
The feature is split into focused, DI-registered services behind interfaces:
• AzSignCommand — argument parsing, flag-dependency validation, resource
discovery/selection, confirmation, and metadata.json generation/cleanup.
• AzureAuthService ( IAzureAuthService ) — credential-chain acquisition with interactive
az login fallback; tenant-ID validation.
• AzureSigningService ( IAzureSigningService ) — NativeAOT-friendly raw-HTTP/System.Text.Json
calls to ARM to list subscriptions, signing accounts, and certificate profiles.
• AzureSignToolService ( IAzureSignToolService ) — acquires the pinned Trusted Signing dlib
from NuGet and drives signtool (architecture-matched) to sign.
• New dependency: Azure.Identity (the signing dlib itself is fetched at runtime, not a
compile-time reference).
Hardening (from PR review)
• Security: tenant ID validated against a GUID/domain allow-list and passed via
ProcessStartInfo.ArgumentList , closing an az login argument-injection vector; the signing
dlib version is pinned (reproducible) and resolved by semantic (not lexicographic) version
ordering.
• Robustness: concurrent stdout/stderr draining + kill-on-cancel to prevent process pipe
deadlocks — centralized in BuildToolsService.RunBuildToolAsync (now also takes a tool-path
override + extra env vars), which AzureSignToolService reuses instead of hand-rolling
Process.Start . This fixes a latent deadlock for all build-tool callers.
• UX/correctness: confirmation prompt is skipped when the identity is fully specified or the
session is non-interactive; --metadata-file existence is checked before any Azure work
(fail-fast); removed a colliding -a short alias; interactive progress now goes through
ILogger so --quiet is honored.
Tests
New/updated unit tests covering the command flow, auth branches (primary success, non-interactive
failure, no-CLI, login success/failure), the ARM REST layer (URL building, JSON/error parsing via
an injected HttpClient ), tenant validation, and signtool success/failure. Full non-E2E suite:
1343 passed, 0 failed; clean Debug + Release builds; VS Code extension compiles and lints.
Tooling & docs
• VS Code: new "Sign Package with Azure Trusted Signing" command.
• Docs/agent context: docs/usage.md , the signing skill fragment, the winapp agent reference
• decision tree, and the skill-command map all document az-sign ; autogenerated
cli-schema.json , plugin skills, .claude mirror, and the npm
winapp-commands.ts / npm-usage.md wrappers regenerated.
Notes
• The Trusted Signing client dlib is downloaded on first use (NuGet global cache), so the first
az-sign run may take longer.