Skip to content

Azure artifact signing with new az-sign command#595

Open
zateutsch wants to merge 10 commits into
mainfrom
zt/359-azure-signing
Open

Azure artifact signing with new az-sign command#595
zateutsch wants to merge 10 commits into
mainfrom
zt/359-azure-signing

Conversation

@zateutsch

@zateutsch zateutsch commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Add winapp az-sign — Azure Trusted Signing support

fixes #359

Summary

Adds a new winapp az-sign command that code-signs an .exe, .msix, or .msixbundle
using Azure Trusted Signing — a cloud-managed signing identity, so no private key/PFX
ever lives on the machine. Complements the existing local-certificate winapp sign command
and works both interactively and in CI/CD.

Screen.Recording.2026-06-30.183250.mp4

What's new for users

# Interactive — discovers/prompts for subscription, account, profile
winapp az-sign ./app.msix

# Fully specified — no prompting (CI/CD)
winapp az-sign ./app.msix -s <sub> -r <rg> --account <acct> -p <profile>

# Reuse an existing metadata.json (skips discovery)
winapp az-sign ./app.msix -m ./metadata.json

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.

@github-actions

github-actions Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Build Metrics Report

Binary Sizes

Artifact Baseline Current Delta
CLI (ARM64) 31.71 MB 35.79 MB 📈 +4.08 MB (+12.86%)
CLI (x64) 32.04 MB 36.00 MB 📈 +3.97 MB (+12.38%)
MSIX (ARM64) 13.30 MB 14.93 MB 📈 +1.63 MB (+12.26%)
MSIX (x64) 14.15 MB 15.86 MB 📈 +1.71 MB (+12.06%)
NPM Package 27.77 MB 31.15 MB 📈 +3.38 MB (+12.16%)
NuGet Package 27.79 MB 31.19 MB 📈 +3.40 MB (+12.23%)
VS Code Extension 20.60 MB 23.98 MB 📈 +3.38 MB (+16.43%)

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 Time

43ms median (x64, winapp --version) · ✅ no change vs. baseline


Updated 2026-07-08 01:40:59 UTC · commit 01e3a54 · workflow run

@zateutsch zateutsch marked this pull request as ready for review July 1, 2026 00:12
Copilot AI review requested due to automatic review settings July 1, 2026 00:12
@zateutsch zateutsch changed the title [DRAFT] Azure artifact signing with new az-sign command Azure artifact signing with new az-sign command Jul 1, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-sign command + AzureAuthService (credential chain with interactive az login fallback and tenant validation), AzureSigningService (NativeAOT-friendly ARM REST discovery), and AzureSignToolService (pinned Trusted Signing dlib + architecture-matched signtool).
  • RunBuildToolAsync gains a toolPathOverride + environment parameter and concurrent pipe draining/kill-on-cancel; all callers, implementers, and test fakes updated.
  • Comprehensive unit tests, a new Azure.Identity dependency, 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.

Comment thread src/winapp-CLI/WinApp.Cli/Commands/AzSignCommand.cs Outdated
Comment thread src/winapp-CLI/WinApp.Cli/Commands/AzSignCommand.cs Outdated
Comment thread src/winapp-CLI/WinApp.Cli/Services/IAzureAuthService.cs Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Artifact signing support

2 participants