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"); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,47 @@ | ||||
| { | ||||
|   "document": { | ||||
|     "publisher": { | ||||
|       "name": "Red Hat Product Security", | ||||
|       "category": "vendor" | ||||
|     }, | ||||
|     "tracking": { | ||||
|       "id": "RHSA-2025:1001", | ||||
|       "status": "final", | ||||
|       "version": "3", | ||||
|       "initial_release_date": "2025-10-01T12:00:00Z", | ||||
|       "current_release_date": "2025-10-05T10:00:00Z" | ||||
|     } | ||||
|   }, | ||||
|   "product_tree": { | ||||
|     "full_product_names": [ | ||||
|       { | ||||
|         "product_id": "rh-enterprise-linux-9", | ||||
|         "name": "Red Hat Enterprise Linux 9", | ||||
|         "product_identification_helper": { | ||||
|           "cpe": "cpe:/o:redhat:enterprise_linux:9", | ||||
|           "purl": "pkg:rpm/redhat/enterprise-linux@9" | ||||
|         } | ||||
|       } | ||||
|     ], | ||||
|     "branches": [ | ||||
|       { | ||||
|         "name": "Red Hat Enterprise Linux", | ||||
|         "product": { | ||||
|           "product_id": "rh-enterprise-linux-9", | ||||
|           "name": "Red Hat Enterprise Linux 9" | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "vulnerabilities": [ | ||||
|     { | ||||
|       "cve": "CVE-2025-1234", | ||||
|       "title": "Kernel privilege escalation", | ||||
|       "product_status": { | ||||
|         "known_affected": [ | ||||
|           "rh-enterprise-linux-9" | ||||
|         ] | ||||
|       } | ||||
|     } | ||||
|   ] | ||||
| } | ||||
| @@ -0,0 +1,20 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
|   <PropertyGroup> | ||||
|     <TargetFramework>net10.0</TargetFramework> | ||||
|     <Nullable>enable</Nullable> | ||||
|     <ImplicitUsings>enable</ImplicitUsings> | ||||
|   </PropertyGroup> | ||||
|   <ItemGroup> | ||||
|     <PackageReference Include="FluentAssertions" Version="6.12.0" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <Using Include="Xunit" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ProjectReference Include="..\StellaOps.Excititor.Core\StellaOps.Excititor.Core.csproj" /> | ||||
|     <ProjectReference Include="..\StellaOps.Excititor.Formats.CSAF\StellaOps.Excititor.Formats.CSAF.csproj" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <None Include="Fixtures\**\*" CopyToOutputDirectory="Always" /> | ||||
|   </ItemGroup> | ||||
| </Project> | ||||
		Reference in New Issue
	
	Block a user