Files
git.stella-ops.org/src/StellaOps.Concelier.Connector.CertCc.Tests/Internal/CertCcMapperTests.cs
2025-10-18 20:47:13 +03:00

119 lines
4.6 KiB
C#

using System;
using System.Globalization;
using MongoDB.Bson;
using StellaOps.Concelier.Models;
using StellaOps.Concelier.Connector.CertCc.Internal;
using StellaOps.Concelier.Storage.Mongo.Documents;
using StellaOps.Concelier.Storage.Mongo.Dtos;
using Xunit;
namespace StellaOps.Concelier.Connector.CertCc.Tests.Internal;
public sealed class CertCcMapperTests
{
private static readonly DateTimeOffset PublishedAt = DateTimeOffset.Parse("2025-10-03T11:35:31Z", CultureInfo.InvariantCulture);
[Fact]
public void Map_ProducesCanonicalAdvisoryWithVendorPrimitives()
{
const string vendorStatement =
"The issue is confirmed, and here is the patch list\n\n" +
"V3912/V3910/V2962/V1000B\t4.4.3.6/4.4.5.1\n" +
"V2927/V2865/V2866\t4.5.1\n" +
"V2765/V2766/V2763/V2135\t4.5.1";
var vendor = new CertCcVendorDto(
"DrayTek Corporation",
ContactDate: PublishedAt.AddDays(-10),
StatementDate: PublishedAt.AddDays(-5),
Updated: PublishedAt,
Statement: vendorStatement,
Addendum: null,
References: new[] { "https://www.draytek.com/support/resources?type=version" });
var vendorStatus = new CertCcVendorStatusDto(
Vendor: "DrayTek Corporation",
CveId: "CVE-2025-10547",
Status: "Affected",
Statement: null,
References: Array.Empty<string>(),
DateAdded: PublishedAt,
DateUpdated: PublishedAt);
var vulnerability = new CertCcVulnerabilityDto(
CveId: "CVE-2025-10547",
Description: null,
DateAdded: PublishedAt,
DateUpdated: PublishedAt);
var metadata = new CertCcNoteMetadata(
VuId: "VU#294418",
IdNumber: "294418",
Title: "Vigor routers running DrayOS RCE via EasyVPN",
Overview: "Overview",
Summary: "Summary",
Published: PublishedAt,
Updated: PublishedAt.AddMinutes(5),
Created: PublishedAt,
Revision: 2,
CveIds: new[] { "CVE-2025-10547" },
PublicUrls: new[]
{
"https://www.draytek.com/about/security-advisory/use-of-uninitialized-variable-vulnerabilities/",
"https://www.draytek.com/support/resources?type=version"
},
PrimaryUrl: "https://www.kb.cert.org/vuls/id/294418/");
var dto = new CertCcNoteDto(
metadata,
Vendors: new[] { vendor },
VendorStatuses: new[] { vendorStatus },
Vulnerabilities: new[] { vulnerability });
var document = new DocumentRecord(
Guid.NewGuid(),
"cert-cc",
"https://www.kb.cert.org/vuls/id/294418/",
PublishedAt,
Sha256: new string('0', 64),
Status: "pending-map",
ContentType: "application/json",
Headers: null,
Metadata: null,
Etag: null,
LastModified: PublishedAt,
GridFsId: null);
var dtoRecord = new DtoRecord(
Id: Guid.NewGuid(),
DocumentId: document.Id,
SourceName: "cert-cc",
SchemaVersion: "certcc.vince.note.v1",
Payload: new BsonDocument(),
ValidatedAt: PublishedAt.AddMinutes(1));
var advisory = CertCcMapper.Map(dto, document, dtoRecord, "cert-cc");
Assert.Equal("certcc/vu-294418", advisory.AdvisoryKey);
Assert.Contains("VU#294418", advisory.Aliases);
Assert.Contains("CVE-2025-10547", advisory.Aliases);
Assert.Equal("en", advisory.Language);
Assert.Equal(PublishedAt, advisory.Published);
Assert.Contains(advisory.References, reference => reference.Url.Contains("/vuls/id/294418", StringComparison.OrdinalIgnoreCase));
var affected = Assert.Single(advisory.AffectedPackages);
Assert.Equal("vendor", affected.Type);
Assert.Equal("DrayTek Corporation", affected.Identifier);
Assert.Contains(affected.Statuses, status => status.Status == AffectedPackageStatusCatalog.Affected);
var range = Assert.Single(affected.VersionRanges);
Assert.NotNull(range.Primitives);
Assert.NotNull(range.Primitives!.VendorExtensions);
Assert.Contains(range.Primitives.VendorExtensions!, kvp => kvp.Key == "certcc.vendor.patches");
Assert.NotEmpty(affected.NormalizedVersions);
Assert.Contains(affected.NormalizedVersions, rule => rule.Scheme == "certcc.vendor" && rule.Value == "4.5.1");
}
}