feat(rate-limiting): Implement core rate limiting functionality with configuration, decision-making, metrics, middleware, and service registration

- Add RateLimitConfig for configuration management with YAML binding support.
- Introduce RateLimitDecision to encapsulate the result of rate limit checks.
- Implement RateLimitMetrics for OpenTelemetry metrics tracking.
- Create RateLimitMiddleware for enforcing rate limits on incoming requests.
- Develop RateLimitService to orchestrate instance and environment rate limit checks.
- Add RateLimitServiceCollectionExtensions for dependency injection registration.
This commit is contained in:
master
2025-12-17 18:02:37 +02:00
parent 394b57f6bf
commit 8bbfe4d2d2
211 changed files with 47179 additions and 1590 deletions

View File

@@ -1,7 +1,9 @@
using System.Collections.Immutable;
using System.Text;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using StellaOps.Scanner.SmartDiff.Detection;
using StellaOps.Scanner.SmartDiff.Output;
using StellaOps.Scanner.Storage.Postgres;
using StellaOps.Scanner.WebService.Security;
@@ -10,6 +12,7 @@ namespace StellaOps.Scanner.WebService.Endpoints;
/// <summary>
/// Smart-Diff API endpoints for material risk changes and VEX candidates.
/// Per Sprint 3500.3 - Smart-Diff Detection Rules.
/// Task SDIFF-BIN-029 - API endpoint `GET /scans/{id}/sarif`
/// </summary>
internal static class SmartDiffEndpoints
{
@@ -27,6 +30,14 @@ internal static class SmartDiffEndpoints
.Produces(StatusCodes.Status404NotFound)
.RequireAuthorization(ScannerPolicies.ScansRead);
// SARIF output endpoint (Task SDIFF-BIN-029)
group.MapGet("/scans/{scanId}/sarif", HandleGetScanSarifAsync)
.WithName("scanner.smartdiff.sarif")
.WithTags("SmartDiff", "SARIF")
.Produces(StatusCodes.Status200OK, contentType: "application/sarif+json")
.Produces(StatusCodes.Status404NotFound)
.RequireAuthorization(ScannerPolicies.ScansRead);
// VEX candidate endpoints
group.MapGet("/images/{digest}/candidates", HandleGetCandidatesAsync)
.WithName("scanner.smartdiff.candidates")
@@ -51,6 +62,81 @@ internal static class SmartDiffEndpoints
.RequireAuthorization(ScannerPolicies.ScansWrite);
}
/// <summary>
/// GET /smart-diff/scans/{scanId}/sarif - Get Smart-Diff results as SARIF 2.1.0.
/// Task: SDIFF-BIN-029
/// </summary>
private static async Task<IResult> HandleGetScanSarifAsync(
string scanId,
IMaterialRiskChangeRepository changeRepo,
IVexCandidateStore candidateStore,
IScanMetadataRepository? metadataRepo = null,
bool? pretty = null,
CancellationToken ct = default)
{
// Gather all data for the scan
var changes = await changeRepo.GetChangesForScanAsync(scanId, ct);
// Get scan metadata if available
string? baseDigest = null;
string? targetDigest = null;
DateTimeOffset scanTime = DateTimeOffset.UtcNow;
if (metadataRepo is not null)
{
var metadata = await metadataRepo.GetScanMetadataAsync(scanId, ct);
if (metadata is not null)
{
baseDigest = metadata.BaseDigest;
targetDigest = metadata.TargetDigest;
scanTime = metadata.ScanTime;
}
}
// Convert to SARIF input format
var sarifInput = new SmartDiffSarifInput(
ScannerVersion: GetScannerVersion(),
ScanTime: scanTime,
BaseDigest: baseDigest,
TargetDigest: targetDigest,
MaterialChanges: changes.Select(c => new MaterialRiskChange(
VulnId: c.VulnId,
ComponentPurl: c.ComponentPurl,
Direction: c.IsRiskIncrease ? RiskDirection.Increased : RiskDirection.Decreased,
Reason: c.ChangeReason,
FilePath: c.FilePath
)).ToList(),
HardeningRegressions: [],
VexCandidates: [],
ReachabilityChanges: []);
// Generate SARIF
var options = new SarifOutputOptions
{
IndentedJson = pretty == true,
IncludeVexCandidates = true,
IncludeHardeningRegressions = true,
IncludeReachabilityChanges = true
};
var generator = new SarifOutputGenerator();
var sarifJson = generator.Generate(sarifInput, options);
// Return as SARIF content type with proper filename
var fileName = $"smartdiff-{scanId}.sarif";
return Results.Text(
sarifJson,
contentType: "application/sarif+json",
statusCode: StatusCodes.Status200OK);
}
private static string GetScannerVersion()
{
var assembly = typeof(SmartDiffEndpoints).Assembly;
var version = assembly.GetName().Version;
return version?.ToString() ?? "1.0.0";
}
/// <summary>
/// GET /smart-diff/scans/{scanId}/changes - Get material risk changes for a scan.
/// </summary>