142 lines
4.1 KiB
C#
142 lines
4.1 KiB
C#
|
|
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
|
using Microsoft.AspNetCore.RateLimiting;
|
|
using OpenTelemetry.Resources;
|
|
using OpenTelemetry.Trace;
|
|
using Serilog;
|
|
using StellaOps.Auth.ServerIntegration;
|
|
using StellaOps.VexLens.Api;
|
|
using StellaOps.VexLens.Consensus;
|
|
using StellaOps.VexLens.Persistence;
|
|
using StellaOps.VexLens.Persistence.Postgres;
|
|
using StellaOps.VexLens.Storage;
|
|
using StellaOps.VexLens.Trust;
|
|
using StellaOps.VexLens.Verification;
|
|
using StellaOps.VexLens.WebService.Extensions;
|
|
using System.Threading.RateLimiting;
|
|
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
|
|
// Configure Serilog
|
|
Log.Logger = new LoggerConfiguration()
|
|
.ReadFrom.Configuration(builder.Configuration)
|
|
.Enrich.FromLogContext()
|
|
.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
|
|
.CreateLogger();
|
|
|
|
builder.Host.UseSerilog();
|
|
|
|
// Configure OpenAPI
|
|
builder.Services.AddEndpointsApiExplorer();
|
|
builder.Services.AddOpenApi();
|
|
|
|
// Configure OpenTelemetry
|
|
builder.Services.AddOpenTelemetry()
|
|
.ConfigureResource(resource => resource.AddService("StellaOps.VexLens"))
|
|
.WithTracing(tracing =>
|
|
{
|
|
tracing
|
|
.AddAspNetCoreInstrumentation()
|
|
.AddHttpClientInstrumentation();
|
|
|
|
if (builder.Environment.IsDevelopment())
|
|
{
|
|
tracing.AddConsoleExporter();
|
|
}
|
|
});
|
|
|
|
// Configure VexLens services
|
|
builder.Services.AddSingleton<IVexConsensusEngine, VexConsensusEngine>();
|
|
builder.Services.AddSingleton<ITrustWeightEngine, TrustWeightEngine>();
|
|
builder.Services.AddSingleton<IConsensusProjectionStore, InMemoryConsensusProjectionStore>();
|
|
builder.Services.AddSingleton<IIssuerDirectory, InMemoryIssuerDirectory>();
|
|
builder.Services.AddSingleton<IVexStatementProvider, NullVexStatementProvider>();
|
|
builder.Services.AddScoped<IVexLensApiService, VexLensApiService>();
|
|
|
|
// Note: PostgreSQL persistence configuration requires VexLens persistence service registration
|
|
// For now, using in-memory stores configured above
|
|
|
|
// Configure health checks
|
|
builder.Services.AddHealthChecks();
|
|
|
|
// Configure rate limiting
|
|
builder.Services.AddRateLimiter(options =>
|
|
{
|
|
options.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
|
|
options.AddFixedWindowLimiter("vexlens", limiterOptions =>
|
|
{
|
|
limiterOptions.PermitLimit = 100;
|
|
limiterOptions.Window = TimeSpan.FromMinutes(1);
|
|
});
|
|
});
|
|
|
|
builder.Services.AddStellaOpsCors(builder.Environment, builder.Configuration);
|
|
|
|
builder.TryAddStellaOpsLocalBinding("vexlens");
|
|
var app = builder.Build();
|
|
app.LogStellaOpsLocalHostname("vexlens");
|
|
|
|
// Configure request pipeline
|
|
if (app.Environment.IsDevelopment())
|
|
{
|
|
app.MapOpenApi();
|
|
}
|
|
|
|
app.UseStellaOpsCors();
|
|
app.UseRateLimiter();
|
|
app.UseSerilogRequestLogging();
|
|
|
|
// Map health check endpoint
|
|
app.MapHealthChecks("/health", new HealthCheckOptions
|
|
{
|
|
ResponseWriter = async (context, report) =>
|
|
{
|
|
context.Response.ContentType = "application/json";
|
|
var result = new
|
|
{
|
|
status = report.Status.ToString(),
|
|
checks = report.Entries.Select(e => new
|
|
{
|
|
name = e.Key,
|
|
status = e.Value.Status.ToString(),
|
|
description = e.Value.Description
|
|
})
|
|
};
|
|
await context.Response.WriteAsJsonAsync(result);
|
|
}
|
|
});
|
|
|
|
// Map VexLens API endpoints
|
|
app.MapVexLensEndpoints();
|
|
|
|
// Log startup
|
|
Log.Information("VexLens WebService starting on {Urls}", string.Join(", ", app.Urls));
|
|
|
|
try
|
|
{
|
|
app.Run();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Fatal(ex, "VexLens WebService terminated unexpectedly");
|
|
}
|
|
finally
|
|
{
|
|
Log.CloseAndFlush();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Null implementation for development without VexHub integration.
|
|
/// </summary>
|
|
internal sealed class NullVexStatementProvider : IVexStatementProvider
|
|
{
|
|
public Task<IReadOnlyList<VexStatementWithContext>> GetStatementsAsync(
|
|
string vulnerabilityId,
|
|
string productKey,
|
|
string? tenantId,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
return Task.FromResult<IReadOnlyList<VexStatementWithContext>>([]);
|
|
}
|
|
}
|