96 lines
3.3 KiB
C#
96 lines
3.3 KiB
C#
using System.Net;
|
|
using System.Security.Claims;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.Extensions.Options;
|
|
using MxGateway.Server.Configuration;
|
|
using MxGateway.Server.Dashboard;
|
|
using MxGateway.Server.Security.Authorization;
|
|
|
|
namespace MxGateway.Tests.Gateway.Dashboard;
|
|
|
|
public sealed class DashboardAuthorizationHandlerTests
|
|
{
|
|
/// <summary>Verifies that unauthenticated remote requests fail authorization.</summary>
|
|
[Fact]
|
|
public async Task HandleAsync_UnauthenticatedRemoteRequest_DoesNotSucceed()
|
|
{
|
|
AuthorizationHandlerContext context = await AuthorizeAsync(
|
|
new ClaimsPrincipal(new ClaimsIdentity()),
|
|
IPAddress.Parse("10.0.0.5"),
|
|
allowAnonymousLocalhost: false);
|
|
|
|
Assert.False(context.HasSucceeded);
|
|
}
|
|
|
|
/// <summary>Verifies that anonymous localhost access succeeds when allowed.</summary>
|
|
[Fact]
|
|
public async Task HandleAsync_AnonymousLocalhostAllowed_Succeeds()
|
|
{
|
|
AuthorizationHandlerContext context = await AuthorizeAsync(
|
|
new ClaimsPrincipal(new ClaimsIdentity()),
|
|
IPAddress.Loopback,
|
|
allowAnonymousLocalhost: true);
|
|
|
|
Assert.True(context.HasSucceeded);
|
|
}
|
|
|
|
/// <summary>Verifies that authenticated users without admin scope fail authorization.</summary>
|
|
[Fact]
|
|
public async Task HandleAsync_AuthenticatedWithoutAdminScope_DoesNotSucceed()
|
|
{
|
|
AuthorizationHandlerContext context = await AuthorizeAsync(
|
|
CreatePrincipal(GatewayScopes.EventsRead),
|
|
IPAddress.Loopback,
|
|
allowAnonymousLocalhost: false);
|
|
|
|
Assert.False(context.HasSucceeded);
|
|
}
|
|
|
|
/// <summary>Verifies that authenticated users with admin scope succeed.</summary>
|
|
[Fact]
|
|
public async Task HandleAsync_AuthenticatedWithAdminScope_Succeeds()
|
|
{
|
|
AuthorizationHandlerContext context = await AuthorizeAsync(
|
|
CreatePrincipal(GatewayScopes.Admin),
|
|
IPAddress.Parse("10.0.0.5"),
|
|
allowAnonymousLocalhost: false);
|
|
|
|
Assert.True(context.HasSucceeded);
|
|
}
|
|
|
|
private static async Task<AuthorizationHandlerContext> AuthorizeAsync(
|
|
ClaimsPrincipal principal,
|
|
IPAddress remoteAddress,
|
|
bool allowAnonymousLocalhost)
|
|
{
|
|
DashboardAuthorizationRequirement requirement = new();
|
|
DefaultHttpContext httpContext = new();
|
|
httpContext.Connection.RemoteIpAddress = remoteAddress;
|
|
DashboardAuthorizationHandler handler = new(
|
|
new HttpContextAccessor { HttpContext = httpContext },
|
|
Options.Create(new GatewayOptions
|
|
{
|
|
Dashboard = new DashboardOptions
|
|
{
|
|
AllowAnonymousLocalhost = allowAnonymousLocalhost,
|
|
RequireAdminScope = true
|
|
}
|
|
}));
|
|
AuthorizationHandlerContext context = new([requirement], principal, httpContext);
|
|
|
|
await handler.HandleAsync(context);
|
|
|
|
return context;
|
|
}
|
|
|
|
private static ClaimsPrincipal CreatePrincipal(string scope)
|
|
{
|
|
ClaimsIdentity identity = new(
|
|
[new Claim(DashboardAuthenticationDefaults.ScopeClaimType, scope)],
|
|
DashboardAuthenticationDefaults.AuthenticationScheme);
|
|
|
|
return new ClaimsPrincipal(identity);
|
|
}
|
|
}
|