Files
git.stella-ops.org/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/ProofSpineEndpointsTests.cs
StellaOps Bot 8137503221 up
2025-12-15 09:23:28 +02:00

129 lines
5.1 KiB
C#

using System.Collections.Generic;
using System.Net;
using System.Net.Http.Json;
using System.Text.Json;
using Microsoft.Extensions.DependencyInjection;
using StellaOps.Scanner.ProofSpine;
using Xunit;
namespace StellaOps.Scanner.WebService.Tests;
public sealed class ProofSpineEndpointsTests
{
[Fact]
public async Task GetSpine_ReturnsSpine_WithVerification()
{
await using var factory = new ScannerApplicationFactory();
using var scope = factory.Services.CreateScope();
var builder = scope.ServiceProvider.GetRequiredService<ProofSpineBuilder>();
var repository = scope.ServiceProvider.GetRequiredService<IProofSpineRepository>();
var spine = await builder
.ForArtifact("sha256:feedface")
.ForVulnerability("CVE-2025-0001")
.WithPolicyProfile("default")
.WithScanRun("scan-001")
.AddSbomSlice("sha256:sbom", new[] { "pkg:a", "pkg:b" }, toolId: "sbom", toolVersion: "1.0.0")
.AddPolicyEval(
policyDigest: "sha256:policy",
factors: new Dictionary<string, string> { ["policy"] = "default" },
verdict: "not_affected",
verdictReason: "component_not_present",
toolId: "policy",
toolVersion: "1.0.0")
.BuildAsync();
await repository.SaveAsync(spine);
var client = factory.CreateClient();
var response = await client.GetAsync($"/api/v1/spines/{spine.SpineId}");
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadFromJsonAsync<JsonElement>();
Assert.Equal(spine.SpineId, body.GetProperty("spineId").GetString());
var segments = body.GetProperty("segments");
Assert.True(segments.GetArrayLength() > 0);
Assert.True(body.TryGetProperty("verification", out _));
}
[Fact]
public async Task ListSpinesByScan_ReturnsSummaries_WithSegmentCount()
{
await using var factory = new ScannerApplicationFactory();
using var scope = factory.Services.CreateScope();
var builder = scope.ServiceProvider.GetRequiredService<ProofSpineBuilder>();
var repository = scope.ServiceProvider.GetRequiredService<IProofSpineRepository>();
var spine = await builder
.ForArtifact("sha256:feedface")
.ForVulnerability("CVE-2025-0002")
.WithPolicyProfile("default")
.WithScanRun("scan-002")
.AddSbomSlice("sha256:sbom", new[] { "pkg:a" }, toolId: "sbom", toolVersion: "1.0.0")
.AddPolicyEval(
policyDigest: "sha256:policy",
factors: new Dictionary<string, string> { ["policy"] = "default" },
verdict: "affected",
verdictReason: "reachable",
toolId: "policy",
toolVersion: "1.0.0")
.BuildAsync();
await repository.SaveAsync(spine);
var client = factory.CreateClient();
var response = await client.GetAsync("/api/v1/scans/scan-002/spines");
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadFromJsonAsync<JsonElement>();
var items = body.GetProperty("items");
Assert.Equal(1, items.GetArrayLength());
Assert.Equal(spine.SpineId, items[0].GetProperty("spineId").GetString());
Assert.True(items[0].GetProperty("segmentCount").GetInt32() > 0);
}
[Fact]
public async Task GetSpine_ReturnsInvalidStatus_WhenSegmentTampered()
{
await using var factory = new ScannerApplicationFactory();
using var scope = factory.Services.CreateScope();
var builder = scope.ServiceProvider.GetRequiredService<ProofSpineBuilder>();
var repository = scope.ServiceProvider.GetRequiredService<IProofSpineRepository>();
var spine = await builder
.ForArtifact("sha256:feedface")
.ForVulnerability("CVE-2025-0003")
.WithPolicyProfile("default")
.WithScanRun("scan-003")
.AddSbomSlice("sha256:sbom", new[] { "pkg:a" }, toolId: "sbom", toolVersion: "1.0.0")
.AddPolicyEval(
policyDigest: "sha256:policy",
factors: new Dictionary<string, string> { ["policy"] = "default" },
verdict: "affected",
verdictReason: "reachable",
toolId: "policy",
toolVersion: "1.0.0")
.BuildAsync();
var tamperedSegment = spine.Segments[0] with { ResultHash = spine.Segments[0].ResultHash + "00" };
var tampered = spine with { Segments = new[] { tamperedSegment, spine.Segments[1] } };
await repository.SaveAsync(tampered);
var client = factory.CreateClient();
var response = await client.GetAsync($"/api/v1/spines/{spine.SpineId}");
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadFromJsonAsync<JsonElement>();
var segments = body.GetProperty("segments");
Assert.Equal("invalid", segments[0].GetProperty("status").GetString());
}
}