Skip to content

Fix signing for aspire-managed bundle payload#16016

Merged
joperezr merged 1 commit intomicrosoft:mainfrom
joperezr:dev/joperezr/fix-aspire-managed-signing
Apr 9, 2026
Merged

Fix signing for aspire-managed bundle payload#16016
joperezr merged 1 commit intomicrosoft:mainfrom
joperezr:dev/joperezr/fix-aspire-managed-signing

Conversation

@joperezr
Copy link
Copy Markdown
Member

@joperezr joperezr commented Apr 9, 2026

Fixes #15989

Description

Fix the CLI bundle signing gap where aspire-managed was not being signed before being packed into the bundle archive.

Root cause: The managed bundle payload was published via Bundle.proj using a standalone dotnet publish call, which runs outside of Arcade's signing infrastructure. By the time Arcade's signing phase ran during the main build, aspire-managed was already packed inside bundle.tar.gz and embedded in the native aspire CLI binary — unreachable by the signing tooling.

Approach

Split the bundle payload pipeline step into three phases so that aspire-managed goes through Arcade's standard signing infrastructure before CreateLayout packs it into the archive:

  1. dotnet publish — produces the self-contained single-file aspire-managed binary
  2. build.cmd/sh -restore -sign — Arcade's SignToolTask discovers the binary via ItemsToSign globs in Signing.props and signs it in-place using ESRP/MicroBuild
  3. Bundle.proj /t:_RestoreDcpPackage;_RunCreateLayout — creates the bundle.tar.gz archive with the already-signed binary

Changes

  • eng/Signing.props: Register aspire-managed.exe / aspire-managed in FileSignInfo (certificate mapping) and ItemsToSign (glob pointing at publish output path)
  • eng/pipelines/templates/BuildAndTest.yml: Replace single Bundle.proj step with the three-phase publish -> sign -> layout flow per target RID
  • eng/pipelines/templates/build_sign_native.yml: Same restructuring for macOS/Linux native stage. Sign step is conditional on codeSign: true (macOS only; Linux ELF binaries are not signed)

Validation

Tested via internal ADO build 2947441. The signing step reported:

SignToolTask starting.
Signing mode: Real
Round 0: Signing 2 files
Build artifacts signed and validated.

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
    • No
  • Does the change require an update in our Aspire docs?
    • No

Copilot AI review requested due to automatic review settings April 9, 2026 20:38
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 9, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 16016

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 16016"

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates the official build/signing pipeline so the aspire-managed bundle payload is signed before it is archived into bundle.tar.gz and embedded into the native Aspire CLI.

Changes:

  • Register aspire-managed in eng/Signing.props (FileSignInfo + ItemsToSign) so Arcade signing can discover and sign the published binary.
  • Restructure the Windows official build template to publish -> sign -> create layout per RID before the main build/sign step.
  • Apply the same publish -> (conditional) sign -> create layout flow in the macOS/Linux native build template.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
eng/Signing.props Adds signing metadata and discovery globs for aspire-managed publish outputs.
eng/pipelines/templates/BuildAndTest.yml Splits bundle payload generation to ensure aspire-managed is signed before bundling (Windows stage).
eng/pipelines/templates/build_sign_native.yml Mirrors the pre-bundle signing flow for macOS/Linux native build jobs (signing conditional).

Comment on lines 49 to +68
- ${{ each targetRid in parameters.targetRids }}:
- script: ${{ parameters.dotnetScript }}
publish
$(Build.SourcesDirectory)/src/Aspire.Managed/Aspire.Managed.csproj
-c ${{ parameters.buildConfig }}
-r ${{ targetRid }}
--self-contained
/p:GenerateDocumentationFile=false
/p:EnforceCodeStyleInBuild=false
$(_OfficialBuildIdArgs)
/bl:${{ parameters.repoLogPath }}/PublishManaged-${{ targetRid }}.binlog
displayName: 🟣Publish aspire-managed (${{ targetRid }})

- script: ${{ parameters.buildScript }}
-restore -sign $(_SignArgs)
-configuration ${{ parameters.buildConfig }}
$(_OfficialBuildIdArgs)
-projects $(Build.SourcesDirectory)/src/Aspire.Managed/Aspire.Managed.csproj
/bl:${{ parameters.repoLogPath }}/SignManaged-${{ targetRid }}.binlog
displayName: 🟣Sign aspire-managed (${{ targetRid }})
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

The Sign aspire-managed step is executed once per targetRid even though ItemsToSign uses a broad $(ArtifactsBinDir)Aspire.Managed\**\publish\aspire-managed.exe glob. With multiple RIDs (win-x64 + win-arm64) this will re-run restore/sign and can end up re-processing already-signed artifacts, increasing build time and introducing avoidable variability. Consider publishing all RIDs first, then running a single signing pass, or narrow the signing invocation/glob to only the current RID’s publish directory.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good catch on the broad glob. We'll address this in a follow-up PR to keep the scope of this change focused.

Comment on lines +71 to +80
- script: >-
$(Build.SourcesDirectory)/$(dotnetScript)
publish
$(Build.SourcesDirectory)/src/Aspire.Managed/Aspire.Managed.csproj
-c $(_BuildConfig)
-r ${{ targetRid }}
--self-contained
/p:GenerateDocumentationFile=false
/p:EnforceCodeStyleInBuild=false
/bl:$(Build.Arcade.LogsPath)PublishManaged.binlog
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

Publish aspire-managed here doesn’t include ${{ parameters.extraBuildArgs }} (which in this pipeline is where $(_OfficialBuildIdArgs) is passed). That means the bundle payload’s aspire-managed binary may be version-stamped differently from the rest of the official build and from the Windows build path. Consider passing the same official/versioning args to the dotnet publish (and, if relevant, the Bundle.proj layout) step so the signed payload matches the build’s intended version metadata.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good catch - fixed. Added extraBuildArgs to the publish step so it gets the same OfficialBuildIdArgs for consistent versioning.

@joperezr joperezr force-pushed the dev/joperezr/fix-aspire-managed-signing branch from 9416197 to fc6cc93 Compare April 9, 2026 20:55
Split the bundle payload pipeline step into three phases so that
aspire-managed goes through Arcade's signing infrastructure before
CreateLayout packs it into the bundle archive:

1. dotnet publish - produces the self-contained single-file binary
2. build.cmd/sh -restore -sign - Arcade signs it via ItemsToSign
3. Bundle.proj /t:_RestoreDcpPackage;_RunCreateLayout - creates the
   tar.gz archive with the already-signed binary

Changes:
- eng/Signing.props: Add FileSignInfo and ItemsToSign entries for
  aspire-managed.exe (Windows) and aspire-managed (Linux/macOS)
- eng/pipelines/templates/BuildAndTest.yml: Split bundle payload step
  into publish, sign, and layout steps per RID
- eng/pipelines/templates/build_sign_native.yml: Same restructuring
  for macOS/Linux native stage (sign step conditional on codeSign)

Fixes microsoft#15989

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@joperezr joperezr force-pushed the dev/joperezr/fix-aspire-managed-signing branch from fc6cc93 to 3060546 Compare April 9, 2026 21:01
@joperezr joperezr merged commit 4fa5ebe into microsoft:main Apr 9, 2026
524 of 527 checks passed
Copy link
Copy Markdown
Member

@JamesNK JamesNK left a comment

Choose a reason for hiding this comment

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

Clean, well-structured fix. The three-phase publish → sign → layout split correctly ensures aspire-managed is signed before being packed into the bundle archive. Signing.props entries are consistent with existing patterns, and the pipeline restructuring in both BuildAndTest.yml and build_sign_native.yml is correct.

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.

aspire-managed.exe is not digitally signed

4 participants