feat(security): OperationalAudit + AuditExport permissions for Audit Log surface (#23 M7)
Bundle G (#23 M7-T15): replace the temporary Admin-only gate on the Audit Log surface with two new permission policies — OperationalAudit (read) and AuditExport (bulk-export) — so the read path and the forensic-export path can be delegated independently. ScadaLink.Security - AuthorizationPolicies: add OperationalAudit + AuditExport policy constants; register them via RequireClaim with an explicit role allow-list (OperationalAuditRoles, AuditExportRoles) so the role-to-permission mapping is documented in one place. - Default mapping: Admin and Audit roles grant both policies; AuditReadOnly grants OperationalAudit only (read access without bulk export); Design and Deployment grant neither. ScadaLink.CentralUI - AuditLogPage: switch the page-level [Authorize] to the OperationalAudit policy and wrap the Export-CSV button in an AuthorizeView gated on AuditExport so an OperationalAudit-only operator still sees the page + filters but cannot trigger the CSV pull. - ConfigurationAuditLog: switch from RequireAdmin to OperationalAudit so both pages under the Audit nav group share the same gate. - NavMenu: the Audit nav group now gates on OperationalAudit so the section header + both child links match the per-page policies. - AuditExportEndpoints: switch RequireAuthorization from RequireAdmin to AuditExport — this is the authoritative gate; the AuthorizeView on the button is just a UX affordance. Tests - New AuditLogPagePermissionTests covers the 5 brief-mandated cases plus defence-in-depth for Admin-alone and AuditReadOnly users on the endpoint. - SecurityTests: add policy-level coverage for the new role→permission matrix (Theory rows pin every role/policy combination). - AuditExportEndpointsTests: switch to AddScadaLinkAuthorization() so the test host exercises the real production wiring under the new gate. - AuditLogPageScaffoldTests: wrap the page render in a CascadingAuthenticationState so the new in-page AuthorizeView resolves the principal.
This commit is contained in:
@@ -71,18 +71,18 @@ public class AuditExportEndpointsTests
|
||||
web.ConfigureServices(services =>
|
||||
{
|
||||
services.AddRouting();
|
||||
// The endpoint is admin-gated; the tests run as
|
||||
// pre-authenticated principals built by FakeAuthHandler
|
||||
// (everyone has the Admin role) so the RequireAdmin policy
|
||||
// succeeds.
|
||||
// The endpoint is AuditExport-gated (#23 M7-T15 Bundle G);
|
||||
// the tests run as pre-authenticated principals built by
|
||||
// FakeAuthHandler (everyone has the Admin role), which is
|
||||
// one of AuditExportRoles, so the policy succeeds.
|
||||
services.AddAuthentication(FakeAuthHandler.SchemeName)
|
||||
.AddScheme<Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions, FakeAuthHandler>(
|
||||
FakeAuthHandler.SchemeName, _ => { });
|
||||
services.AddAuthorization(options =>
|
||||
{
|
||||
options.AddPolicy(AuthorizationPolicies.RequireAdmin, policy =>
|
||||
policy.RequireClaim(JwtTokenService.RoleClaimType, "Admin"));
|
||||
});
|
||||
// Use the real production policy wiring so the endpoint's
|
||||
// updated AuditExport gate (#23 M7-T15 Bundle G) is what
|
||||
// the tests exercise. The fake principal carries the
|
||||
// "Admin" role, which AuditExportRoles permits.
|
||||
services.AddScadaLinkAuthorization();
|
||||
services.AddSingleton(repo);
|
||||
services.AddScoped<IAuditLogExportService, AuditLogExportService>();
|
||||
});
|
||||
@@ -224,8 +224,8 @@ public class AuditExportEndpointsTests
|
||||
|
||||
/// <summary>
|
||||
/// Test-only authentication handler that signs every request in as an Admin.
|
||||
/// Lets the endpoint's <c>RequireAdmin</c> policy pass without spinning up
|
||||
/// the real cookie + LDAP pipeline.
|
||||
/// Admin is in <c>AuditExportRoles</c>, so the endpoint's AuditExport policy
|
||||
/// passes without spinning up the real cookie + LDAP pipeline.
|
||||
/// </summary>
|
||||
private sealed class FakeAuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user