This commit is contained in:
StellaOps Bot
2025-12-29 20:10:48 +02:00
297 changed files with 53621 additions and 390 deletions

View File

@@ -1,3 +1,4 @@
using System.Security.Claims;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Http;
@@ -141,12 +142,10 @@ internal static class SourcesEndpoints
private static async Task<IResult> HandleListAsync(
[AsParameters] ListSourcesQueryParams queryParams,
ISbomSourceService sourceService,
ITenantContext tenantContext,
HttpContext context,
CancellationToken ct)
{
var tenantId = tenantContext.TenantId;
if (string.IsNullOrEmpty(tenantId))
if (!TryResolveTenant(context, out var tenantId))
{
return ProblemResultFactory.Create(
context,
@@ -171,12 +170,10 @@ internal static class SourcesEndpoints
private static async Task<IResult> HandleGetAsync(
Guid sourceId,
ISbomSourceService sourceService,
ITenantContext tenantContext,
HttpContext context,
CancellationToken ct)
{
var tenantId = tenantContext.TenantId;
if (string.IsNullOrEmpty(tenantId))
if (!TryResolveTenant(context, out var tenantId))
{
return ProblemResultFactory.Create(
context,
@@ -202,12 +199,10 @@ internal static class SourcesEndpoints
private static async Task<IResult> HandleGetByNameAsync(
string name,
ISbomSourceService sourceService,
ITenantContext tenantContext,
HttpContext context,
CancellationToken ct)
{
var tenantId = tenantContext.TenantId;
if (string.IsNullOrEmpty(tenantId))
if (!TryResolveTenant(context, out var tenantId))
{
return ProblemResultFactory.Create(
context,
@@ -233,14 +228,11 @@ internal static class SourcesEndpoints
private static async Task<IResult> HandleCreateAsync(
CreateSourceRequest request,
ISbomSourceService sourceService,
ITenantContext tenantContext,
IUserContext userContext,
LinkGenerator links,
HttpContext context,
CancellationToken ct)
{
var tenantId = tenantContext.TenantId;
if (string.IsNullOrEmpty(tenantId))
if (!TryResolveTenant(context, out var tenantId))
{
return ProblemResultFactory.Create(
context,
@@ -249,7 +241,7 @@ internal static class SourcesEndpoints
StatusCodes.Status400BadRequest);
}
var userId = userContext.UserId ?? "system";
var userId = ResolveActor(context);
try
{
@@ -291,13 +283,10 @@ internal static class SourcesEndpoints
Guid sourceId,
UpdateSourceRequest request,
ISbomSourceService sourceService,
ITenantContext tenantContext,
IUserContext userContext,
HttpContext context,
CancellationToken ct)
{
var tenantId = tenantContext.TenantId;
if (string.IsNullOrEmpty(tenantId))
if (!TryResolveTenant(context, out var tenantId))
{
return ProblemResultFactory.Create(
context,
@@ -306,7 +295,7 @@ internal static class SourcesEndpoints
StatusCodes.Status400BadRequest);
}
var userId = userContext.UserId ?? "system";
var userId = ResolveActor(context);
try
{
@@ -344,12 +333,10 @@ internal static class SourcesEndpoints
private static async Task<IResult> HandleDeleteAsync(
Guid sourceId,
ISbomSourceService sourceService,
ITenantContext tenantContext,
HttpContext context,
CancellationToken ct)
{
var tenantId = tenantContext.TenantId;
if (string.IsNullOrEmpty(tenantId))
if (!TryResolveTenant(context, out var tenantId))
{
return ProblemResultFactory.Create(
context,
@@ -376,12 +363,10 @@ internal static class SourcesEndpoints
private static async Task<IResult> HandleTestConnectionAsync(
Guid sourceId,
ISbomSourceService sourceService,
ITenantContext tenantContext,
HttpContext context,
CancellationToken ct)
{
var tenantId = tenantContext.TenantId;
if (string.IsNullOrEmpty(tenantId))
if (!TryResolveTenant(context, out var tenantId))
{
return ProblemResultFactory.Create(
context,
@@ -408,12 +393,10 @@ internal static class SourcesEndpoints
private static async Task<IResult> HandleTestNewConnectionAsync(
TestConnectionRequest request,
ISbomSourceService sourceService,
ITenantContext tenantContext,
HttpContext context,
CancellationToken ct)
{
var tenantId = tenantContext.TenantId;
if (string.IsNullOrEmpty(tenantId))
if (!TryResolveTenant(context, out var tenantId))
{
return ProblemResultFactory.Create(
context,
@@ -430,13 +413,10 @@ internal static class SourcesEndpoints
Guid sourceId,
PauseSourceRequest request,
ISbomSourceService sourceService,
ITenantContext tenantContext,
IUserContext userContext,
HttpContext context,
CancellationToken ct)
{
var tenantId = tenantContext.TenantId;
if (string.IsNullOrEmpty(tenantId))
if (!TryResolveTenant(context, out var tenantId))
{
return ProblemResultFactory.Create(
context,
@@ -445,7 +425,7 @@ internal static class SourcesEndpoints
StatusCodes.Status400BadRequest);
}
var userId = userContext.UserId ?? "system";
var userId = ResolveActor(context);
try
{
@@ -465,13 +445,10 @@ internal static class SourcesEndpoints
private static async Task<IResult> HandleResumeAsync(
Guid sourceId,
ISbomSourceService sourceService,
ITenantContext tenantContext,
IUserContext userContext,
HttpContext context,
CancellationToken ct)
{
var tenantId = tenantContext.TenantId;
if (string.IsNullOrEmpty(tenantId))
if (!TryResolveTenant(context, out var tenantId))
{
return ProblemResultFactory.Create(
context,
@@ -480,7 +457,7 @@ internal static class SourcesEndpoints
StatusCodes.Status400BadRequest);
}
var userId = userContext.UserId ?? "system";
var userId = ResolveActor(context);
try
{
@@ -500,13 +477,10 @@ internal static class SourcesEndpoints
private static async Task<IResult> HandleActivateAsync(
Guid sourceId,
ISbomSourceService sourceService,
ITenantContext tenantContext,
IUserContext userContext,
HttpContext context,
CancellationToken ct)
{
var tenantId = tenantContext.TenantId;
if (string.IsNullOrEmpty(tenantId))
if (!TryResolveTenant(context, out var tenantId))
{
return ProblemResultFactory.Create(
context,
@@ -515,7 +489,7 @@ internal static class SourcesEndpoints
StatusCodes.Status400BadRequest);
}
var userId = userContext.UserId ?? "system";
var userId = ResolveActor(context);
try
{
@@ -536,13 +510,10 @@ internal static class SourcesEndpoints
Guid sourceId,
TriggerScanRequest? request,
ISbomSourceService sourceService,
ITenantContext tenantContext,
IUserContext userContext,
HttpContext context,
CancellationToken ct)
{
var tenantId = tenantContext.TenantId;
if (string.IsNullOrEmpty(tenantId))
if (!TryResolveTenant(context, out var tenantId))
{
return ProblemResultFactory.Create(
context,
@@ -551,7 +522,7 @@ internal static class SourcesEndpoints
StatusCodes.Status400BadRequest);
}
var userId = userContext.UserId ?? "system";
var userId = ResolveActor(context);
try
{
@@ -581,12 +552,10 @@ internal static class SourcesEndpoints
Guid sourceId,
[AsParameters] ListRunsQueryParams queryParams,
ISbomSourceService sourceService,
ITenantContext tenantContext,
HttpContext context,
CancellationToken ct)
{
var tenantId = tenantContext.TenantId;
if (string.IsNullOrEmpty(tenantId))
if (!TryResolveTenant(context, out var tenantId))
{
return ProblemResultFactory.Create(
context,
@@ -622,12 +591,10 @@ internal static class SourcesEndpoints
Guid sourceId,
Guid runId,
ISbomSourceService sourceService,
ITenantContext tenantContext,
HttpContext context,
CancellationToken ct)
{
var tenantId = tenantContext.TenantId;
if (string.IsNullOrEmpty(tenantId))
if (!TryResolveTenant(context, out var tenantId))
{
return ProblemResultFactory.Create(
context,
@@ -690,6 +657,57 @@ internal static class SourcesEndpoints
_ => "Unknown source type"
};
private static bool TryResolveTenant(HttpContext context, out string tenantId)
{
tenantId = string.Empty;
var tenant = context.User?.FindFirstValue(StellaOpsClaimTypes.Tenant);
if (!string.IsNullOrWhiteSpace(tenant))
{
tenantId = tenant.Trim();
return true;
}
if (context.Request.Headers.TryGetValue("X-Stella-Tenant", out var headerTenant))
{
var headerValue = headerTenant.ToString();
if (!string.IsNullOrWhiteSpace(headerValue))
{
tenantId = headerValue.Trim();
return true;
}
}
if (context.Request.Headers.TryGetValue("X-Tenant-Id", out var legacyTenant))
{
var headerValue = legacyTenant.ToString();
if (!string.IsNullOrWhiteSpace(headerValue))
{
tenantId = headerValue.Trim();
return true;
}
}
return false;
}
private static string ResolveActor(HttpContext context)
{
var subject = context.User?.FindFirstValue(StellaOpsClaimTypes.Subject);
if (!string.IsNullOrWhiteSpace(subject))
{
return subject.Trim();
}
var clientId = context.User?.FindFirstValue(StellaOpsClaimTypes.ClientId);
if (!string.IsNullOrWhiteSpace(clientId))
{
return clientId.Trim();
}
return "system";
}
private static IResult Json<T>(T value, int statusCode)
{
var payload = JsonSerializer.Serialize(value, SerializerOptions);

View File

@@ -5,12 +5,10 @@
"name": "Node Observation (Phase 22)",
"type": "node-observation",
"usedByEntrypoint": false,
"capabilities": [],
"threatVectors": [],
"metadata": {
"node.observation.components": "3",
"node.observation.edges": "5",
"node.observation.entrypoints": "1",
"node.observation.components": "2",
"node.observation.edges": "2",
"node.observation.entrypoints": "0",
"node.observation.native": "1",
"node.observation.wasm": "1"
},
@@ -19,8 +17,8 @@
"kind": "derived",
"source": "node.observation",
"locator": "phase22.ndjson",
"value": "{\u0022type\u0022:\u0022component\u0022,\u0022componentType\u0022:\u0022native\u0022,\u0022path\u0022:\u0022/native/addon.node\u0022,\u0022reason\u0022:\u0022native-addon-file\u0022,\u0022confidence\u0022:0.82,\u0022resolverTrace\u0022:[\u0022file:/native/addon.node\u0022],\u0022arch\u0022:\u0022x86_64\u0022,\u0022platform\u0022:\u0022linux\u0022}\r\n{\u0022type\u0022:\u0022component\u0022,\u0022componentType\u0022:\u0022wasm\u0022,\u0022path\u0022:\u0022/pkg/pkg.wasm\u0022,\u0022reason\u0022:\u0022wasm-file\u0022,\u0022confidence\u0022:0.8,\u0022resolverTrace\u0022:[\u0022file:/pkg/pkg.wasm\u0022]}\r\n{\u0022type\u0022:\u0022component\u0022,\u0022componentType\u0022:\u0022pkg\u0022,\u0022path\u0022:\u0022/src/app.js\u0022,\u0022format\u0022:\u0022esm\u0022,\u0022fromBundle\u0022:true,\u0022reason\u0022:\u0022source-map\u0022,\u0022confidence\u0022:0.87,\u0022resolverTrace\u0022:[\u0022bundle:/dist/main.js\u0022,\u0022map:/dist/main.js.map\u0022,\u0022source:/src/app.js\u0022]}\r\n{\u0022type\u0022:\u0022edge\u0022,\u0022edgeType\u0022:\u0022native-addon\u0022,\u0022from\u0022:\u0022/dist/main.js\u0022,\u0022to\u0022:\u0022/native/addon.node\u0022,\u0022reason\u0022:\u0022native-dlopen-string\u0022,\u0022confidence\u0022:0.76,\u0022resolverTrace\u0022:[\u0022source:/dist/main.js\u0022,\u0022call:process.dlopen(\\u0027../native/addon.node\\u0027)\u0022]}\r\n{\u0022type\u0022:\u0022edge\u0022,\u0022edgeType\u0022:\u0022wasm\u0022,\u0022from\u0022:\u0022/dist/main.js\u0022,\u0022to\u0022:\u0022/pkg/pkg.wasm\u0022,\u0022reason\u0022:\u0022wasm-import\u0022,\u0022confidence\u0022:0.74,\u0022resolverTrace\u0022:[\u0022source:/dist/main.js\u0022,\u0022call:WebAssembly.instantiate(\\u0027../pkg/pkg.wasm\\u0027)\u0022]}\r\n{\u0022type\u0022:\u0022edge\u0022,\u0022edgeType\u0022:\u0022capability\u0022,\u0022from\u0022:\u0022/dist/main.js\u0022,\u0022to\u0022:\u0022child_process.execFile\u0022,\u0022reason\u0022:\u0022capability-child-process\u0022,\u0022confidence\u0022:0.7,\u0022resolverTrace\u0022:[\u0022source:/dist/main.js\u0022,\u0022call:child_process.execFile\u0022]}\r\n{\u0022type\u0022:\u0022edge\u0022,\u0022edgeType\u0022:\u0022wasm\u0022,\u0022from\u0022:\u0022/src/app.js\u0022,\u0022to\u0022:\u0022/src/pkg/pkg.wasm\u0022,\u0022reason\u0022:\u0022wasm-import\u0022,\u0022confidence\u0022:0.74,\u0022resolverTrace\u0022:[\u0022source:/src/app.js\u0022,\u0022call:WebAssembly.instantiate(\\u0027./pkg/pkg.wasm\\u0027)\u0022]}\r\n{\u0022type\u0022:\u0022edge\u0022,\u0022edgeType\u0022:\u0022capability\u0022,\u0022from\u0022:\u0022/src/app.js\u0022,\u0022to\u0022:\u0022child_process.execFile\u0022,\u0022reason\u0022:\u0022capability-child-process\u0022,\u0022confidence\u0022:0.7,\u0022resolverTrace\u0022:[\u0022source:/src/app.js\u0022,\u0022call:child_process.execFile\u0022]}\r\n{\u0022type\u0022:\u0022entrypoint\u0022,\u0022path\u0022:\u0022/dist/main.js\u0022,\u0022format\u0022:\u0022esm\u0022,\u0022reason\u0022:\u0022bundle-entrypoint\u0022,\u0022confidence\u0022:0.88,\u0022resolverTrace\u0022:[\u0022bundle:/dist/main.js\u0022,\u0022map:/dist/main.js.map\u0022]}",
"sha256": "47eba68d13bf6a2b9a554ed02b10a31485d97e03b5264ef54bcdda428d7dfc45"
"value": "{\u0022type\u0022:\u0022component\u0022,\u0022componentType\u0022:\u0022native\u0022,\u0022path\u0022:\u0022/native/addon.node\u0022,\u0022reason\u0022:\u0022native-addon-file\u0022,\u0022confidence\u0022:0.82,\u0022resolverTrace\u0022:[\u0022file:/native/addon.node\u0022],\u0022arch\u0022:\u0022x86_64\u0022,\u0022platform\u0022:\u0022linux\u0022}\r\n{\u0022type\u0022:\u0022component\u0022,\u0022componentType\u0022:\u0022wasm\u0022,\u0022path\u0022:\u0022/pkg/pkg.wasm\u0022,\u0022reason\u0022:\u0022wasm-file\u0022,\u0022confidence\u0022:0.8,\u0022resolverTrace\u0022:[\u0022file:/pkg/pkg.wasm\u0022]}\r\n{\u0022type\u0022:\u0022edge\u0022,\u0022edgeType\u0022:\u0022wasm\u0022,\u0022from\u0022:\u0022/src/app.js\u0022,\u0022to\u0022:\u0022/src/pkg/pkg.wasm\u0022,\u0022reason\u0022:\u0022wasm-import\u0022,\u0022confidence\u0022:0.74,\u0022resolverTrace\u0022:[\u0022source:/src/app.js\u0022,\u0022call:WebAssembly.instantiate(\\u0027./pkg/pkg.wasm\\u0027)\u0022]}\r\n{\u0022type\u0022:\u0022edge\u0022,\u0022edgeType\u0022:\u0022capability\u0022,\u0022from\u0022:\u0022/src/app.js\u0022,\u0022to\u0022:\u0022child_process.execFile\u0022,\u0022reason\u0022:\u0022capability-child-process\u0022,\u0022confidence\u0022:0.7,\u0022resolverTrace\u0022:[\u0022source:/src/app.js\u0022,\u0022call:child_process.execFile\u0022]}",
"sha256": "1329f1c41716d8430b5bdb6d02d1d5f2be1be80877ac15a7e72d3a079fffa4fb"
}
]
}