Fix aspire-managed macOS signing, permissions, and add CI verification#16053
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 16053Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 16053" |
| IInteractionService interactionService, | ||
| AspireCliTelemetry telemetry, | ||
| ICliHostEnvironment hostEnvironment, | ||
| Func<bool>? isWindows = null) : ICertificateService |
There was a problem hiding this comment.
We want to skip it on macOS too, since it needs GUI interaction there.
There was a problem hiding this comment.
this is for mocking though right?
There was a problem hiding this comment.
Yes, restored it — renamed to isNonInteractiveTrustSupported (defaults to OperatingSystem.IsLinux) so tests can mock the OS check. The original isWindows was too narrow since we now skip trust on both macOS and Windows in non-interactive mode.
There was a problem hiding this comment.
Pull request overview
Fixes macOS signing/runtime issues for the aspire-managed bundle payload and hardens CI by adding post-signing archive verification, plus fallback Unix permission handling for Windows-built archives.
Changes:
- Add macOS JIT entitlements and an ad-hoc pre-signing step to preserve entitlements through MicroBuild signing; restore execute permissions post-sign.
- Add CLI archive verification scripts and wire them into pipelines (Windows + macOS/Linux).
- Ensure extracted bundle payload files get correct Unix modes when tar entries don’t carry permissions (notably for Windows-created tar archives), including
dcptun_c.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| eng/aspire-managed-entitlements.plist | Adds hardened-runtime entitlements needed for CoreCLR JIT and dylib loading on macOS. |
| eng/pipelines/templates/build_sign_native.yml | Adds macOS ad-hoc codesign + chmod restore + archive verification for runnable RIDs. |
| eng/pipelines/templates/BuildAndTest.yml | Adds Windows archive verification step after signing. |
| eng/scripts/verify-cli-archive.sh | New Linux/macOS verification script that exercises aspire --version and aspire new. |
| eng/scripts/verify-cli-archive.ps1 | New Windows verification script that exercises aspire --version and aspire new. |
| src/Aspire.Cli/Bundles/BundleService.cs | Applies fallback Unix modes on extraction when tar entries lack modes; includes dcptun_c. |
| src/Aspire.Cli/Certificates/CertificateService.cs | Skips interactive trust operations in non-interactive mode on macOS/Windows while allowing Linux to proceed. |
| tests/Aspire.Cli.Tests/Certificates/CertificateServiceTests.cs | Updates/extends tests for the new non-interactive trust behavior across platforms. |
| tools/CreateLayout/Program.cs | Sets Unix mode bits for key executables when creating tar archives on Windows. |
macOS hardened runtime blocks CoreCLR JIT (W^X memory mapping) unless the binary carries com.apple.security.cs.allow-jit and related entitlements. MicroBuild's MacDeveloperHardenWithNotarization signing preserves entitlements from a prior ad-hoc signature, so we codesign with the entitlements plist before Arcade signing. This follows the same pattern used by dotnet/sdk for Roslyn managed binaries (roslyn-entitlements.plist). Fixes #16043 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
MicroBuild rewrites the binary file during signing, which resets Unix file permissions to the default umask (typically 644). The execute bit must be restored before CreateLayout packs the binary into the CLI archive. Without this, macOS and Linux archives contain a non-executable aspire-managed binary. Fixes #16043 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Previously, CertificateService skipped the certificate trust operation only on Windows in non-interactive mode. On macOS, the trust operation would hang waiting for a Keychain password prompt in CI environments. Broaden the skip to both macOS and Windows in non-interactive mode, but allow Linux trust to proceed since it is non-interactive by nature (update-ca-certificates does not prompt). Remove the injected isWindows function in favor of direct OperatingSystem.IsLinux() check, which is simpler and more correct. Add a new test (EnsureCertificatesTrustedAsync_NonInteractiveNonWindows_ WithNotTrustedCert_SkipsTrustOperation) to validate the macOS CI behavior, and update existing tests to be platform-aware. Fixes #16043 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add verify-cli-archive.sh (Linux/macOS) and verify-cli-archive.ps1
(Windows) scripts that validate a signed CLI archive by:
1. Extracting the archive to a temp location
2. Running 'aspire --version' to verify the binary executes
3. Running 'aspire new aspire-starter' to test bundle self-extraction
and project creation (exercises aspire-managed)
4. Cleaning up temp state (backs up and restores ~/.aspire)
These scripts will be wired into the CI pipeline to catch signing and
permissions regressions before they reach users.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add post-signing verification steps to both build_sign_native.yml (macOS/Linux) and BuildAndTest.yml (Windows) that run the verification scripts after the CLI archives are built and signed. Verification runs for RIDs that can fully execute on the build agent: - macOS (Apple Silicon): osx-arm64 only - Linux (amd64): linux-x64 only - Windows: win-x64 This ensures that signing/permissions regressions (like the ones fixed in this PR) are caught during the official build before release. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
60a6227 to
720df97
Compare
- Restore mockable isNonInteractiveTrustSupported parameter in CertificateService for testability (was Func<bool> isWindows) - Fix cert tests to use explicit mocks instead of OS-dependent assertions - Move backup dir into VERIFY_TMPDIR to avoid orphaned temp dirs - Fix BuildAndTest.yml comment to match actual script behavior Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Re: build_sign_native.yml comment about macOS/Linux The comment is actually correct — |
|
Internal validation build triggered: https://dev.azure.com/dnceng/internal/_build/results?buildId=2948628 |
|
/create-issue |
|
Failed tests found on this PR:
📋 Creates or updates a failing-test issue from CI failures. |
|
/create-issue Aspire.Hosting.Tests.Backchannel.Exec.ContainerResourceExecTests.Exec_NginxContainer_ListFiles_ProducesLogs_Success |
|
🎬 CLI E2E Test Recordings — 58 recordings uploaded (commit View recordings
📹 Recordings uploaded automatically from CI run #24273345519 |
|
/backport to release/13.2 |
|
Started backporting to |
|
@joperezr backporting to git am output$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patch
Applying: Add macOS JIT entitlements and ad-hoc codesign step for aspire-managed
Using index info to reconstruct a base tree...
M eng/pipelines/templates/build_sign_native.yml
Falling back to patching base and 3-way merge...
Auto-merging eng/pipelines/templates/build_sign_native.yml
CONFLICT (content): Merge conflict in eng/pipelines/templates/build_sign_native.yml
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Patch failed at 0001 Add macOS JIT entitlements and ad-hoc codesign step for aspire-managed
Error: The process '/usr/bin/git' failed with exit code 128 |
…rt trust, and CI verification (#16215) * Add macOS JIT entitlements and ad-hoc codesign step for aspire-managed macOS hardened runtime blocks CoreCLR JIT (W^X memory mapping) unless the binary carries com.apple.security.cs.allow-jit and related entitlements. MicroBuild's MacDeveloperHardenWithNotarization signing preserves entitlements from a prior ad-hoc signature, so we codesign with the entitlements plist before Arcade signing. This follows the same pattern used by dotnet/sdk for Roslyn managed binaries (roslyn-entitlements.plist). Fixes #16043 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: joperezr <13854455+joperezr@users.noreply.github.com> * Restore execute permissions on aspire-managed after MicroBuild signing MicroBuild rewrites the binary file during signing, which resets Unix file permissions to the default umask (typically 644). The execute bit must be restored before CreateLayout packs the binary into the CLI archive. Without this, macOS and Linux archives contain a non-executable aspire-managed binary. Fixes #16043 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: joperezr <13854455+joperezr@users.noreply.github.com> * Narrow non-interactive cert trust skip to macOS and Windows only Backport of fbdac8a with conflict resolution: - Added EnsureHttpCertificateExists() to ICertificateToolRunner and NativeCertificateToolRunner - Added ICliHostEnvironment parameter to CertificateService constructor - Updated CliTestHelper default CertificateServiceFactory to pass ICliHostEnvironment - Added IsSuccessfulEnsureResult helper method - Added TestCliHostEnvironment and new non-interactive test cases Co-authored-by: joperezr <13854455+joperezr@users.noreply.github.com> * Add CLI archive verification scripts Add verify-cli-archive.sh (Linux/macOS) and verify-cli-archive.ps1 (Windows) scripts that validate a signed CLI archive by: 1. Extracting the archive to a temp location 2. Running 'aspire --version' to verify the binary executes 3. Running 'aspire new aspire-starter' to test bundle self-extraction and project creation (exercises aspire-managed) 4. Cleaning up temp state (backs up and restores ~/.aspire) These scripts will be wired into the CI pipeline to catch signing and permissions regressions before they reach users. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: joperezr <13854455+joperezr@users.noreply.github.com> * Wire CLI archive verification into CI pipelines Add post-signing verification steps to both build_sign_native.yml (macOS/Linux) and BuildAndTest.yml (Windows) that run the verification scripts after the CLI archives are built and signed. Verification runs for RIDs that can fully execute on the build agent: - macOS (Apple Silicon): osx-arm64 only - Linux (amd64): linux-x64 only - Windows: win-x64 This ensures that signing/permissions regressions (like the ones fixed in this PR) are caught during the official build before release. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: joperezr <13854455+joperezr@users.noreply.github.com> * Address PR feedback: restore testability and fix scripts - Restore mockable isNonInteractiveTrustSupported parameter in CertificateService for testability (was Func<bool> isWindows) - Fix cert tests to use explicit mocks instead of OS-dependent assertions - Move backup dir into VERIFY_TMPDIR to avoid orphaned temp dirs - Fix BuildAndTest.yml comment to match actual script behavior Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: joperezr <13854455+joperezr@users.noreply.github.com> * Add EnsureHttpCertificateExists to shared TestCertificateToolRunner The TestCertificateToolRunner in TestServices/ also needs to implement the EnsureHttpCertificateExists method added to ICertificateToolRunner as part of the backport. Co-authored-by: joperezr <13854455+joperezr@users.noreply.github.com> * Remove non-entitlement changes from backport Keep only macOS entitlements plist and build_sign_native.yml signing changes. Remove CI verification scripts, cert trust changes, and related test updates. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add CI verification scripts for signed CLI archives Restore BuildAndTest.yml wiring and verify-cli-archive scripts to validate signed archives work correctly after signing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Ankit Jain <radical@gmail.com> Co-authored-by: joperezr <13854455+joperezr@users.noreply.github.com> Co-authored-by: Copilot <copilot@github.com> Co-authored-by: Jose Perez Rodriguez <joperezr@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Description
Fixes #16043
Problem
The
aspire-managedbinary on macOS was broken after signing due to multiple issues:com.apple.security.cs.allow-jitand related entitlements. The signed binary would crash on launch withHRESULT: 0x80070008.aspire-managedbinaries.Fix
eng/aspire-managed-entitlements.plist) and ad-hoc codesign with entitlements before MicroBuild signing. MicroBuild preserves entitlements from the prior ad-hoc signature when re-signing with the real certificate. This follows the same pattern used bydotnet/sdkfor Roslyn managed binaries.chmod +x) after MicroBuild signing on macOS/Linux, before CreateLayout packs the binary into the archive.isWindowsfunction in favor of a simplerOperatingSystem.IsLinux()check.Validation
verify-cli-archive.sh(Linux/macOS) andverify-cli-archive.ps1(Windows) scripts that run after signing to validate the archive by extracting it, runningaspire --version, and creating a project withaspire new. Wired intobuild_sign_native.yml(osx-arm64, linux-x64) andBuildAndTest.yml(win-x64).EnsureCertificatesTrustedAsync_NonInteractiveNonWindows_WithNotTrustedCert_SkipsTrustOperationvalidates the macOS CI cert trust behavior.Checklist