using System.Collections.Generic; using System.Linq; using Microsoft.Extensions.Options; using StellaOps.Vexer.Attestation.Extensions; using StellaOps.Vexer.Attestation; using StellaOps.Vexer.Attestation.Transparency; using StellaOps.Vexer.ArtifactStores.S3.Extensions; using StellaOps.Vexer.Export; using StellaOps.Vexer.Storage.Mongo; using StellaOps.Vexer.Connectors.RedHat.CSAF.DependencyInjection; var builder = WebApplication.CreateBuilder(args); var configuration = builder.Configuration; var services = builder.Services; services.AddOptions() .Bind(configuration.GetSection("Vexer:Storage:Mongo")) .ValidateOnStart(); services.AddVexerMongoStorage(); services.AddVexExportEngine(); services.AddVexExportCacheServices(); services.AddVexAttestation(); services.Configure(configuration.GetSection("Vexer:Attestation:Client")); services.AddRedHatCsafConnector(); var rekorSection = configuration.GetSection("Vexer:Attestation:Rekor"); if (rekorSection.Exists()) { services.AddVexRekorClient(opts => rekorSection.Bind(opts)); } var fileSystemSection = configuration.GetSection("Vexer:Artifacts:FileSystem"); if (fileSystemSection.Exists()) { services.AddVexFileSystemArtifactStore(opts => fileSystemSection.Bind(opts)); } else { services.AddVexFileSystemArtifactStore(_ => { }); } var s3Section = configuration.GetSection("Vexer:Artifacts:S3"); if (s3Section.Exists()) { services.AddVexS3ArtifactClient(opts => s3Section.GetSection("Client").Bind(opts)); services.AddSingleton(provider => { var options = new S3ArtifactStoreOptions(); s3Section.GetSection("Store").Bind(options); return new S3ArtifactStore( provider.GetRequiredService(), Microsoft.Extensions.Options.Options.Create(options), provider.GetRequiredService>()); }); } var offlineSection = configuration.GetSection("Vexer:Artifacts:OfflineBundle"); if (offlineSection.Exists()) { services.AddVexOfflineBundleArtifactStore(opts => offlineSection.Bind(opts)); } services.AddEndpointsApiExplorer(); services.AddHealthChecks(); services.AddSingleton(TimeProvider.System); var app = builder.Build(); app.MapGet("/vexer/status", async (HttpContext context, IEnumerable artifactStores, IOptions mongoOptions, TimeProvider timeProvider) => { var payload = new StatusResponse( timeProvider.GetUtcNow(), mongoOptions.Value.RawBucketName, mongoOptions.Value.GridFsInlineThresholdBytes, artifactStores.Select(store => store.GetType().Name).ToArray()); context.Response.ContentType = "application/json"; await System.Text.Json.JsonSerializer.SerializeAsync(context.Response.Body, payload); }); app.MapHealthChecks("/vexer/health"); app.Run(); public partial class Program; internal sealed record StatusResponse(DateTimeOffset UtcNow, string MongoBucket, int InlineThreshold, string[] ArtifactStores);