Skip to content

Add logging if we detect the app host is running with an untrusted dev cert#14666

Merged
danegsta merged 34 commits intorelease/13.2from
danegsta/trustLog
Mar 9, 2026
Merged

Add logging if we detect the app host is running with an untrusted dev cert#14666
danegsta merged 34 commits intorelease/13.2from
danegsta/trustLog

Conversation

@danegsta
Copy link
Member

Description

It's possible, particularly after .NET SDK updates, to end up in a situation where there's a newer dev cert added to the CurrentUser/My cert store (which is the source of dev certs for TLS termination), but not to the CurrentUser/Root cert store which is where trusted certificates are pulled from. This can lead to a situation where services try to terminate HTTPS endpoints with an updated dev cert, but nothing actually trusts the new certificate. Diagnosing the issue is confusing and can require checking the logs for individual services.

This adds an explicit error level log if automatic dev cert trust is enabled and the latest certificate isn't in the trusted root store.

This replaces #13943 in targeting release/13.2.

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?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • 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
    • No
  • Does the change require an update in our Aspire docs?

@danegsta danegsta requested a review from mitchdenny as a code owner February 25, 2026 00:45
Copilot AI review requested due to automatic review settings February 25, 2026 00:45
@github-actions
Copy link
Contributor

github-actions bot commented Feb 25, 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/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 14666

Or

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

Copy link
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

This PR improves diagnosability when Aspire is configured to automatically trust the ASP.NET Core development certificate but the newest dev cert is not actually trusted by the OS trust store, by surfacing an app-host log and a dashboard notification.

Changes:

  • Add a dev-certificate trust check during DcpHost startup and emit a dashboard notification when the latest dev cert isn’t trusted.
  • Add cross-platform trust detection helper in DeveloperCertificateService (Root store check on Windows/Linux; security verify-cert on macOS).
  • Ensure the dashboard resource can be configured with a Kestrel certificate callback when HTTPS endpoints are present, plus add new localized strings and update tests.

Reviewed changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/Aspire.Hosting.Tests/Dcp/DcpHostNotificationTests.cs Updates DcpHost construction in tests to pass new dependencies.
tests/Aspire.Hosting.Tests/Dashboard/DashboardResourceTests.cs Adds a test validating the dashboard resource is annotated with an HTTPS/Kestrel certificate callback when using HTTPS.
src/Aspire.Hosting/DeveloperCertificateService.cs Adds certificate trust probing helper and disposes unused cert instances.
src/Aspire.Hosting/Dcp/DcpHost.cs Runs dev-cert trust check at startup and prompts a dashboard notification when trust is missing.
src/Aspire.Hosting/Dashboard/DashboardEventHandlers.cs Adds logic to attach a Kestrel certificate configuration callback when dashboard endpoints include HTTPS.
src/Aspire.Hosting/AspireEventSource.cs Adds EventSource events for dev-cert trust check start/stop.
src/Aspire.Hosting/Resources/InteractionStrings.resx Adds new strings for “development certificate not fully trusted” title/message.
src/Aspire.Hosting/Resources/InteractionStrings.Designer.cs Regenerates strongly-typed resource accessors for the new strings.
src/Aspire.Hosting/Resources/xlf/InteractionStrings.cs.xlf Adds new string IDs for translation (state=new).
src/Aspire.Hosting/Resources/xlf/InteractionStrings.de.xlf Adds new string IDs for translation (state=new).
src/Aspire.Hosting/Resources/xlf/InteractionStrings.es.xlf Adds new string IDs for translation (state=new).
src/Aspire.Hosting/Resources/xlf/InteractionStrings.fr.xlf Adds new string IDs for translation (state=new).
src/Aspire.Hosting/Resources/xlf/InteractionStrings.it.xlf Adds new string IDs for translation (state=new).
src/Aspire.Hosting/Resources/xlf/InteractionStrings.ja.xlf Adds new string IDs for translation (state=new).
src/Aspire.Hosting/Resources/xlf/InteractionStrings.ko.xlf Adds new string IDs for translation (state=new).
src/Aspire.Hosting/Resources/xlf/InteractionStrings.pl.xlf Adds new string IDs for translation (state=new).
src/Aspire.Hosting/Resources/xlf/InteractionStrings.pt-BR.xlf Adds new string IDs for translation (state=new).
src/Aspire.Hosting/Resources/xlf/InteractionStrings.ru.xlf Adds new string IDs for translation (state=new).
src/Aspire.Hosting/Resources/xlf/InteractionStrings.tr.xlf Adds new string IDs for translation (state=new).
src/Aspire.Hosting/Resources/xlf/InteractionStrings.zh-Hans.xlf Adds new string IDs for translation (state=new).
src/Aspire.Hosting/Resources/xlf/InteractionStrings.zh-Hant.xlf Adds new string IDs for translation (state=new).
Files not reviewed (1)
  • src/Aspire.Hosting/Resources/InteractionStrings.Designer.cs: Language not supported

@github-actions
Copy link
Contributor

github-actions bot commented Feb 25, 2026

🎬 CLI E2E Test Recordings

The following terminal recordings are available for commit 1f08c4e:

Test Recording
AddPackageInteractiveWhileAppHostRunningDetached ▶️ View Recording
AddPackageWhileAppHostRunningDetached ▶️ View Recording
AgentCommands_AllHelpOutputs_AreCorrect ▶️ View Recording
AgentInitCommand_DefaultSelection_InstallsSkillOnly ▶️ View Recording
AgentInitCommand_MigratesDeprecatedConfig ▶️ View Recording
AspireUpdateRemovesAppHostPackageVersionFromDirectoryPackagesProps ▶️ View Recording
Banner_DisplayedOnFirstRun ▶️ View Recording
Banner_DisplayedWithExplicitFlag ▶️ View Recording
CreateAndDeployToDockerCompose ▶️ View Recording
CreateAndDeployToDockerComposeInteractive ▶️ View Recording
CreateAndPublishToKubernetes ▶️ View Recording
CreateAndRunAspireStarterProject ▶️ View Recording
CreateAndRunAspireStarterProjectWithBundle ▶️ View Recording
CreateAndRunJsReactProject ▶️ View Recording
CreateAndRunPythonReactProject ▶️ View Recording
CreateAndRunTypeScriptStarterProject ▶️ View Recording
CreateEmptyAppHostProject ▶️ View Recording
CreateStartAndStopAspireProject ▶️ View Recording
CreateStartWaitAndStopAspireProject ▶️ View Recording
CreateTypeScriptAppHostWithViteApp ▶️ View Recording
DescribeCommandResolvesReplicaNames ▶️ View Recording
DescribeCommandShowsRunningResources ▶️ View Recording
DetachFormatJsonProducesValidJson ▶️ View Recording
DoctorCommand_DetectsDeprecatedAgentConfig ▶️ View Recording
DoctorCommand_WithSslCertDir_ShowsTrusted ▶️ View Recording
DoctorCommand_WithoutSslCertDir_ShowsPartiallyTrusted ▶️ View Recording
LogsCommandShowsResourceLogs ▶️ View Recording
PsCommandListsRunningAppHost ▶️ View Recording
PsFormatJsonOutputsOnlyJsonToStdout ▶️ View Recording
RestoreGeneratesSdkFiles ▶️ View Recording
SecretCrudOnDotNetAppHost ▶️ View Recording
SecretCrudOnTypeScriptAppHost ▶️ View Recording
StagingChannel_ConfigureAndVerifySettings_ThenSwitchChannels ▶️ View Recording
StopAllAppHostsFromAppHostDirectory ▶️ View Recording
StopAllAppHostsFromUnrelatedDirectory ▶️ View Recording
StopNonInteractiveMultipleAppHostsShowsError ▶️ View Recording
StopNonInteractiveSingleAppHost ▶️ View Recording
StopWithNoRunningAppHostExitsSuccessfully ▶️ View Recording
TypeScriptAppHostWithProjectReferenceIntegration ▶️ View Recording

📹 Recordings uploaded automatically from CI run #22814938132

@danegsta
Copy link
Member Author

@karolz-ms @joperezr heads up but we'll have to decide how we want to deal with a merge conflict in AspireEventSource.cs between this PR and #14557

public async Task StartAsync(CancellationToken cancellationToken)
{
await EnsureDcpContainerRuntimeAsync(cancellationToken).ConfigureAwait(false);
await EnsureDevelopmentCertificateTrustAsync(cancellationToken).ConfigureAwait(false);
Copy link
Member

Choose a reason for hiding this comment

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

Why in the DCP host? Doesn't seem DCP related to me.

What about doing it in an app host event? For example, Seb added detection for whether secrets are disable and you have persistent container in an app host event.

Copy link
Member Author

Choose a reason for hiding this comment

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

This was purely because it's the place we're doing existing startup runtime dependency checks (the container health check also lives here). We may be able to decide on a better location, but for now this is a location of convenience.

/// <inheritdoc />
public bool UseForHttps { get; }

internal static async Task<bool> IsCertificateTrustedAsync(IFileSystemService fileSystemService, X509Certificate2 certificate, CancellationToken cancellationToken = default)
Copy link
Member

Choose a reason for hiding this comment

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

Someone else will have to review this. I'm not an expert in this area.

Copy link
Member Author

Choose a reason for hiding this comment

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

This was reviewed in the previous version of the PR that stalled out due to a test issue that's now fixed. I re-opened because the old one was targeting main instead of release/13.2.

Co-authored-by: Damian Edwards <damian@damianedwards.com>
@danegsta
Copy link
Member Author

danegsta commented Mar 7, 2026

@copilot update other strings in the PR that reference running dotnet dev-certs commands to use the See https://aka.ms/aspire/devcerts for more information. reference instead.

Copy link
Contributor

Copilot AI commented Mar 7, 2026

@danegsta I've opened a new pull request, #15042, to work on those changes. Once the pull request is ready, I'll request review from you.

…v cert (#15042)

* Initial plan

* Replace dotnet dev-certs command references with aka.ms/aspire/devcerts link

Co-authored-by: danegsta <50252651+danegsta@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: danegsta <50252651+danegsta@users.noreply.github.com>
@danegsta
Copy link
Member Author

danegsta commented Mar 7, 2026

@copilot there's a failing test that's looking for outdated strings after the latest changes.

Copy link
Contributor

Copilot AI commented Mar 7, 2026

@danegsta I've opened a new pull request, #15043, to work on those changes. Once the pull request is ready, I'll request review from you.

…/devcerts (#15043)

* Initial plan

* Fix failing test that was checking for outdated string content after log message update

Co-authored-by: danegsta <50252651+danegsta@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: danegsta <50252651+danegsta@users.noreply.github.com>
Copy link
Contributor

Copilot AI commented Mar 8, 2026

@danegsta I've opened a new pull request, #15048, to work on those changes. Once the pull request is ready, I'll request review from you.

…ificate" in user-facing strings (#15048)

* Initial plan

* Replace "ASP.NET Core Development Certificate" with "development certificate" in strings

Co-authored-by: danegsta <50252651+danegsta@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: danegsta <50252651+danegsta@users.noreply.github.com>
@danegsta danegsta merged commit 542c3f5 into release/13.2 Mar 9, 2026
1112 of 1123 checks passed
@danegsta danegsta deleted the danegsta/trustLog branch March 9, 2026 22:28
@dotnet-policy-service dotnet-policy-service bot added this to the 13.2 milestone Mar 9, 2026
Copilot AI added a commit that referenced this pull request Mar 10, 2026
…v cert (#14666)

* Add logging if we detect the app host is running with an untrusted dev cert

* Allow overriding the dev cert used by the dashboard

* Also notify the dashboard if the certificate isn't trusted

* Update src/Aspire.Hosting/DeveloperCertificateService.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Move forward unlocking the macos keychain and trust the cert

* Update trust check to handle MacOS

* Add link to dev-certs code

* Cleanup some of the exceptions

* Trusting on Mac isn't going to be an option; switch to a warning in logs

* Use resource strings, move check and logging to DcpHost setup

* Update how HTTPS check is determined

* Use the file system service to get a temp folder

* Refactor DeveloperCertificateService to use ProcessSpec and ProcessUtil APIs with async/await (#14110)

* Update test service mocks

* Guard against the interaction service not being available

* Fix merge issue in DashboardEventHandlers

* Fix developer cert service timeout on Mac CI

* Only skip interaction service prompt if service not available

* Add additional test

* Fix failing test

* Disable dev cert https in mac ci tests

* Revert unrequired macos timeout change

* Add comments explaining the dashboard certificate config

* Only warn if there's an HTTPS/TLS endpoint

* Cleanup how we determine certificate trust to a cross-platform approach

* Expose interface property such that it can be used in tests

* Add chain build that got removed

* Check if cert is in root store on Windows

* Fix check that wasn't properly detecting the lack of trusted certificates

* Update src/Aspire.Hosting/Dcp/DcpHost.cs

Co-authored-by: Damian Edwards <damian@damianedwards.com>

* Add logging if we detect the app host is running with an untrusted dev cert (#15042)

* Initial plan

* Replace dotnet dev-certs command references with aka.ms/aspire/devcerts link

Co-authored-by: danegsta <50252651+danegsta@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: danegsta <50252651+danegsta@users.noreply.github.com>

* Fix failing test after log message updated to reference aka.ms/aspire/devcerts (#15043)

* Initial plan

* Fix failing test that was checking for outdated string content after log message update

Co-authored-by: danegsta <50252651+danegsta@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: danegsta <50252651+danegsta@users.noreply.github.com>

* Replace "ASP.NET Core Development Certificate" with "development certificate" in user-facing strings (#15048)

* Initial plan

* Replace "ASP.NET Core Development Certificate" with "development certificate" in strings

Co-authored-by: danegsta <50252651+danegsta@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: danegsta <50252651+danegsta@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Damian Edwards <damian@damianedwards.com>
@radical radical mentioned this pull request Mar 11, 2026
16 tasks
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.

7 participants