More security!
All checks were successful
Build Docker Images / test (map[name:Morska plugin_project:DiunaBI.Plugins.Morska]) (push) Successful in 1m25s
Build Docker Images / test (map[name:PedrolloPL plugin_project:DiunaBI.Plugins.PedrolloPL]) (push) Successful in 1m25s
Build Docker Images / build-and-push (map[image_suffix:morska name:Morska plugin_project:DiunaBI.Plugins.Morska]) (push) Successful in 1m41s
Build Docker Images / build-and-push (map[image_suffix:pedrollopl name:PedrolloPL plugin_project:DiunaBI.Plugins.PedrolloPL]) (push) Successful in 1m40s
All checks were successful
Build Docker Images / test (map[name:Morska plugin_project:DiunaBI.Plugins.Morska]) (push) Successful in 1m25s
Build Docker Images / test (map[name:PedrolloPL plugin_project:DiunaBI.Plugins.PedrolloPL]) (push) Successful in 1m25s
Build Docker Images / build-and-push (map[image_suffix:morska name:Morska plugin_project:DiunaBI.Plugins.Morska]) (push) Successful in 1m41s
Build Docker Images / build-and-push (map[image_suffix:pedrollopl name:PedrolloPL plugin_project:DiunaBI.Plugins.PedrolloPL]) (push) Successful in 1m40s
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.RateLimiting;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.RateLimiting;
|
||||
using DiunaBI.API.Hubs;
|
||||
using DiunaBI.API.Services;
|
||||
using DiunaBI.Infrastructure.Data;
|
||||
@@ -72,6 +74,41 @@ builder.Services.AddCors(options =>
|
||||
|
||||
builder.Services.AddControllers();
|
||||
|
||||
// Rate Limiting
|
||||
builder.Services.AddRateLimiter(options =>
|
||||
{
|
||||
// Global API rate limit
|
||||
options.AddFixedWindowLimiter("api", config =>
|
||||
{
|
||||
config.PermitLimit = 100;
|
||||
config.Window = TimeSpan.FromMinutes(1);
|
||||
config.QueueProcessingOrder = System.Threading.RateLimiting.QueueProcessingOrder.OldestFirst;
|
||||
config.QueueLimit = 0; // No queueing
|
||||
});
|
||||
|
||||
// Strict limit for authentication endpoint
|
||||
options.AddFixedWindowLimiter("auth", config =>
|
||||
{
|
||||
config.PermitLimit = 10;
|
||||
config.Window = TimeSpan.FromMinutes(1);
|
||||
config.QueueProcessingOrder = System.Threading.RateLimiting.QueueProcessingOrder.OldestFirst;
|
||||
config.QueueLimit = 0;
|
||||
});
|
||||
|
||||
// Rejection response
|
||||
options.OnRejected = async (context, token) =>
|
||||
{
|
||||
context.HttpContext.Response.StatusCode = 429; // Too Many Requests
|
||||
await context.HttpContext.Response.WriteAsJsonAsync(new
|
||||
{
|
||||
error = "Too many requests. Please try again later.",
|
||||
retryAfter = context.Lease.TryGetMetadata(MetadataName.RetryAfter, out var retryAfter)
|
||||
? (double?)retryAfter.TotalSeconds
|
||||
: (double?)null
|
||||
}, cancellationToken: token);
|
||||
};
|
||||
});
|
||||
|
||||
// SignalR
|
||||
builder.Services.AddSignalR();
|
||||
|
||||
@@ -202,6 +239,18 @@ pluginManager.LoadPluginsFromDirectory(pluginsPath);
|
||||
|
||||
app.UseCors("CORSPolicy");
|
||||
|
||||
// Security Headers
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
context.Response.Headers.Append("X-Content-Type-Options", "nosniff");
|
||||
context.Response.Headers.Append("X-Frame-Options", "DENY");
|
||||
context.Response.Headers.Append("X-XSS-Protection", "1; mode=block");
|
||||
context.Response.Headers.Append("Referrer-Policy", "strict-origin-when-cross-origin");
|
||||
await next();
|
||||
});
|
||||
|
||||
app.UseRateLimiter();
|
||||
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user