tenant fixes

This commit is contained in:
master
2026-02-23 23:44:50 +02:00
parent bdb1438654
commit 4f947a8b61
159 changed files with 1064 additions and 556 deletions

View File

@@ -9,6 +9,7 @@ using StellaOps.PacksRegistry.WebService;
using StellaOps.PacksRegistry.WebService.Contracts;
using StellaOps.PacksRegistry.WebService.Options;
using StellaOps.Auth.ServerIntegration;
using StellaOps.Auth.ServerIntegration.Tenancy;
using StellaOps.Router.AspNet;
using System.Text.Json.Serialization;
@@ -57,6 +58,7 @@ builder.Services.AddSingleton(TimeProvider.System);
builder.Services.AddHealthChecks();
builder.Services.AddStellaOpsTenantServices();
builder.Services.AddStellaOpsCors(builder.Environment, builder.Configuration);
// Stella Router integration
@@ -76,6 +78,7 @@ if (app.Environment.IsDevelopment())
}
app.UseStellaOpsCors();
app.UseStellaOpsTenantMiddleware();
app.MapHealthChecks("/healthz");
app.TryUseStellaRouter(routerEnabled);
@@ -160,7 +163,8 @@ app.MapPost("/api/v1/packs", async (PackUploadRequest request, PackService servi
.WithDescription("Uploads a new policy pack as base64-encoded content with optional signature and provenance attachment. Returns 201 Created with the registered pack record and assigned pack ID. Requires the X-StellaOps-Tenant header or a tenantId body field.")
.Produces<PackResponse>(StatusCodes.Status201Created)
.Produces(StatusCodes.Status400BadRequest)
.Produces(StatusCodes.Status401Unauthorized);
.Produces(StatusCodes.Status401Unauthorized)
.RequireTenant();
app.MapGet("/api/v1/packs", async (string? tenant, bool? includeDeprecated, PackService service, LifecycleService lifecycleService, HttpContext context, AuthOptions auth, CancellationToken cancellationToken) =>
{
@@ -197,7 +201,8 @@ app.MapGet("/api/v1/packs", async (string? tenant, bool? includeDeprecated, Pack
.WithName("ListPacks")
.WithDescription("Returns the list of policy packs for the specified tenant, optionally excluding deprecated packs. When tenant allowlists are configured, a tenant query parameter or X-StellaOps-Tenant header is required.")
.Produces<IEnumerable<PackResponse>>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized);
.Produces(StatusCodes.Status401Unauthorized)
.RequireTenant();
app.MapGet("/api/v1/packs/{packId}", async (string packId, PackService service, HttpContext context, AuthOptions auth, CancellationToken cancellationToken) =>
{
@@ -226,7 +231,8 @@ app.MapGet("/api/v1/packs/{packId}", async (string packId, PackService service,
.Produces<PackResponse>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status404NotFound);
.Produces(StatusCodes.Status404NotFound)
.RequireTenant();
app.MapGet("/api/v1/packs/{packId}/content", async (string packId, PackService service, HttpContext context, AuthOptions auth, CancellationToken cancellationToken) =>
{
@@ -262,7 +268,8 @@ app.MapGet("/api/v1/packs/{packId}/content", async (string packId, PackService s
.Produces(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status404NotFound);
.Produces(StatusCodes.Status404NotFound)
.RequireTenant();
app.MapGet("/api/v1/packs/{packId}/provenance", async (string packId, PackService service, HttpContext context, AuthOptions auth, CancellationToken cancellationToken) =>
{
@@ -302,7 +309,8 @@ app.MapGet("/api/v1/packs/{packId}/provenance", async (string packId, PackServic
.Produces(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status404NotFound);
.Produces(StatusCodes.Status404NotFound)
.RequireTenant();
app.MapGet("/api/v1/packs/{packId}/manifest", async (string packId, PackService service, HttpContext context, AuthOptions auth, CancellationToken cancellationToken) =>
{
@@ -344,7 +352,8 @@ app.MapGet("/api/v1/packs/{packId}/manifest", async (string packId, PackService
.Produces<PackManifestResponse>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status404NotFound);
.Produces(StatusCodes.Status404NotFound)
.RequireTenant();
app.MapPost("/api/v1/packs/{packId}/signature", async (string packId, RotateSignatureRequest request, PackService service, HttpContext context, AuthOptions auth, CancellationToken cancellationToken) =>
{
@@ -391,7 +400,8 @@ app.MapPost("/api/v1/packs/{packId}/signature", async (string packId, RotateSign
.Produces(StatusCodes.Status400BadRequest)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status404NotFound);
.Produces(StatusCodes.Status404NotFound)
.RequireTenant();
app.MapPost("/api/v1/packs/{packId}/attestations", async (string packId, AttestationUploadRequest request, AttestationService attestationService, HttpContext context, AuthOptions auth, CancellationToken cancellationToken) =>
{
@@ -433,7 +443,8 @@ app.MapPost("/api/v1/packs/{packId}/attestations", async (string packId, Attesta
.Produces(StatusCodes.Status400BadRequest)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status404NotFound);
.Produces(StatusCodes.Status404NotFound)
.RequireTenant();
app.MapGet("/api/v1/packs/{packId}/attestations", async (string packId, AttestationService attestationService, HttpContext context, AuthOptions auth, CancellationToken cancellationToken) =>
{
@@ -461,7 +472,8 @@ app.MapGet("/api/v1/packs/{packId}/attestations", async (string packId, Attestat
.Produces<IEnumerable<AttestationResponse>>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status404NotFound);
.Produces(StatusCodes.Status404NotFound)
.RequireTenant();
app.MapGet("/api/v1/packs/{packId}/attestations/{type}", async (string packId, string type, AttestationService attestationService, HttpContext context, AuthOptions auth, CancellationToken cancellationToken) =>
{
@@ -496,7 +508,8 @@ app.MapGet("/api/v1/packs/{packId}/attestations/{type}", async (string packId, s
.Produces(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status404NotFound);
.Produces(StatusCodes.Status404NotFound)
.RequireTenant();
app.MapGet("/api/v1/packs/{packId}/parity", async (string packId, ParityService parityService, HttpContext context, AuthOptions auth, CancellationToken cancellationToken) =>
{
@@ -525,7 +538,8 @@ app.MapGet("/api/v1/packs/{packId}/parity", async (string packId, ParityService
.Produces<ParityResponse>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status404NotFound);
.Produces(StatusCodes.Status404NotFound)
.RequireTenant();
app.MapGet("/api/v1/packs/{packId}/lifecycle", async (string packId, LifecycleService lifecycleService, HttpContext context, AuthOptions auth, CancellationToken cancellationToken) =>
{
@@ -554,7 +568,8 @@ app.MapGet("/api/v1/packs/{packId}/lifecycle", async (string packId, LifecycleSe
.Produces<LifecycleResponse>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status404NotFound);
.Produces(StatusCodes.Status404NotFound)
.RequireTenant();
app.MapPost("/api/v1/packs/{packId}/lifecycle", async (string packId, LifecycleRequest request, LifecycleService lifecycleService, HttpContext context, AuthOptions auth, CancellationToken cancellationToken) =>
{
@@ -596,7 +611,8 @@ app.MapPost("/api/v1/packs/{packId}/lifecycle", async (string packId, LifecycleR
.Produces(StatusCodes.Status400BadRequest)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status404NotFound);
.Produces(StatusCodes.Status404NotFound)
.RequireTenant();
app.MapPost("/api/v1/packs/{packId}/parity", async (string packId, ParityRequest request, ParityService parityService, HttpContext context, AuthOptions auth, CancellationToken cancellationToken) =>
{
@@ -638,7 +654,8 @@ app.MapPost("/api/v1/packs/{packId}/parity", async (string packId, ParityRequest
.Produces(StatusCodes.Status400BadRequest)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status404NotFound);
.Produces(StatusCodes.Status404NotFound)
.RequireTenant();
app.MapPost("/api/v1/export/offline-seed", async (OfflineSeedRequest request, ExportService exportService, HttpContext context, AuthOptions auth, CancellationToken cancellationToken) =>
{
@@ -667,7 +684,8 @@ app.MapPost("/api/v1/export/offline-seed", async (OfflineSeedRequest request, Ex
.Produces(StatusCodes.Status200OK)
.Produces(StatusCodes.Status400BadRequest)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden);
.Produces(StatusCodes.Status403Forbidden)
.RequireTenant();
app.MapPost("/api/v1/mirrors", async (MirrorRequest request, MirrorService mirrorService, HttpContext context, AuthOptions auth, CancellationToken cancellationToken) =>
{
@@ -700,7 +718,8 @@ app.MapPost("/api/v1/mirrors", async (MirrorRequest request, MirrorService mirro
.Produces<MirrorResponse>(StatusCodes.Status201Created)
.Produces(StatusCodes.Status400BadRequest)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden);
.Produces(StatusCodes.Status403Forbidden)
.RequireTenant();
app.MapGet("/api/v1/mirrors", async (string? tenant, MirrorService mirrorService, HttpContext context, AuthOptions auth, CancellationToken cancellationToken) =>
{
@@ -723,7 +742,8 @@ app.MapGet("/api/v1/mirrors", async (string? tenant, MirrorService mirrorService
.WithDescription("Returns all mirror registrations for the specified tenant, or all mirrors if no tenant filter is applied. Returns 403 if the caller's tenant allowlist excludes the requested tenant.")
.Produces<IEnumerable<MirrorResponse>>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden);
.Produces(StatusCodes.Status403Forbidden)
.RequireTenant();
app.MapPost("/api/v1/mirrors/{id}/sync", async (string id, MirrorSyncRequest request, MirrorService mirrorService, HttpContext context, AuthOptions auth, CancellationToken cancellationToken) =>
{
@@ -752,7 +772,8 @@ app.MapPost("/api/v1/mirrors/{id}/sync", async (string id, MirrorSyncRequest req
.Produces(StatusCodes.Status400BadRequest)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden)
.Produces(StatusCodes.Status404NotFound);
.Produces(StatusCodes.Status404NotFound)
.RequireTenant();
app.MapGet("/api/v1/compliance/summary", async (string? tenant, ComplianceService complianceService, HttpContext context, AuthOptions auth, CancellationToken cancellationToken) =>
{
@@ -775,7 +796,8 @@ app.MapGet("/api/v1/compliance/summary", async (string? tenant, ComplianceServic
.WithDescription("Returns a compliance summary for the specified tenant's pack collection including signed pack count, unsigned count, packs with attestations, deprecated packs, and mirror sync status breakdown. Returns 403 if the tenant is not allowed.")
.Produces<ComplianceSummary>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status401Unauthorized)
.Produces(StatusCodes.Status403Forbidden);
.Produces(StatusCodes.Status403Forbidden)
.RequireTenant();
// Refresh Router endpoint cache
app.TryRefreshStellaRouterEndpoints(routerEnabled);