sln build fix (again), tests fixes, audit work and doctors work

This commit is contained in:
master
2026-01-12 22:15:51 +02:00
parent 9873f80830
commit 9330c64349
812 changed files with 48051 additions and 3891 deletions

View File

@@ -0,0 +1,132 @@
using System.Globalization;
using Microsoft.Extensions.Configuration;
using StellaOps.Doctor.Models;
using StellaOps.Doctor.Plugins;
namespace StellaOps.Doctor.Plugins.Security.Checks;
/// <summary>
/// Validates rate limiting configuration.
/// </summary>
public sealed class RateLimitingCheck : IDoctorCheck
{
/// <inheritdoc />
public string CheckId => "check.security.ratelimit";
/// <inheritdoc />
public string Name => "Rate Limiting";
/// <inheritdoc />
public string Description => "Validates rate limiting is configured to prevent abuse";
/// <inheritdoc />
public DoctorSeverity DefaultSeverity => DoctorSeverity.Warn;
/// <inheritdoc />
public IReadOnlyList<string> Tags => ["security", "ratelimit", "api"];
/// <inheritdoc />
public TimeSpan EstimatedDuration => TimeSpan.FromMilliseconds(50);
/// <inheritdoc />
public bool CanRun(DoctorPluginContext context) => true;
/// <inheritdoc />
public Task<DoctorCheckResult> RunAsync(DoctorPluginContext context, CancellationToken ct)
{
var result = context.CreateResult(CheckId, "stellaops.doctor.security", DoctorCategory.Security.ToString());
var rateLimitEnabled = context.Configuration.GetValue<bool?>("RateLimiting:Enabled")
?? context.Configuration.GetValue<bool?>("Security:RateLimiting:Enabled");
if (rateLimitEnabled == null)
{
return Task.FromResult(result
.Info("Rate limiting configuration not found")
.WithEvidence("Rate limiting", e =>
{
e.Add("Configured", "false");
e.Add("Recommendation", "Consider enabling rate limiting for API protection");
})
.Build());
}
if (rateLimitEnabled != true)
{
return Task.FromResult(result
.Warn("Rate limiting is disabled")
.WithEvidence("Rate limiting", e =>
{
e.Add("Enabled", "false");
e.Add("Recommendation", "Enable rate limiting to prevent API abuse");
})
.WithCauses("Rate limiting explicitly disabled in configuration")
.WithRemediation(r => r
.AddManualStep(1, "Enable rate limiting", "Set RateLimiting:Enabled to true"))
.WithVerification("stella doctor --check check.security.ratelimit")
.Build());
}
var permitLimit = context.Configuration.GetValue<int?>("RateLimiting:PermitLimit")
?? context.Configuration.GetValue<int?>("Security:RateLimiting:PermitLimit")
?? 100;
var windowSeconds = context.Configuration.GetValue<int?>("RateLimiting:WindowSeconds")
?? context.Configuration.GetValue<int?>("Security:RateLimiting:WindowSeconds")
?? 60;
var queueLimit = context.Configuration.GetValue<int?>("RateLimiting:QueueLimit")
?? context.Configuration.GetValue<int?>("Security:RateLimiting:QueueLimit")
?? 0;
var issues = new List<string>();
if (permitLimit > 10000)
{
issues.Add($"Rate limit permit count ({permitLimit}) is very high");
}
if (windowSeconds < 1)
{
issues.Add("Rate limit window is less than 1 second");
}
else if (windowSeconds > 3600)
{
issues.Add($"Rate limit window ({windowSeconds}s) is very long - may not effectively prevent bursts");
}
var requestsPerSecond = (double)permitLimit / windowSeconds;
if (requestsPerSecond > 1000)
{
issues.Add($"Effective rate ({requestsPerSecond:F0} req/s) may be too permissive");
}
if (issues.Count > 0)
{
return Task.FromResult(result
.Warn($"{issues.Count} rate limiting configuration issue(s)")
.WithEvidence("Rate limiting", e =>
{
e.Add("Enabled", "true");
e.Add("PermitLimit", permitLimit.ToString(CultureInfo.InvariantCulture));
e.Add("WindowSeconds", windowSeconds.ToString(CultureInfo.InvariantCulture));
e.Add("QueueLimit", queueLimit.ToString(CultureInfo.InvariantCulture));
e.Add("EffectiveRatePerSecond", requestsPerSecond.ToString("F2", CultureInfo.InvariantCulture));
})
.WithCauses(issues.ToArray())
.Build());
}
return Task.FromResult(result
.Pass("Rate limiting is properly configured")
.WithEvidence("Rate limiting", e =>
{
e.Add("Enabled", "true");
e.Add("PermitLimit", permitLimit.ToString(CultureInfo.InvariantCulture));
e.Add("WindowSeconds", windowSeconds.ToString(CultureInfo.InvariantCulture));
e.Add("QueueLimit", queueLimit.ToString(CultureInfo.InvariantCulture));
e.Add("EffectiveRatePerSecond", requestsPerSecond.ToString("F2", CultureInfo.InvariantCulture));
})
.Build());
}
}