Fix dashboard resource service scheme and generate HTTPS dev cert for non-.NET AppHosts#17454
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 17454Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 17454" |
The .NET SDK first-run experience generates the HTTPS dev certificate when any dotnet command runs. Non-.NET AppHost languages (TypeScript, Python, etc.) launch a prebuilt native binary and never invoke dotnet, so the first-run cert generation never triggers. Add EnsureHttpCertificateExists() to ICertificateToolRunner which calls EnsureAspNetCoreHttpsDevelopmentCertificate(trust: false) to generate the cert without requiring user interaction. Call it from CertificateService when running non-interactively and no cert exists.
…text - Add CliGenerateHttpsCertificate to KnownConfigNames (grouped with CLI consts) - Inject CliExecutionContext into CertificateService for testability - Add ShouldGenerateHttpsCertificate() with ASPIRE_CLI_GENERATE_HTTPS_CERTIFICATE=false opt-out - Update test helpers to pass CliExecutionContext
- Test cert is generated when no certs exist (non-interactive) - Test cert generation is skipped when certs already exist - Test ASPIRE_CLI_GENERATE_HTTPS_CERTIFICATE=false opt-out suppresses generation
- Refresh preCheck after successful generation so trust-level checks reflect actual state - Log warning via DisplayMessage when certificate generation fails - Pass isInteractive: false to EnsureAspNetCoreHttpsDevelopmentCertificate (matches SDK first-run behavior of accepting older cert versions) - Add CreateNoCertsResult() test helper for readability - Update GeneratesCert test to simulate realistic two-call check pattern
There was a problem hiding this comment.
Pull request overview
Fixes a failure scenario for non-.NET AppHosts (e.g., TypeScript starter) where the dashboard resource service defaults to HTTPS but a dev HTTPS certificate may not exist because no dotnet first-run experience runs to generate it.
Changes:
- Updated dashboard resource service scheme selection so the default is HTTPS unless unsecured transport is explicitly allowed.
- Added non-interactive HTTPS dev-certificate creation in the CLI when no certificate exists (with an environment-variable opt-out).
- Added/updated tests to cover scheme resolution and certificate generation/opt-out/warning behavior.
Reviewed changes
Copilot reviewed 24 out of 25 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/Aspire.Hosting.Tests/Dashboard/DashboardServiceHostTests.cs | Adds coverage for DashboardServiceHost.ResolveScheme behavior. |
| tests/Aspire.Cli.Tests/Utils/CliTestHelper.cs | Updates test DI wiring for the new CertificateService constructor parameter. |
| tests/Aspire.Cli.Tests/TestServices/TestCertificateToolRunner.cs | Extends the certificate tool runner test double with EnsureHttpCertificateExists(). |
| tests/Aspire.Cli.Tests/Commands/CertificatesCommandTests.cs | Updates command tests to construct CertificateService with CliExecutionContext. |
| tests/Aspire.Cli.Tests/Certificates/CertificateServiceTests.cs | Adds tests for non-interactive cert generation, opt-out, and warning-on-failure. |
| src/Shared/KnownConfigNames.cs | Introduces ASPIRE_CLI_GENERATE_HTTPS_CERTIFICATE config name. |
| src/Aspire.Hosting/Dashboard/DashboardServiceHost.cs | Extracts and fixes scheme resolution logic for the resource service endpoint. |
| src/Aspire.Cli/Resources/xlf/ErrorStrings.zh-Hant.xlf | Adds localized entry for CertificateGenerationFailed. |
| src/Aspire.Cli/Resources/xlf/ErrorStrings.zh-Hans.xlf | Adds localized entry for CertificateGenerationFailed. |
| src/Aspire.Cli/Resources/xlf/ErrorStrings.tr.xlf | Adds localized entry for CertificateGenerationFailed. |
| src/Aspire.Cli/Resources/xlf/ErrorStrings.ru.xlf | Adds localized entry for CertificateGenerationFailed. |
| src/Aspire.Cli/Resources/xlf/ErrorStrings.pt-BR.xlf | Adds localized entry for CertificateGenerationFailed. |
| src/Aspire.Cli/Resources/xlf/ErrorStrings.pl.xlf | Adds localized entry for CertificateGenerationFailed. |
| src/Aspire.Cli/Resources/xlf/ErrorStrings.ko.xlf | Adds localized entry for CertificateGenerationFailed. |
| src/Aspire.Cli/Resources/xlf/ErrorStrings.ja.xlf | Adds localized entry for CertificateGenerationFailed. |
| src/Aspire.Cli/Resources/xlf/ErrorStrings.it.xlf | Adds localized entry for CertificateGenerationFailed. |
| src/Aspire.Cli/Resources/xlf/ErrorStrings.fr.xlf | Adds localized entry for CertificateGenerationFailed. |
| src/Aspire.Cli/Resources/xlf/ErrorStrings.es.xlf | Adds localized entry for CertificateGenerationFailed. |
| src/Aspire.Cli/Resources/xlf/ErrorStrings.de.xlf | Adds localized entry for CertificateGenerationFailed. |
| src/Aspire.Cli/Resources/xlf/ErrorStrings.cs.xlf | Adds localized entry for CertificateGenerationFailed. |
| src/Aspire.Cli/Resources/ErrorStrings.resx | Adds CertificateGenerationFailed resource string. |
| src/Aspire.Cli/Resources/ErrorStrings.Designer.cs | Updates generated accessor for CertificateGenerationFailed. |
| src/Aspire.Cli/Certificates/NativeCertificateToolRunner.cs | Implements EnsureHttpCertificateExists() using CertificateManager (trust:false). |
| src/Aspire.Cli/Certificates/ICertificateToolRunner.cs | Adds EnsureHttpCertificateExists() contract. |
| src/Aspire.Cli/Certificates/CertificateService.cs | Adds non-interactive certificate generation + env var opt-out logic. |
Files not reviewed (1)
- src/Aspire.Cli/Resources/ErrorStrings.Designer.cs: Language not supported
…ion failure - Extract ResolveScheme() static method from DashboardServiceHost for testability - Add DashboardServiceHostTests covering: default HTTPS, HTTP with unsecured transport, explicit URI scheme usage, and scheme independence from allowUnsecuredTransport - Add CertificateServiceTests covering: warning displayed on cert generation failure
788ff45 to
328c6e1
Compare
|
❓ CLI E2E Tests unknown — 96 passed, 0 failed, 5 unknown (commit View all recordings
📹 Recordings uploaded automatically from CI run #26379892419 |
| { | ||
| var preCheck = certificateToolRunner.CheckHttpCertificate(); | ||
|
|
||
| if (!preCheck.HasCertificates && ShouldGenerateHttpsCertificate()) |
dnegstad
left a comment
There was a problem hiding this comment.
Matches the non-interactive certificate generation behavior of the SDK; only question I have is whether we should support the DOTNET_ prefixed environment variable too.
| /// </summary> | ||
| private bool ShouldGenerateHttpsCertificate() | ||
| { | ||
| var value = executionContext.GetEnvironmentVariable(KnownConfigNames.CliGenerateHttpsCertificate); |
There was a problem hiding this comment.
Should we honor either the DOTNET_ or ASPIRE_ version here (with the ASPIRE_ version taking precedence)? We honor other DOTNET_ prefixed certificate config still since we want to maintain parity with the aspnet CertificateManager behavior.
danegsta
left a comment
There was a problem hiding this comment.
Helps if I'm not logged into my personal account when I try to approve... looks good, but we should decide if we're going to support both environment prefix and make sure we match the SDK behavior for when we generate a new certificate.
| { | ||
| var preCheck = certificateToolRunner.CheckHttpCertificate(); | ||
|
|
||
| if (!preCheck.HasCertificates && ShouldGenerateHttpsCertificate()) |
There was a problem hiding this comment.
Actually, does HasCertificates do a minimum version check (does it require not just a cert with the dev certs OID, but also a certificate with a minimum version 4 (to match what the SDK sets)? We should make sure we're matching the behavior of generating a new certificate both when there's no certificate and when there's no valid certificate (including the minimum version check).
There was a problem hiding this comment.
Looks like it does, so we're matching the SDK behavior.
…pHosts Documents the new behavior introduced in microsoft/aspire#17454: - When aspire run starts a non-.NET AppHost (e.g., TypeScript) in non-interactive mode and no HTTPS dev certificate exists, the CLI now automatically generates one. - The ASPIRE_CLI_GENERATE_HTTPS_CERTIFICATE environment variable can be set to 'false' to opt out of automatic certificate generation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Pull request created: #1063
|
|
📝 Documentation has been drafted in microsoft/aspire.dev#1063 targeting Updated Triggered signal: Note This draft PR needs human review before merging. |
aspire add failed to add the integration package after stopping the detach process
#17587
Summary
Fixes a CI test failure where the TypeScript starter template fails because the dashboard resource service defaults to HTTPS but no dev certificate exists when the AppHost isn't a .NET project (so
dotnet runnever triggers first-run cert generation).Changes
DashboardServiceHost scheme resolution (
src/Aspire.Hosting/Dashboard/DashboardServiceHost.cs)ResolveScheme(Uri? configuredUri, bool allowUnsecuredTransport)as an internal static method for testabilityAllowUnsecuredTransportis setNon-interactive HTTPS certificate generation (
src/Aspire.Cli/Certificates/)CertificateServicenow automatically generates an HTTPS dev certificate when none existsEnsureHttpCertificateExists()toICertificateToolRunner/NativeCertificateToolRunnerthat callsCertificateManager.EnsureAspNetCoreHttpsDevelopmentCertificateOpt-out via environment variable
ASPIRE_CLI_GENERATE_HTTPS_CERTIFICATEtoKnownConfigNames"false"skips automatic certificate generationTests
DashboardServiceHostTests.ResolveScheme_ReturnsExpectedScheme— theory covering all scheme resolution casesCertificateServiceTests— new tests for cert generation when none exist, skipping when certs exist, env var opt-out, and warning on failureFixes
Fixes the TypeScript starter CI test failure caused by missing HTTPS dev cert when the dashboard resource service defaults to HTTPS.