Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 5 additions & 2 deletions Aspire.sln
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecksSandbox.AppHost
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DaprServiceC", "playground\dapr\ServiceC\DaprServiceC.csproj", "{B26653B9-439E-4850-A7F8-43C6E5121952}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dashboard", "Dashboard", "{830F7CA9-8E51-4D62-832F-91F53F85B7AE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -1738,7 +1740,7 @@ Global
{31F5E4F3-AC4E-4538-BC7D-85BCF9CA686A} = {975F6F41-B455-451D-A312-098DE4A167B6}
{A37AAFDB-545B-4599-806A-EFCB8B310446} = {975F6F41-B455-451D-A312-098DE4A167B6}
{8CB12764-E469-4BB5-8554-5F9CA0F6DE18} = {975F6F41-B455-451D-A312-098DE4A167B6}
{1ABCD945-5CAA-4F30-A741-7A9DA919254A} = {4981B3A5-4AFD-4191-BF7D-8692D9783D60}
{1ABCD945-5CAA-4F30-A741-7A9DA919254A} = {830F7CA9-8E51-4D62-832F-91F53F85B7AE}
{E20280B8-8BE0-4967-AFC2-65FFCD6EC5E4} = {F534D4F8-5E3A-42FC-BCD7-4C2D6060F9C8}
{6EAA089D-7ADD-4C74-B040-FD3D75DB5C75} = {C424395C-1235-41A4-BF55-07880A04368C}
{9D9C360B-9DF1-4076-8416-66964427C8F3} = {C424395C-1235-41A4-BF55-07880A04368C}
Expand Down Expand Up @@ -1820,7 +1822,7 @@ Global
{157A434E-E3CA-4080-96CF-903CC3DF66E9} = {8AA07A14-A4A7-45EC-B0F6-4690B516B16D}
{921CB408-5E37-4354-B4CF-EAE517F633DC} = {8AA07A14-A4A7-45EC-B0F6-4690B516B16D}
{C774BE00-EE93-4148-B866-8F0F2BA1E473} = {C424395C-1235-41A4-BF55-07880A04368C}
{0870A667-FB0C-4758-AEAF-9E5F092AD7C1} = {4981B3A5-4AFD-4191-BF7D-8692D9783D60}
{0870A667-FB0C-4758-AEAF-9E5F092AD7C1} = {830F7CA9-8E51-4D62-832F-91F53F85B7AE}
{C4833DEC-0A4F-4504-B8D0-06C60B84119C} = {91F22EEA-EB23-425A-9B32-9438A0809F4B}
{9CA94707-E801-444F-A582-D5BD0104CF9B} = {91F22EEA-EB23-425A-9B32-9438A0809F4B}
{3216CF59-84B0-46FF-8572-D0AFB0155423} = {A7C6452C-FEDB-4883-9AE7-29892D260AA3}
Expand Down Expand Up @@ -1998,6 +2000,7 @@ Global
{B7345F72-712F-436C-AE18-CAF7CDD4A990} = {D173887B-AF42-4576-B9C1-96B9E9B3D9C0}
{042DD8C6-A26C-4B06-80A1-FE7F8659C5BC} = {B7345F72-712F-436C-AE18-CAF7CDD4A990}
{B26653B9-439E-4850-A7F8-43C6E5121952} = {57A42144-739E-49A7-BADB-BB8F5F20FA17}
{830F7CA9-8E51-4D62-832F-91F53F85B7AE} = {4981B3A5-4AFD-4191-BF7D-8692D9783D60}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6DCEDFEC-988E-4CB3-B45B-191EB5086E0C}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Aspire.Dashboard.Authentication.Connection;
using Aspire.Dashboard.Model;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.InternalTesting;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Primitives;
Expand All @@ -21,7 +22,7 @@ public async Task InvokeAsync_Development_AllowExternalFetch()
var httpContext = new DefaultHttpContext();

// Act
await middleware.InvokeAsync(httpContext);
await middleware.InvokeAsync(httpContext).DefaultTimeout();

// Assert
Assert.NotEqual(StringValues.Empty, httpContext.Response.Headers.ContentSecurityPolicy);
Expand All @@ -36,7 +37,7 @@ public async Task InvokeAsync_Production_DenyExternalFetch()
var httpContext = new DefaultHttpContext();

// Act
await middleware.InvokeAsync(httpContext);
await middleware.InvokeAsync(httpContext).DefaultTimeout();

// Assert
Assert.NotEqual(StringValues.Empty, httpContext.Response.Headers.ContentSecurityPolicy);
Expand All @@ -54,7 +55,7 @@ public async Task InvokeAsync_Scheme_ImageSourceChangesOnScheme(string scheme, s
httpContext.Request.Scheme = scheme;

// Act
await middleware.InvokeAsync(httpContext);
await middleware.InvokeAsync(httpContext).DefaultTimeout();

// Assert
Assert.NotEqual(StringValues.Empty, httpContext.Response.Headers.ContentSecurityPolicy);
Expand All @@ -70,7 +71,7 @@ public async Task InvokeAsync_Otlp_NotAdded()
httpContext.Features.Set<IConnectionTypeFeature>(new TestConnectionTypeFeature { ConnectionTypes = [ConnectionType.Otlp] });

// Act
await middleware.InvokeAsync(httpContext);
await middleware.InvokeAsync(httpContext).DefaultTimeout();

// Assert
Assert.Equal(StringValues.Empty, httpContext.Response.Headers.ContentSecurityPolicy);
Expand Down
19 changes: 10 additions & 9 deletions tests/Aspire.Dashboard.Tests/ChannelExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Diagnostics;
using System.Threading.Channels;
using Aspire.Dashboard.Utils;
using Microsoft.AspNetCore.InternalTesting;
using Xunit;

namespace Aspire.Dashboard.Tests;
Expand Down Expand Up @@ -31,7 +32,7 @@ public async Task GetBatchesAsync_CancellationToken_Exits()
});

// Assert
await TaskHelpers.WaitIgnoreCancelAsync(readTask);
await TaskHelpers.WaitIgnoreCancelAsync(readTask).DefaultTimeout();
}

[Fact]
Expand All @@ -55,7 +56,7 @@ public async Task GetBatchesAsync_WithCancellation_Exits()
});

// Assert
await TaskHelpers.WaitIgnoreCancelAsync(readTask);
await TaskHelpers.WaitIgnoreCancelAsync(readTask).DefaultTimeout();
}

[Fact]
Expand Down Expand Up @@ -87,19 +88,19 @@ public async Task GetBatchesAsync_MinReadInterval_WaitForNextRead()

// Assert
var stopwatch = Stopwatch.StartNew();
var read1 = await resultChannel.Reader.ReadAsync();
var read1 = await resultChannel.Reader.ReadAsync().DefaultTimeout();
Assert.Equal(["a", "b", "c"], read1.Single());

channel.Writer.TryWrite(["d", "e", "f"]);

var read2 = await resultChannel.Reader.ReadAsync();
var read2 = await resultChannel.Reader.ReadAsync().DefaultTimeout();
Assert.Equal(["d", "e", "f"], read2.Single());

var elapsed = stopwatch.Elapsed;
CustomAssert.AssertExceedsMinInterval(elapsed, minReadInterval);

channel.Writer.Complete();
await TaskHelpers.WaitIgnoreCancelAsync(readTask);
await TaskHelpers.WaitIgnoreCancelAsync(readTask).DefaultTimeout();
}

[Fact]
Expand Down Expand Up @@ -131,18 +132,18 @@ public async Task GetBatchesAsync_MinReadInterval_WithCancellation_Exit()

// Assert
var stopwatch = Stopwatch.StartNew();
var read1 = await resultChannel.Reader.ReadAsync();
var read1 = await resultChannel.Reader.ReadAsync().DefaultTimeout();
Assert.Equal(["a", "b", "c"], read1.Single());

channel.Writer.TryWrite(["d", "e", "f"]);

var read2Task = resultChannel.Reader.ReadAsync();
var read2Task = resultChannel.Reader.ReadAsync().DefaultTimeout();
cts.Cancel();

await TaskHelpers.WaitIgnoreCancelAsync(readTask);
await TaskHelpers.WaitIgnoreCancelAsync(readTask).DefaultTimeout();
try
{
await read2Task;
await read2Task.DefaultTimeout();
}
catch (ChannelClosedException)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Grpc.Core;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.InternalTesting;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -40,10 +41,10 @@ public DashboardClientAuthTests(ITestOutputHelper testOutputHelper)
public async Task ConnectsToResourceService_Unsecured(bool useHttps)
{
var loggerFactory = IntegrationTestHelpers.CreateLoggerFactory(_testOutputHelper);
await using var server = await CreateResourceServiceServerAsync(loggerFactory, useHttps);
await using var client = await CreateDashboardClientAsync(loggerFactory, server.Url, authMode: ResourceClientAuthMode.Unsecured);
await using var server = await CreateResourceServiceServerAsync(loggerFactory, useHttps).DefaultTimeout();
await using var client = await CreateDashboardClientAsync(loggerFactory, server.Url, authMode: ResourceClientAuthMode.Unsecured).DefaultTimeout();

var call = await server.Calls.ApplicationInformationCallsChannel.Reader.ReadAsync();
var call = await server.Calls.ApplicationInformationCallsChannel.Reader.ReadAsync().DefaultTimeout();

Assert.NotNull(call.Request);
Assert.NotNull(call.RequestHeaders);
Expand All @@ -56,10 +57,10 @@ public async Task ConnectsToResourceService_Unsecured(bool useHttps)
public async Task ConnectsToResourceService_ApiKey(bool useHttps)
{
var loggerFactory = IntegrationTestHelpers.CreateLoggerFactory(_testOutputHelper);
await using var server = await CreateResourceServiceServerAsync(loggerFactory, useHttps);
await using var client = await CreateDashboardClientAsync(loggerFactory, server.Url, authMode: ResourceClientAuthMode.ApiKey, configureOptions: options => options.ResourceServiceClient.ApiKey = "TestApiKey!");
await using var server = await CreateResourceServiceServerAsync(loggerFactory, useHttps).DefaultTimeout();
await using var client = await CreateDashboardClientAsync(loggerFactory, server.Url, authMode: ResourceClientAuthMode.ApiKey, configureOptions: options => options.ResourceServiceClient.ApiKey = "TestApiKey!").DefaultTimeout();

var call = await server.Calls.ApplicationInformationCallsChannel.Reader.ReadAsync();
var call = await server.Calls.ApplicationInformationCallsChannel.Reader.ReadAsync().DefaultTimeout();

Assert.NotNull(call.Request);
Assert.NotNull(call.RequestHeaders);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Aspire.Dashboard.Configuration;
using Aspire.Dashboard.Utils;
using Aspire.Hosting;
using Microsoft.AspNetCore.InternalTesting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Xunit;
Expand All @@ -34,12 +35,12 @@ public async Task Get_Unauthenticated_RedirectToLogin()
config[DashboardConfigNames.DashboardFrontendAuthModeName.ConfigKey] = FrontendAuthMode.BrowserToken.ToString();
config[DashboardConfigNames.DashboardFrontendBrowserTokenName.ConfigKey] = apiKey;
});
await app.StartAsync();
await app.StartAsync().DefaultTimeout();

using var client = new HttpClient { BaseAddress = new Uri($"http://{app.FrontendSingleEndPointAccessor().EndPoint}") };

// Act
var response = await client.GetAsync("/");
var response = await client.GetAsync("/").DefaultTimeout();

// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Expand All @@ -56,19 +57,19 @@ public async Task Get_LoginPage_ValidToken_RedirectToApp()
config[DashboardConfigNames.DashboardFrontendAuthModeName.ConfigKey] = FrontendAuthMode.BrowserToken.ToString();
config[DashboardConfigNames.DashboardFrontendBrowserTokenName.ConfigKey] = apiKey;
});
await app.StartAsync();
await app.StartAsync().DefaultTimeout();

using var client = new HttpClient { BaseAddress = new Uri($"http://{app.FrontendSingleEndPointAccessor().EndPoint}") };

// Act 1
var response1 = await client.GetAsync(DashboardUrls.LoginUrl(returnUrl: DashboardUrls.TracesUrl(), token: apiKey));
var response1 = await client.GetAsync(DashboardUrls.LoginUrl(returnUrl: DashboardUrls.TracesUrl(), token: apiKey)).DefaultTimeout();

// Assert 1
Assert.Equal(HttpStatusCode.OK, response1.StatusCode);
Assert.Equal(DashboardUrls.TracesUrl(), response1.RequestMessage!.RequestUri!.PathAndQuery);

// Act 2
var response2 = await client.GetAsync(DashboardUrls.StructuredLogsUrl());
var response2 = await client.GetAsync(DashboardUrls.StructuredLogsUrl()).DefaultTimeout();

// Assert 2
Assert.Equal(HttpStatusCode.OK, response2.StatusCode);
Expand All @@ -87,12 +88,12 @@ public async Task Get_LoginPage_ValidToken_OtlpHttpConnection_Denied()
config[DashboardConfigNames.DashboardFrontendAuthModeName.ConfigKey] = FrontendAuthMode.BrowserToken.ToString();
config[DashboardConfigNames.DashboardFrontendBrowserTokenName.ConfigKey] = apiKey;
}, testSink: testSink);
await app.StartAsync();
await app.StartAsync().DefaultTimeout();

using var client = new HttpClient { BaseAddress = new Uri($"http://{app.OtlpServiceHttpEndPointAccessor().EndPoint}") };

// Act
var response = await client.GetAsync(DashboardUrls.LoginUrl(returnUrl: DashboardUrls.TracesUrl(), token: apiKey));
var response = await client.GetAsync(DashboardUrls.LoginUrl(returnUrl: DashboardUrls.TracesUrl(), token: apiKey)).DefaultTimeout();

// Assert
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
Expand All @@ -111,12 +112,12 @@ public async Task Get_LoginPage_InvalidToken_RedirectToLoginWithoutToken()
config[DashboardConfigNames.DashboardFrontendAuthModeName.ConfigKey] = FrontendAuthMode.BrowserToken.ToString();
config[DashboardConfigNames.DashboardFrontendBrowserTokenName.ConfigKey] = apiKey;
});
await app.StartAsync();
await app.StartAsync().DefaultTimeout();

using var client = new HttpClient { BaseAddress = new Uri($"http://{app.FrontendSingleEndPointAccessor().EndPoint}") };

// Act
var response = await client.GetAsync(DashboardUrls.LoginUrl(returnUrl: DashboardUrls.TracesUrl(), token: "Wrong!"));
var response = await client.GetAsync(DashboardUrls.LoginUrl(returnUrl: DashboardUrls.TracesUrl(), token: "Wrong!")).DefaultTimeout();

// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Expand All @@ -136,12 +137,12 @@ public async Task Post_ValidateTokenApi_AvailableBasedOnOptions(FrontendAuthMode
config[DashboardConfigNames.DashboardFrontendAuthModeName.ConfigKey] = authMode.ToString();
config[DashboardConfigNames.DashboardFrontendBrowserTokenName.ConfigKey] = apiKey;
});
await app.StartAsync();
await app.StartAsync().DefaultTimeout();

using var client = new HttpClient { BaseAddress = new Uri($"http://{app.FrontendSingleEndPointAccessor().EndPoint}") };

// Act
var response = await client.PostAsync("/api/validatetoken?token=" + requestToken, content: null);
var response = await client.PostAsync("/api/validatetoken?token=" + requestToken, content: null).DefaultTimeout();

// Assert
Assert.Equal(statusCode, response.StatusCode);
Expand All @@ -164,7 +165,7 @@ public async Task LogOutput_NoToken_GeneratedTokenLogged()
}, testSink: testSink);

// Act
await app.StartAsync();
await app.StartAsync().DefaultTimeout();

// Assert
var l = testSink.Writes.Where(w => w.LoggerName == typeof(DashboardWebApplication).FullName).ToList();
Expand Down Expand Up @@ -225,7 +226,7 @@ public async Task LogOutput_AnyIP_LoginLinkLocalhost(string frontendUrl, string
}, testSink: testSink);

// Act
await app.StartAsync();
await app.StartAsync().DefaultTimeout();

// Assert
var l = testSink.Writes.Where(w => w.LoggerName == typeof(DashboardWebApplication).FullName).ToList();
Expand All @@ -252,7 +253,7 @@ public async Task LogOutput_InContainer_LoginLinkContainerMessage()
}, testSink: testSink);

// Act
await app.StartAsync();
await app.StartAsync().DefaultTimeout();

// Assert
var l = testSink.Writes.Where(w => w.LoggerName == typeof(DashboardWebApplication).FullName).ToList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Web;
using Aspire.Dashboard.Authentication;
using Aspire.Hosting;
using Microsoft.AspNetCore.InternalTesting;
using Microsoft.Extensions.Logging.Testing;
using Xunit;
using Xunit.Abstractions;
Expand All @@ -16,7 +17,7 @@ public class FrontendOpenIdConnectAuthTests(ITestOutputHelper testOutputHelper)
[Fact]
public async Task Get_Unauthenticated_RedirectsToAuthority()
{
await using var authority = await MockOpenIdAuthority.CreateAsync();
await using var authority = await MockOpenIdAuthority.CreateAsync().DefaultTimeout();

await using var app = IntegrationTestHelpers.CreateDashboardWebApplication(
testOutputHelper,
Expand All @@ -25,7 +26,7 @@ public async Task Get_Unauthenticated_RedirectsToAuthority()
ConfigureOpenIdConnect(config, authority);
});

await app.StartAsync();
await app.StartAsync().DefaultTimeout();

var handler = new HttpClientHandler()
{
Expand All @@ -36,7 +37,7 @@ public async Task Get_Unauthenticated_RedirectsToAuthority()
using var client = new HttpClient(handler) { BaseAddress = new Uri($"http://{app.FrontendSingleEndPointAccessor().EndPoint}") };

// Act
var response = await client.GetAsync("/");
var response = await client.GetAsync("/").DefaultTimeout();

// Assert
Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
Expand All @@ -53,13 +54,13 @@ public async Task Get_Unauthenticated_RedirectsToAuthority()
Assert.Equal("code", query.Get("response_type"));
Assert.Equal("openid profile", query.Get("scope"));

await app.StopAsync();
await app.StopAsync().DefaultTimeout();
}

[Fact]
public async Task Get_Unauthenticated_OtlpHttpConnection_Denied()
{
await using var authority = await MockOpenIdAuthority.CreateAsync();
await using var authority = await MockOpenIdAuthority.CreateAsync().DefaultTimeout();

var testSink = new TestSink();
await using var app = IntegrationTestHelpers.CreateDashboardWebApplication(
Expand All @@ -70,7 +71,7 @@ public async Task Get_Unauthenticated_OtlpHttpConnection_Denied()
},
testSink: testSink);

await app.StartAsync();
await app.StartAsync().DefaultTimeout();

var handler = new HttpClientHandler()
{
Expand All @@ -81,15 +82,15 @@ public async Task Get_Unauthenticated_OtlpHttpConnection_Denied()
using var client = new HttpClient(handler) { BaseAddress = new Uri($"http://{app.OtlpServiceHttpEndPointAccessor().EndPoint}") };

// Act
var response = await client.GetAsync("/");
var response = await client.GetAsync("/").DefaultTimeout();

// Assert
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);

var log = testSink.Writes.Single(s => s.LoggerName == typeof(FrontendCompositeAuthenticationHandler).FullName && s.EventId.Name == "AuthenticationSchemeNotAuthenticatedWithFailure");
Assert.Equal("FrontendComposite was not authenticated. Failure message: Connection type Frontend is not enabled on this connection.", log.Message);

await app.StopAsync();
await app.StopAsync().DefaultTimeout();
}

private static void ConfigureOpenIdConnect(Dictionary<string, string?> config, MockOpenIdAuthority.Authority authority)
Expand Down
Loading