using System.IO; using System.Threading.RateLimiting; using Microsoft.AspNetCore.RateLimiting; using Microsoft.Extensions.Options; using NetEscapades.Configuration.Yaml; using StellaOps.Auth.Abstractions; using StellaOps.Auth.Client; using StellaOps.Auth.ServerIntegration; using StellaOps.Configuration; using StellaOps.Policy.Engine.Hosting; using StellaOps.Policy.Engine.Options; using StellaOps.Policy.Engine.Compilation; using StellaOps.Policy.Engine.Endpoints; using StellaOps.Policy.Engine.BatchEvaluation; using StellaOps.Policy.Engine.DependencyInjection; using StellaOps.PolicyDsl; using StellaOps.Policy.Engine.Services; using StellaOps.Policy.Engine.Workers; using StellaOps.Policy.Engine.Streaming; using StellaOps.Policy.Engine.Telemetry; using StellaOps.Policy.Engine.ConsoleSurface; using StellaOps.AirGap.Policy; using StellaOps.Policy.Engine.Orchestration; using StellaOps.Policy.Engine.ReachabilityFacts; using StellaOps.Policy.Engine.Storage.InMemory; using StellaOps.Policy.Engine.Storage.Mongo.Repositories; var builder = WebApplication.CreateBuilder(args); var policyEngineConfigFiles = new[] { "../etc/policy-engine.yaml", "../etc/policy-engine.local.yaml", "policy-engine.yaml", "policy-engine.local.yaml" }; var policyEngineActivationConfigFiles = new[] { "../etc/policy-engine.activation.yaml", "../etc/policy-engine.activation.local.yaml", "/config/policy-engine/activation.yaml", "policy-engine.activation.yaml", "policy-engine.activation.local.yaml" }; builder.Logging.ClearProviders(); builder.Logging.AddConsole(); builder.Configuration.AddStellaOpsDefaults(options => { options.BasePath = builder.Environment.ContentRootPath; options.EnvironmentPrefix = "STELLAOPS_POLICY_ENGINE_"; options.ConfigureBuilder = configurationBuilder => { var contentRoot = builder.Environment.ContentRootPath; foreach (var relative in policyEngineConfigFiles) { var path = Path.Combine(contentRoot, relative); configurationBuilder.AddYamlFile(path, optional: true); } foreach (var relative in policyEngineActivationConfigFiles) { var path = Path.Combine(contentRoot, relative); configurationBuilder.AddYamlFile(path, optional: true); } }; }); var bootstrap = StellaOpsConfigurationBootstrapper.Build(options => { options.BasePath = builder.Environment.ContentRootPath; options.EnvironmentPrefix = "STELLAOPS_POLICY_ENGINE_"; options.BindingSection = PolicyEngineOptions.SectionName; options.ConfigureBuilder = configurationBuilder => { foreach (var relative in policyEngineConfigFiles) { var path = Path.Combine(builder.Environment.ContentRootPath, relative); configurationBuilder.AddYamlFile(path, optional: true); } foreach (var relative in policyEngineActivationConfigFiles) { var path = Path.Combine(builder.Environment.ContentRootPath, relative); configurationBuilder.AddYamlFile(path, optional: true); } }; options.PostBind = static (value, _) => value.Validate(); }); builder.Configuration.AddConfiguration(bootstrap.Configuration); builder.ConfigurePolicyEngineTelemetry(bootstrap.Options); builder.Services.AddAirGapEgressPolicy(builder.Configuration, sectionName: "AirGap"); builder.Services.AddOptions() .Bind(builder.Configuration.GetSection(PolicyEngineOptions.SectionName)) .Validate(options => { try { options.Validate(); return true; } catch (Exception ex) { throw new OptionsValidationException( PolicyEngineOptions.SectionName, typeof(PolicyEngineOptions), new[] { ex.Message }); } }) .ValidateOnStart(); builder.Services.AddSingleton(sp => sp.GetRequiredService>().Value); builder.Services.AddSingleton(sp => sp.GetRequiredService().ExceptionLifecycle); builder.Services.AddSingleton(TimeProvider.System); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(sp => new StellaOps.Policy.Engine.Events.LoggingExceptionEventPublisher( sp.GetService(), sp.GetRequiredService>())); builder.Services.AddSingleton(); builder.Services.AddHostedService(); builder.Services.AddHostedService(); builder.Services.AddHostedService(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddPolicyEngineCore(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddHttpContextAccessor(); builder.Services.AddRouting(options => options.LowercaseUrls = true); builder.Services.AddProblemDetails(); builder.Services.AddHealthChecks(); // Rate limiting configuration for simulation endpoints var rateLimitOptions = builder.Configuration .GetSection(PolicyEngineRateLimitOptions.SectionName) .Get() ?? new PolicyEngineRateLimitOptions(); if (rateLimitOptions.Enabled) { builder.Services.AddRateLimiter(options => { options.RejectionStatusCode = StatusCodes.Status429TooManyRequests; options.AddTokenBucketLimiter(PolicyEngineRateLimitOptions.PolicyName, limiterOptions => { limiterOptions.TokenLimit = rateLimitOptions.SimulationPermitLimit; limiterOptions.ReplenishmentPeriod = TimeSpan.FromSeconds(rateLimitOptions.WindowSeconds); limiterOptions.TokensPerPeriod = rateLimitOptions.SimulationPermitLimit; limiterOptions.QueueLimit = rateLimitOptions.QueueLimit; limiterOptions.QueueProcessingOrder = QueueProcessingOrder.OldestFirst; }); options.OnRejected = async (context, cancellationToken) => { var tenant = context.HttpContext.User.FindFirst("tenant_id")?.Value; var endpoint = context.HttpContext.Request.Path.Value; PolicyEngineTelemetry.RecordRateLimitExceeded(tenant, endpoint); context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests; context.HttpContext.Response.Headers.RetryAfter = rateLimitOptions.WindowSeconds.ToString(); await context.HttpContext.Response.WriteAsJsonAsync(new { error = "ERR_POL_007", message = "Rate limit exceeded. Please retry after the reset window.", retryAfterSeconds = rateLimitOptions.WindowSeconds }, cancellationToken); }; }); } builder.Services.AddAuthentication(); builder.Services.AddAuthorization(); builder.Services.AddStellaOpsScopeHandler(); builder.Services.AddStellaOpsResourceServerAuthentication( builder.Configuration, configurationSection: $"{PolicyEngineOptions.SectionName}:ResourceServer"); if (bootstrap.Options.Authority.Enabled) { builder.Services.AddStellaOpsAuthClient(clientOptions => { clientOptions.Authority = bootstrap.Options.Authority.Issuer; clientOptions.ClientId = bootstrap.Options.Authority.ClientId; clientOptions.ClientSecret = bootstrap.Options.Authority.ClientSecret; clientOptions.HttpTimeout = TimeSpan.FromSeconds(bootstrap.Options.Authority.BackchannelTimeoutSeconds); clientOptions.DefaultScopes.Clear(); foreach (var scope in bootstrap.Options.Authority.Scopes) { clientOptions.DefaultScopes.Add(scope); } }); } var app = builder.Build(); app.UseAuthentication(); app.UseAuthorization(); if (rateLimitOptions.Enabled) { app.UseRateLimiter(); } app.MapHealthChecks("/healthz"); app.MapGet("/readyz", (PolicyEngineStartupDiagnostics diagnostics) => diagnostics.IsReady ? Results.Ok(new { status = "ready" }) : Results.StatusCode(StatusCodes.Status503ServiceUnavailable)) .WithName("Readiness"); app.MapGet("/", () => Results.Redirect("/healthz")); app.MapPolicyCompilation(); app.MapPolicyPacks(); app.MapPathScopeSimulation(); app.MapOverlaySimulation(); app.MapEvidenceSummaries(); app.MapBatchEvaluation(); app.MapConsoleSimulationDiff(); app.MapTrustWeighting(); app.MapAdvisoryAiKnobs(); app.MapBatchContext(); app.MapOrchestratorJobs(); app.MapPolicyWorker(); app.MapLedgerExport(); app.MapSnapshots(); app.MapViolations(); app.MapPolicyDecisions(); app.MapRiskProfiles(); app.MapRiskProfileSchema(); app.MapScopeAttachments(); app.MapRiskSimulation(); app.MapOverrides(); app.MapProfileExport(); app.MapProfileEvents(); app.Run();