Initial commit (history squashed)
This commit is contained in:
		
							
								
								
									
										231
									
								
								tools/FixtureUpdater/Program.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								tools/FixtureUpdater/Program.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,231 @@
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Text.Json;
 | 
			
		||||
using System.Text.Json.Serialization;
 | 
			
		||||
using MongoDB.Bson;
 | 
			
		||||
using StellaOps.Feedser.Models;
 | 
			
		||||
using StellaOps.Feedser.Source.Ghsa;
 | 
			
		||||
using StellaOps.Feedser.Source.Common;
 | 
			
		||||
using StellaOps.Feedser.Source.Ghsa.Internal;
 | 
			
		||||
using StellaOps.Feedser.Source.Osv.Internal;
 | 
			
		||||
using StellaOps.Feedser.Source.Osv;
 | 
			
		||||
using StellaOps.Feedser.Storage.Mongo.Documents;
 | 
			
		||||
using StellaOps.Feedser.Storage.Mongo.Dtos;
 | 
			
		||||
 | 
			
		||||
var serializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web)
 | 
			
		||||
{
 | 
			
		||||
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var projectRoot = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", "..", "..", "..", ".."));
 | 
			
		||||
 | 
			
		||||
var fixturesPath = Path.Combine(projectRoot, "src", "StellaOps.Feedser.Source.Osv.Tests", "Fixtures");
 | 
			
		||||
 | 
			
		||||
RewriteOsvFixtures(fixturesPath);
 | 
			
		||||
RewriteSnapshotFixtures(fixturesPath);
 | 
			
		||||
RewriteGhsaFixtures(fixturesPath);
 | 
			
		||||
return;
 | 
			
		||||
 | 
			
		||||
void RewriteOsvFixtures(string fixturesPath)
 | 
			
		||||
{
 | 
			
		||||
    var rawPath = Path.Combine(fixturesPath, "osv-ghsa.raw-osv.json");
 | 
			
		||||
    if (!File.Exists(rawPath))
 | 
			
		||||
    {
 | 
			
		||||
        Console.WriteLine($"[FixtureUpdater] OSV raw fixture missing: {rawPath}");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    using var document = JsonDocument.Parse(File.ReadAllText(rawPath));
 | 
			
		||||
    var advisories = new List<Advisory>();
 | 
			
		||||
    foreach (var element in document.RootElement.EnumerateArray())
 | 
			
		||||
    {
 | 
			
		||||
        var dto = JsonSerializer.Deserialize<OsvVulnerabilityDto>(element.GetRawText(), serializerOptions);
 | 
			
		||||
        if (dto is null)
 | 
			
		||||
        {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var ecosystem = dto.Affected?.FirstOrDefault()?.Package?.Ecosystem ?? "unknown";
 | 
			
		||||
        var uri = new Uri($"https://osv.dev/vulnerability/{dto.Id}");
 | 
			
		||||
        var documentRecord = new DocumentRecord(
 | 
			
		||||
            Guid.NewGuid(),
 | 
			
		||||
            OsvConnectorPlugin.SourceName,
 | 
			
		||||
            uri.ToString(),
 | 
			
		||||
            DateTimeOffset.UtcNow,
 | 
			
		||||
            "fixture-sha",
 | 
			
		||||
            DocumentStatuses.PendingMap,
 | 
			
		||||
            "application/json",
 | 
			
		||||
            null,
 | 
			
		||||
            new Dictionary<string, string>(StringComparer.Ordinal)
 | 
			
		||||
            {
 | 
			
		||||
                ["osv.ecosystem"] = ecosystem,
 | 
			
		||||
            },
 | 
			
		||||
            null,
 | 
			
		||||
            DateTimeOffset.UtcNow,
 | 
			
		||||
            null,
 | 
			
		||||
            null);
 | 
			
		||||
 | 
			
		||||
        var payload = BsonDocument.Parse(element.GetRawText());
 | 
			
		||||
        var dtoRecord = new DtoRecord(
 | 
			
		||||
            Guid.NewGuid(),
 | 
			
		||||
            documentRecord.Id,
 | 
			
		||||
            OsvConnectorPlugin.SourceName,
 | 
			
		||||
            "osv.v1",
 | 
			
		||||
            payload,
 | 
			
		||||
            DateTimeOffset.UtcNow);
 | 
			
		||||
 | 
			
		||||
        var advisory = OsvMapper.Map(dto, documentRecord, dtoRecord, ecosystem);
 | 
			
		||||
        advisories.Add(advisory);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    advisories.Sort((left, right) => string.Compare(left.AdvisoryKey, right.AdvisoryKey, StringComparison.Ordinal));
 | 
			
		||||
    var snapshot = SnapshotSerializer.ToSnapshot(advisories);
 | 
			
		||||
    File.WriteAllText(Path.Combine(fixturesPath, "osv-ghsa.osv.json"), snapshot);
 | 
			
		||||
    Console.WriteLine($"[FixtureUpdater] Updated {Path.Combine(fixturesPath, "osv-ghsa.osv.json")}");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RewriteSnapshotFixtures(string fixturesPath)
 | 
			
		||||
{
 | 
			
		||||
    var baselinePublished = new DateTimeOffset(2025, 1, 5, 12, 0, 0, TimeSpan.Zero);
 | 
			
		||||
    var baselineModified = new DateTimeOffset(2025, 1, 8, 6, 30, 0, TimeSpan.Zero);
 | 
			
		||||
    var baselineFetched = new DateTimeOffset(2025, 1, 8, 7, 0, 0, TimeSpan.Zero);
 | 
			
		||||
 | 
			
		||||
    var cases = new (string Ecosystem, string Purl, string PackageName, string SnapshotFile)[]
 | 
			
		||||
    {
 | 
			
		||||
        ("npm", "pkg:npm/%40scope%2Fleft-pad", "@scope/left-pad", "osv-npm.snapshot.json"),
 | 
			
		||||
        ("PyPI", "pkg:pypi/requests", "requests", "osv-pypi.snapshot.json"),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    foreach (var (ecosystem, purl, packageName, snapshotFile) in cases)
 | 
			
		||||
    {
 | 
			
		||||
        var dto = new OsvVulnerabilityDto
 | 
			
		||||
        {
 | 
			
		||||
            Id = $"OSV-2025-{ecosystem}-0001",
 | 
			
		||||
            Summary = $"{ecosystem} package vulnerability",
 | 
			
		||||
            Details = $"Detailed description for {ecosystem} package {packageName}.",
 | 
			
		||||
            Published = baselinePublished,
 | 
			
		||||
            Modified = baselineModified,
 | 
			
		||||
            Aliases = new[] { $"CVE-2025-11{ecosystem.Length}", $"GHSA-{ecosystem.Length}abc-{ecosystem.Length}def-{ecosystem.Length}ghi" },
 | 
			
		||||
            Related = new[] { $"OSV-RELATED-{ecosystem}-42" },
 | 
			
		||||
            References = new[]
 | 
			
		||||
            {
 | 
			
		||||
                new OsvReferenceDto { Url = $"https://example.com/{ecosystem}/advisory", Type = "ADVISORY" },
 | 
			
		||||
                new OsvReferenceDto { Url = $"https://example.com/{ecosystem}/fix", Type = "FIX" },
 | 
			
		||||
            },
 | 
			
		||||
            Severity = new[]
 | 
			
		||||
            {
 | 
			
		||||
                new OsvSeverityDto { Type = "CVSS_V3", Score = "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H" },
 | 
			
		||||
            },
 | 
			
		||||
            Affected = new[]
 | 
			
		||||
            {
 | 
			
		||||
                new OsvAffectedPackageDto
 | 
			
		||||
                {
 | 
			
		||||
                    Package = new OsvPackageDto
 | 
			
		||||
                    {
 | 
			
		||||
                        Ecosystem = ecosystem,
 | 
			
		||||
                        Name = packageName,
 | 
			
		||||
                        Purl = purl,
 | 
			
		||||
                    },
 | 
			
		||||
                    Ranges = new[]
 | 
			
		||||
                    {
 | 
			
		||||
                        new OsvRangeDto
 | 
			
		||||
                        {
 | 
			
		||||
                            Type = "SEMVER",
 | 
			
		||||
                            Events = new[]
 | 
			
		||||
                            {
 | 
			
		||||
                                new OsvEventDto { Introduced = "0" },
 | 
			
		||||
                                new OsvEventDto { Fixed = "2.0.0" },
 | 
			
		||||
                            },
 | 
			
		||||
                        },
 | 
			
		||||
                    },
 | 
			
		||||
                    Versions = new[] { "1.0.0", "1.5.0" },
 | 
			
		||||
                    EcosystemSpecific = JsonDocument.Parse("{\"severity\":\"high\"}").RootElement.Clone(),
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
            DatabaseSpecific = JsonDocument.Parse("{\"source\":\"osv.dev\"}").RootElement.Clone(),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        var document = new DocumentRecord(
 | 
			
		||||
            Guid.NewGuid(),
 | 
			
		||||
            OsvConnectorPlugin.SourceName,
 | 
			
		||||
            $"https://osv.dev/vulnerability/{dto.Id}",
 | 
			
		||||
            baselineFetched,
 | 
			
		||||
            "fixture-sha",
 | 
			
		||||
            DocumentStatuses.PendingParse,
 | 
			
		||||
            "application/json",
 | 
			
		||||
            null,
 | 
			
		||||
            new Dictionary<string, string>(StringComparer.Ordinal) { ["osv.ecosystem"] = ecosystem },
 | 
			
		||||
            null,
 | 
			
		||||
            baselineModified,
 | 
			
		||||
            null);
 | 
			
		||||
 | 
			
		||||
        var payload = BsonDocument.Parse(JsonSerializer.Serialize(dto, serializerOptions));
 | 
			
		||||
        var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, OsvConnectorPlugin.SourceName, "osv.v1", payload, baselineModified);
 | 
			
		||||
 | 
			
		||||
        var advisory = OsvMapper.Map(dto, document, dtoRecord, ecosystem);
 | 
			
		||||
        var snapshot = SnapshotSerializer.ToSnapshot(advisory);
 | 
			
		||||
        File.WriteAllText(Path.Combine(fixturesPath, snapshotFile), snapshot);
 | 
			
		||||
        Console.WriteLine($"[FixtureUpdater] Updated {Path.Combine(fixturesPath, snapshotFile)}");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RewriteGhsaFixtures(string fixturesPath)
 | 
			
		||||
{
 | 
			
		||||
    var rawPath = Path.Combine(fixturesPath, "osv-ghsa.raw-ghsa.json");
 | 
			
		||||
    if (!File.Exists(rawPath))
 | 
			
		||||
    {
 | 
			
		||||
        Console.WriteLine($"[FixtureUpdater] GHSA raw fixture missing: {rawPath}");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    JsonDocument document;
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        document = JsonDocument.Parse(File.ReadAllText(rawPath));
 | 
			
		||||
    }
 | 
			
		||||
    catch (JsonException ex)
 | 
			
		||||
    {
 | 
			
		||||
        Console.WriteLine($"[FixtureUpdater] Failed to parse GHSA raw fixture '{rawPath}': {ex.Message}");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    using (document)
 | 
			
		||||
    {
 | 
			
		||||
    var advisories = new List<Advisory>();
 | 
			
		||||
    foreach (var element in document.RootElement.EnumerateArray())
 | 
			
		||||
    {
 | 
			
		||||
        GhsaRecordDto dto;
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            dto = GhsaRecordParser.Parse(Encoding.UTF8.GetBytes(element.GetRawText()));
 | 
			
		||||
        }
 | 
			
		||||
        catch (JsonException)
 | 
			
		||||
        {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var uri = new Uri($"https://github.com/advisories/{dto.GhsaId}");
 | 
			
		||||
        var documentRecord = new DocumentRecord(
 | 
			
		||||
            Guid.NewGuid(),
 | 
			
		||||
            GhsaConnectorPlugin.SourceName,
 | 
			
		||||
            uri.ToString(),
 | 
			
		||||
            DateTimeOffset.UtcNow,
 | 
			
		||||
            "fixture-sha",
 | 
			
		||||
            DocumentStatuses.PendingMap,
 | 
			
		||||
            "application/json",
 | 
			
		||||
            null,
 | 
			
		||||
            new Dictionary<string, string>(StringComparer.Ordinal),
 | 
			
		||||
            null,
 | 
			
		||||
            DateTimeOffset.UtcNow,
 | 
			
		||||
            null,
 | 
			
		||||
            null);
 | 
			
		||||
 | 
			
		||||
        var advisory = GhsaMapper.Map(dto, documentRecord, DateTimeOffset.UtcNow);
 | 
			
		||||
        advisories.Add(advisory);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        advisories.Sort((left, right) => string.Compare(left.AdvisoryKey, right.AdvisoryKey, StringComparison.Ordinal));
 | 
			
		||||
        var snapshot = SnapshotSerializer.ToSnapshot(advisories);
 | 
			
		||||
        File.WriteAllText(Path.Combine(fixturesPath, "osv-ghsa.ghsa.json"), snapshot);
 | 
			
		||||
        Console.WriteLine($"[FixtureUpdater] Updated {Path.Combine(fixturesPath, "osv-ghsa.ghsa.json")}");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user