Skip to content

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

Open
danegsta wants to merge 33 commits intorelease/13.2from
danegsta/trustLog
Open

Add logging if we detect the app host is running with an untrusted dev cert#14666
danegsta wants to merge 33 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 db607d3:

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 ❌ Upload failed
LogsCommandShowsResourceLogs ▶️ View Recording
PsCommandListsRunningAppHost ▶️ View Recording
PsFormatJsonOutputsOnlyJsonToStdout ▶️ View Recording
SecretCrudOnDotNetAppHost ▶️ View Recording
SecretCrudOnTypeScriptAppHost ▶️ View Recording
StagingChannel_ConfigureAndVerifySettings_ThenSwitchChannels ▶️ View Recording
StopAllAppHostsFromAppHostDirectory ❌ Upload failed
StopAllAppHostsFromUnrelatedDirectory ▶️ View Recording
StopNonInteractiveMultipleAppHostsShowsError ❌ Upload failed
StopNonInteractiveSingleAppHost ▶️ View Recording
StopWithNoRunningAppHostExitsSuccessfully ▶️ View Recording
TypeScriptAppHostWithProjectReferenceIntegration ▶️ View Recording

📹 Recordings uploaded automatically from CI run #22807550441

@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>
Comment on lines +187 to +198
<data name="DeveloperCertificateNotFullyTrustedTitle" xml:space="preserve">
<value>Development certificate not fully trusted</value>
</data>
<data name="DeveloperCertificateNotFullyTrustedMessage" xml:space="preserve">
<value>The most recent ASP.NET Core Development Certificate isn't fully trusted. See https://aka.ms/aspire/devcerts for more information.</value>
</data>
<data name="NoDeveloperCertificateTrustedTitle" xml:space="preserve">
<value>No trusted development certificate</value>
</data>
<data name="NoDeveloperCertificateTrustedMessage" xml:space="preserve">
<value>No trusted ASP.NET Core Development Certificate was found. See https://aka.ms/aspire/devcerts for more information.</value>
</data>
Copy link
Member

Choose a reason for hiding this comment

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

WE gotta fix all of these string.

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.

6 participants