Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stop the apphost from running if the application url is http and ASPIRE_ALLOW_UNSECURED_TRANSPORT is not set #3177

Merged
merged 41 commits into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
f59b339
Minimal change to kick start the branch.
mitchdenny Mar 26, 2024
9700e04
WIP.
mitchdenny Mar 26, 2024
eb14d59
WIP
mitchdenny Mar 26, 2024
9024c6c
Remove unnecessary change.
mitchdenny Mar 26, 2024
a2c8928
Change mins to zero to increase entropy.
mitchdenny Mar 26, 2024
6729211
Make token properties read-only.
mitchdenny Mar 26, 2024
8fb7574
WIP
mitchdenny Mar 26, 2024
6eb42d2
Improved error message.
mitchdenny Mar 26, 2024
02e9ad9
Improve exception.
mitchdenny Mar 26, 2024
a5ee58f
Tweak exception message.
mitchdenny Mar 26, 2024
8dcdf0c
Return validation result instead of throwing.
mitchdenny Mar 26, 2024
4a2c658
Add defaults to password gen, and add #if def for ToHexStringLower
mitchdenny Mar 27, 2024
f827070
Add flag to allow setting on ASPIRE_ALLOW_UNSECURED_TRANSPORT for tes…
mitchdenny Mar 27, 2024
3bc8cd1
Getting tests passing.
mitchdenny Mar 27, 2024
415fb6d
Fix test cases.
mitchdenny Mar 27, 2024
93e053f
Update src/Aspire.Hosting/Dashboard/DashboardTokenProvider.cs
mitchdenny Mar 27, 2024
d7e6286
PR feedback.
mitchdenny Mar 27, 2024
17afc6d
PR feedback.
mitchdenny Mar 27, 2024
edbd7b2
Bikeshedding on arguments to PasswordGenerator :)
mitchdenny Mar 27, 2024
e462fc4
Merge branch 'main' into mitchdenny/dashboard-auth-basic-plumbing
mitchdenny Mar 27, 2024
7f115c0
Move transport check after guard clause.
mitchdenny Mar 27, 2024
93c8896
Merge branch 'mitchdenny/dashboard-auth-basic-plumbing' of https://gi…
mitchdenny Mar 27, 2024
392b652
KnownEnvironmentVaraibles to KnownConfigNames
mitchdenny Mar 27, 2024
341c1e0
Reword failure message.
mitchdenny Mar 27, 2024
0b62088
Add some test cases.
mitchdenny Mar 27, 2024
c63b4fd
Use ValidateOnstart
mitchdenny Mar 27, 2024
d298d85
Remove random file.
mitchdenny Mar 27, 2024
da1ff6b
We don't need the dummy call inside DashboardServiceHost.
mitchdenny Mar 27, 2024
54e5dad
bool? -> bool with some extra test coverage.
mitchdenny Mar 27, 2024
84b02d6
Update apphost launch settings.
mitchdenny Mar 27, 2024
4e03c64
PR feedback.
mitchdenny Mar 27, 2024
82efb14
Handle DistributedApplicationOptions.AllowUnsecuredTransport and Dist…
mitchdenny Mar 27, 2024
b04f9d1
remove unnecessary set of config.
mitchdenny Mar 27, 2024
11c6e40
Cover other URLs and complete code coverage.
mitchdenny Mar 27, 2024
741dc58
Fix issue of project not working in helix.
mitchdenny Mar 27, 2024
b0300f9
Enable unsecured transport in helix fixture.
mitchdenny Mar 27, 2024
9a605df
Helix test debugging.
mitchdenny Mar 27, 2024
d2b05e7
Update TransportOptions.cs
mitchdenny Mar 27, 2024
b077b82
Don't need to set config manually anymore.
mitchdenny Mar 27, 2024
5ae82c1
launchSettings apalooza
mitchdenny Mar 28, 2024
654fa37
Remove unnecessary fixture subclass.
mitchdenny Mar 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions playground/TestShop/AppHost/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -1,29 +1,31 @@
{
"profiles": {
"http": {
"https": {
"commandName": "Project",
"launchBrowser": true,
"dotnetRunMessages": true,
"applicationUrl": "http://localhost:15888",
"applicationUrl": "https://localhost:15887;http://localhost:15888",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT": "Development",
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:16031",
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:17031",
"DOTNET_ASPIRE_SHOW_DASHBOARD_RESOURCES": "true"
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:16037",
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:17037",
"DOTNET_ASPIRE_SHOW_DASHBOARD_RESOURCES": "true",
"ASPIRE__DASHBOARD__AUTHENTICATION__BROWSERTOKEN": "ABC123"
}
},
"https": {
"http": {
"commandName": "Project",
"launchBrowser": true,
"dotnetRunMessages": true,
"applicationUrl": "https://localhost:15887;http://localhost:15888",
"applicationUrl": "http://localhost:15888",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT": "Development",
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:16037",
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:17037",
"DOTNET_ASPIRE_SHOW_DASHBOARD_RESOURCES": "true"
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:16031",
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:17031",
"DOTNET_ASPIRE_SHOW_DASHBOARD_RESOURCES": "true",
//"ASPIRE__DASHBOARD__AUTHENTICATION__ALLOWUNSECURETRANSPORT": "true"
}
},
"generate-manifest": {
Expand Down
2 changes: 1 addition & 1 deletion playground/TestShop/AppHost/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Aspire.Hosting.Dcp": "Warning"
"Aspire.Hosting.Dcp": "Debug"
}
}
}
1 change: 1 addition & 0 deletions src/Aspire.Hosting/Aspire.Hosting.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<Compile Include="$(SharedDir)IConfigurationExtensions.cs" Link="Utils\IConfigurationExtensions.cs" />
<Compile Include="$(SharedDir)KnownFormats.cs" Link="Utils\KnownFormats.cs" />
<Compile Include="$(SharedDir)KnownResourceNames.cs" Link="Utils\KnownResourceNames.cs" />
<Compile Include="$(SharedDir)KnownEnvironmentVariables.cs" Link="Utils\KnownEnvironmentVariables.cs" />
<Compile Include="$(SharedDir)PathNormalizer.cs" Link="Utils\PathNormalizer.cs" />
<Compile Include="$(SharedDir)StringComparers.cs" Link="Utils\StringComparers.cs" />
<Compile Include="$(SharedDir)TaskHelpers.cs" Link="Utils\TaskHelpers.cs" />
Expand Down
10 changes: 10 additions & 0 deletions src/Aspire.Hosting/Dashboard/DashboardAuthenticationOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace Aspire.Hosting.Dashboard;

internal class DashboardAuthenticationOptions
{
public bool? AllowUnsecureTransport { get; set; }
public string? BrowserToken { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;

namespace Aspire.Hosting.Dashboard;

internal class DashboardAuthenticationOptionsValidator(IConfiguration configuration) : IValidateOptions<DashboardAuthenticationOptions>
{
public ValidateOptionsResult Validate(string? name, DashboardAuthenticationOptions options)
{
if (configuration[KnownEnvironmentVariables.AspNetCoreUrls] is not { } applicationUrls)
{
throw new DistributedApplicationException($"AppHost does not have applicationUrl in launch profile, or {KnownEnvironmentVariables.AspNetCoreUrls} environment variable set.");
mitchdenny marked this conversation as resolved.
Show resolved Hide resolved
}

var firstApplicationUrl = applicationUrls.Split(";").First();

if (!Uri.TryCreate(firstApplicationUrl, UriKind.Absolute, out var parsedFirstApplicationUrl))
{
throw new DistributedApplicationException($"AppHost applicationUrl in launch profile, or {KnownEnvironmentVariables.AspNetCoreUrls} environment variable could not be parsed as a URI.");
mitchdenny marked this conversation as resolved.
Show resolved Hide resolved
}

if (parsedFirstApplicationUrl.Scheme == "http" && !options.AllowUnsecureTransport.GetValueOrDefault(false))
{
throw new DistributedApplicationException($"AppHost cannot use a non-TLS URL for applicationUrl in launch profile, or {KnownEnvironmentVariables.AspNetCoreUrls} unless DashboardAuthenticationOptions.AllowUnsecureTransport is set to true.");
}

_ = configuration;
mitchdenny marked this conversation as resolved.
Show resolved Hide resolved
return ValidateOptionsResult.Success;
}
}
37 changes: 37 additions & 0 deletions src/Aspire.Hosting/Dashboard/DashboardTokenProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Licensed to the .NET Foundation under one or more agreements.
mitchdenny marked this conversation as resolved.
Show resolved Hide resolved
// The .NET Foundation licenses this file to you under the MIT license.

using System.Text;
using Aspire.Hosting.Utils;
using Microsoft.Extensions.Options;

namespace Aspire.Hosting.Dashboard;

internal interface IDashboardTokenProvider
{
public string BrowserToken { get; }
mitchdenny marked this conversation as resolved.
Show resolved Hide resolved
public string OltpToken { get; }
mitchdenny marked this conversation as resolved.
Show resolved Hide resolved
public string ResourceServerToken { get; }
}

internal class DashboardTokenProvider : IDashboardTokenProvider
{
public DashboardTokenProvider(IOptions<DashboardAuthenticationOptions> dashboardAuthenticationOptions)
{
BrowserToken = dashboardAuthenticationOptions.Value.BrowserToken ?? GenerateToken();
OltpToken = GenerateToken();
ResourceServerToken = GenerateToken();
}

private static string GenerateToken()
{
var rawToken = PasswordGenerator.Generate(24, true, true, true, true, 0, 0, 0, 0);
mitchdenny marked this conversation as resolved.
Show resolved Hide resolved
var rawTokenBytes = Encoding.UTF8.GetBytes(rawToken);
var encodedToken = Convert.ToHexString(rawTokenBytes).ToLower();
mitchdenny marked this conversation as resolved.
Show resolved Hide resolved
return encodedToken;
}

public string BrowserToken { get; }
public string OltpToken { get; }
public string ResourceServerToken { get; }
}
18 changes: 17 additions & 1 deletion src/Aspire.Hosting/Dcp/ApplicationExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,10 @@ internal sealed class ApplicationExecutor(ILogger<ApplicationExecutor> logger,
DistributedApplicationExecutionContext executionContext,
ResourceNotificationService notificationService,
ResourceLoggerService loggerService,
IDcpDependencyCheckService dcpDependencyCheckService)
IDcpDependencyCheckService dcpDependencyCheckService,
IOptions<DashboardAuthenticationOptions> dashboardAuthenticationOptions,
IDashboardTokenProvider dashboardTokenProvider
)
{
private const string DebugSessionPortVar = "DEBUG_SESSION_PORT";

Expand Down Expand Up @@ -708,6 +711,19 @@ private void ConfigureAspireDashboardResource(IResource dashboardResource)

var grpcEndpointUrl = await _dashboardEndpointProvider.GetResourceServiceUriAsync(context.CancellationToken).ConfigureAwait(false);

if (dashboardAuthenticationOptions.Value.AllowUnsecureTransport.GetValueOrDefault(false))
{
// Configure for insecure running.
context.EnvironmentVariables["DISABLEAUTHPLACEHOLDER"] = true;
mitchdenny marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
// Configure for secure running.
context.EnvironmentVariables["BROWSERTOKENPLACEHOLDER"] = dashboardTokenProvider.BrowserToken;
context.EnvironmentVariables["OTLPTOKENPLACEHOLDER"] = dashboardTokenProvider.OltpToken;
context.EnvironmentVariables["RESOURCESERVERTOKENPLACEHOLDER"] = dashboardTokenProvider.ResourceServerToken;
mitchdenny marked this conversation as resolved.
Show resolved Hide resolved
}

context.EnvironmentVariables["ASPNETCORE_URLS"] = appHostApplicationUrl;
context.EnvironmentVariables["DOTNET_RESOURCE_SERVICE_ENDPOINT_URL"] = grpcEndpointUrl;
context.EnvironmentVariables["DOTNET_DASHBOARD_OTLP_ENDPOINT_URL"] = otlpEndpointUrl;
Expand Down
5 changes: 5 additions & 0 deletions src/Aspire.Hosting/DistributedApplicationBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
using Aspire.Hosting.Publishing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace Aspire.Hosting;

Expand Down Expand Up @@ -89,9 +91,12 @@ public DistributedApplicationBuilder(DistributedApplicationOptions options)
_innerBuilder.Services.AddSingleton<ResourceLoggerService>();

// Dashboard
_innerBuilder.Services.AddOptions<DashboardAuthenticationOptions>().Bind(Configuration.GetSection("Aspire:Dashboard:Authentication"));
mitchdenny marked this conversation as resolved.
Show resolved Hide resolved
_innerBuilder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IValidateOptions<DashboardAuthenticationOptions>, DashboardAuthenticationOptionsValidator>());
_innerBuilder.Services.AddSingleton<DashboardServiceHost>();
_innerBuilder.Services.AddHostedService<DashboardServiceHost>(sp => sp.GetRequiredService<DashboardServiceHost>());
_innerBuilder.Services.AddLifecycleHook<DashboardManifestExclusionHook>();
_innerBuilder.Services.AddSingleton<IDashboardTokenProvider, DashboardTokenProvider>();

// DCP stuff
_innerBuilder.Services.AddSingleton<ApplicationExecutor>();
Expand Down
9 changes: 9 additions & 0 deletions src/Shared/KnownEnvironmentVariables.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace Aspire.Hosting;

internal static class KnownEnvironmentVariables
mitchdenny marked this conversation as resolved.
Show resolved Hide resolved
{
public static string AspNetCoreUrls = "ASPNETCORE_URLS";
}
Loading