Files
git.stella-ops.org/src/Concelier/__Tests/StellaOps.Concelier.SbomIntegration.Tests/VexIntegrationTests.cs
2026-01-22 19:08:46 +02:00

107 lines
2.9 KiB
C#

using System.Text;
using Microsoft.Extensions.Logging.Abstractions;
using StellaOps.Concelier.SbomIntegration.Models;
using StellaOps.Concelier.SbomIntegration.Parsing;
using StellaOps.Concelier.SbomIntegration.Vex;
using StellaOps.TestKit;
using Xunit;
namespace StellaOps.Concelier.SbomIntegration.Tests;
public sealed class VexIntegrationTests
{
[Trait("Category", TestCategories.Integration)]
[Fact]
public async Task ConsumeFromSbomAsync_ParsesEmbeddedCycloneDxVex()
{
var json = """
{
"bomFormat": "CycloneDX",
"specVersion": "1.7",
"serialNumber": "urn:uuid:00000000-0000-0000-0000-000000000001",
"version": 1,
"metadata": {
"timestamp": "2026-01-20T00:00:00Z",
"component": {
"bom-ref": "comp-1",
"type": "library",
"name": "example",
"version": "1.0.0",
"purl": "pkg:npm/example@1.0.0"
},
"tools": [
{
"vendor": "test",
"name": "test",
"version": "1.0"
}
]
},
"components": [
{
"bom-ref": "comp-1",
"type": "library",
"name": "example",
"version": "1.0.0",
"purl": "pkg:npm/example@1.0.0"
}
],
"vulnerabilities": [
{
"id": "CVE-2026-9999",
"analysis": {
"state": "not_affected",
"justification": "component_not_present",
"response": ["will_not_fix"],
"detail": "component absent",
"lastUpdated": "2026-01-20T00:00:00Z"
},
"affects": [
{ "ref": "comp-1" }
],
"ratings": [
{
"method": "CVSSv3",
"score": 7.5,
"severity": "high"
}
]
}
]
}
""";
await using var stream = new MemoryStream(Encoding.UTF8.GetBytes(json));
var parser = new ParsedSbomParser(NullLogger<ParsedSbomParser>.Instance);
var sbom = await parser.ParseAsync(stream, SbomFormat.CycloneDX, CancellationToken.None);
var consumer = CreateConsumer();
var result = await consumer.ConsumeFromSbomAsync(sbom, VexConsumptionPolicyDefaults.Default, CancellationToken.None);
Assert.Single(result.Statements);
Assert.Equal("CVE-2026-9999", result.Statements[0].VulnerabilityId);
Assert.Equal(VexStatus.NotAffected, result.Statements[0].Status);
Assert.Contains("pkg:npm/example@1.0.0", result.Statements[0].AffectedComponents);
}
private static VexConsumer CreateConsumer()
{
var evaluator = new VexTrustEvaluator(new StubTimeProvider());
var resolver = new VexConflictResolver();
var merger = new VexMerger(resolver);
var extractors = new IVexStatementExtractor[]
{
new CycloneDxVexExtractor(),
new SpdxVexExtractor()
};
return new VexConsumer(evaluator, merger, extractors);
}
private sealed class StubTimeProvider : TimeProvider
{
public override DateTimeOffset GetUtcNow()
=> DateTimeOffset.Parse("2026-01-20T01:00:00Z");
}
}