Rename Vexer to Excititor
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using StellaOps.Excititor.Core;
|
||||
using StellaOps.Excititor.Formats.CSAF;
|
||||
|
||||
namespace StellaOps.Excititor.Formats.CSAF.Tests;
|
||||
|
||||
public sealed class CsafNormalizerTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task NormalizeAsync_ProducesClaimsPerProductStatus()
|
||||
{
|
||||
var json = """
|
||||
{
|
||||
"document": {
|
||||
"tracking": {
|
||||
"id": "RHSA-2025:0001",
|
||||
"version": "3",
|
||||
"revision": "3",
|
||||
"status": "final",
|
||||
"initial_release_date": "2025-10-01T00:00:00Z",
|
||||
"current_release_date": "2025-10-10T00:00:00Z"
|
||||
},
|
||||
"publisher": {
|
||||
"name": "Red Hat Product Security",
|
||||
"category": "vendor"
|
||||
}
|
||||
},
|
||||
"product_tree": {
|
||||
"full_product_names": [
|
||||
{
|
||||
"product_id": "CSAFPID-0001",
|
||||
"name": "Red Hat Enterprise Linux 9",
|
||||
"product_identification_helper": {
|
||||
"cpe": "cpe:/o:redhat:enterprise_linux:9",
|
||||
"purl": "pkg:rpm/redhat/enterprise-linux@9"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"vulnerabilities": [
|
||||
{
|
||||
"cve": "CVE-2025-0001",
|
||||
"title": "Kernel vulnerability",
|
||||
"product_status": {
|
||||
"known_affected": [ "CSAFPID-0001" ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "VEX-0002",
|
||||
"title": "Library issue",
|
||||
"product_status": {
|
||||
"known_not_affected": [ "CSAFPID-0001" ]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
""";
|
||||
|
||||
var rawDocument = new VexRawDocument(
|
||||
ProviderId: "excititor:redhat",
|
||||
VexDocumentFormat.Csaf,
|
||||
new Uri("https://example.com/csaf/rhsa-2025-0001.json"),
|
||||
new DateTimeOffset(2025, 10, 11, 0, 0, 0, TimeSpan.Zero),
|
||||
"sha256:dummydigest",
|
||||
Encoding.UTF8.GetBytes(json),
|
||||
ImmutableDictionary<string, string>.Empty);
|
||||
|
||||
var provider = new VexProvider("excititor:redhat", "Red Hat CSAF", VexProviderKind.Distro);
|
||||
var normalizer = new CsafNormalizer(NullLogger<CsafNormalizer>.Instance);
|
||||
|
||||
var batch = await normalizer.NormalizeAsync(rawDocument, provider, CancellationToken.None);
|
||||
|
||||
batch.Claims.Should().HaveCount(2);
|
||||
|
||||
var affectedClaim = batch.Claims.First(c => c.VulnerabilityId == "CVE-2025-0001");
|
||||
affectedClaim.Status.Should().Be(VexClaimStatus.Affected);
|
||||
affectedClaim.Product.Key.Should().Be("CSAFPID-0001");
|
||||
affectedClaim.Product.Purl.Should().Be("pkg:rpm/redhat/enterprise-linux@9");
|
||||
affectedClaim.Product.Cpe.Should().Be("cpe:/o:redhat:enterprise_linux:9");
|
||||
affectedClaim.Document.Revision.Should().Be("3");
|
||||
affectedClaim.FirstSeen.Should().Be(new DateTimeOffset(2025, 10, 1, 0, 0, 0, TimeSpan.Zero));
|
||||
affectedClaim.LastSeen.Should().Be(new DateTimeOffset(2025, 10, 10, 0, 0, 0, TimeSpan.Zero));
|
||||
affectedClaim.AdditionalMetadata.Should().ContainKey("csaf.tracking.id");
|
||||
affectedClaim.AdditionalMetadata["csaf.publisher.name"].Should().Be("Red Hat Product Security");
|
||||
|
||||
var notAffectedClaim = batch.Claims.First(c => c.VulnerabilityId == "VEX-0002");
|
||||
notAffectedClaim.Status.Should().Be(VexClaimStatus.NotAffected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NormalizeAsync_PreservesRedHatSpecificMetadata()
|
||||
{
|
||||
var path = Path.Combine(AppContext.BaseDirectory, "Fixtures", "rhsa-sample.json");
|
||||
var json = await File.ReadAllTextAsync(path);
|
||||
|
||||
var rawDocument = new VexRawDocument(
|
||||
ProviderId: "excititor:redhat",
|
||||
VexDocumentFormat.Csaf,
|
||||
new Uri("https://security.example.com/rhsa-2025-1001.json"),
|
||||
new DateTimeOffset(2025, 10, 6, 0, 0, 0, TimeSpan.Zero),
|
||||
"sha256:rhdadigest",
|
||||
Encoding.UTF8.GetBytes(json),
|
||||
ImmutableDictionary<string, string>.Empty);
|
||||
|
||||
var provider = new VexProvider("excititor:redhat", "Red Hat CSAF", VexProviderKind.Distro);
|
||||
var normalizer = new CsafNormalizer(NullLogger<CsafNormalizer>.Instance);
|
||||
|
||||
var batch = await normalizer.NormalizeAsync(rawDocument, provider, CancellationToken.None);
|
||||
batch.Claims.Should().ContainSingle();
|
||||
|
||||
var claim = batch.Claims[0];
|
||||
claim.VulnerabilityId.Should().Be("CVE-2025-1234");
|
||||
claim.Status.Should().Be(VexClaimStatus.Affected);
|
||||
claim.Product.Key.Should().Be("rh-enterprise-linux-9");
|
||||
claim.Product.Name.Should().Be("Red Hat Enterprise Linux 9");
|
||||
claim.Product.Purl.Should().Be("pkg:rpm/redhat/enterprise-linux@9");
|
||||
claim.Product.Cpe.Should().Be("cpe:/o:redhat:enterprise_linux:9");
|
||||
claim.FirstSeen.Should().Be(new DateTimeOffset(2025, 10, 1, 12, 0, 0, TimeSpan.Zero));
|
||||
claim.LastSeen.Should().Be(new DateTimeOffset(2025, 10, 5, 10, 0, 0, TimeSpan.Zero));
|
||||
|
||||
claim.AdditionalMetadata.Should().ContainKey("csaf.tracking.id");
|
||||
claim.AdditionalMetadata["csaf.tracking.id"].Should().Be("RHSA-2025:1001");
|
||||
claim.AdditionalMetadata["csaf.tracking.status"].Should().Be("final");
|
||||
claim.AdditionalMetadata["csaf.publisher.name"].Should().Be("Red Hat Product Security");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user