152 lines
5.0 KiB
C#
152 lines
5.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using StellaOps.Concelier.Models;
|
|
using StellaOps.Concelier.Storage.Mongo.Documents;
|
|
|
|
namespace StellaOps.Concelier.Connector.Cccs.Internal;
|
|
|
|
internal static class CccsMapper
|
|
{
|
|
public static Advisory Map(CccsAdvisoryDto dto, DocumentRecord document, DateTimeOffset recordedAt)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(dto);
|
|
ArgumentNullException.ThrowIfNull(document);
|
|
|
|
var aliases = BuildAliases(dto);
|
|
var references = BuildReferences(dto, recordedAt);
|
|
var packages = BuildPackages(dto, recordedAt);
|
|
var provenance = new[]
|
|
{
|
|
new AdvisoryProvenance(
|
|
CccsConnectorPlugin.SourceName,
|
|
"advisory",
|
|
dto.AlertType ?? dto.SerialNumber,
|
|
recordedAt,
|
|
new[] { ProvenanceFieldMasks.Advisory })
|
|
};
|
|
|
|
return new Advisory(
|
|
advisoryKey: dto.SerialNumber,
|
|
title: dto.Title,
|
|
summary: dto.Summary,
|
|
language: dto.Language,
|
|
published: dto.Published ?? dto.Modified,
|
|
modified: dto.Modified ?? dto.Published,
|
|
severity: null,
|
|
exploitKnown: false,
|
|
aliases: aliases,
|
|
references: references,
|
|
affectedPackages: packages,
|
|
cvssMetrics: Array.Empty<CvssMetric>(),
|
|
provenance: provenance);
|
|
}
|
|
|
|
private static IReadOnlyList<string> BuildAliases(CccsAdvisoryDto dto)
|
|
{
|
|
var aliases = new List<string>(capacity: 4)
|
|
{
|
|
dto.SerialNumber,
|
|
};
|
|
|
|
if (!string.IsNullOrWhiteSpace(dto.SourceId)
|
|
&& !string.Equals(dto.SourceId, dto.SerialNumber, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
aliases.Add(dto.SourceId);
|
|
}
|
|
|
|
foreach (var cve in dto.CveIds)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(cve))
|
|
{
|
|
aliases.Add(cve);
|
|
}
|
|
}
|
|
|
|
return aliases
|
|
.Where(static alias => !string.IsNullOrWhiteSpace(alias))
|
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
|
.OrderBy(static alias => alias, StringComparer.OrdinalIgnoreCase)
|
|
.ToArray();
|
|
}
|
|
|
|
private static IReadOnlyList<AdvisoryReference> BuildReferences(CccsAdvisoryDto dto, DateTimeOffset recordedAt)
|
|
{
|
|
var references = new List<AdvisoryReference>
|
|
{
|
|
new(dto.CanonicalUrl, "details", "cccs", null, new AdvisoryProvenance(
|
|
CccsConnectorPlugin.SourceName,
|
|
"reference",
|
|
dto.CanonicalUrl,
|
|
recordedAt,
|
|
new[] { ProvenanceFieldMasks.References }))
|
|
};
|
|
|
|
foreach (var reference in dto.References)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(reference.Url))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
references.Add(new AdvisoryReference(
|
|
reference.Url,
|
|
"reference",
|
|
"cccs",
|
|
reference.Label,
|
|
new AdvisoryProvenance(
|
|
CccsConnectorPlugin.SourceName,
|
|
"reference",
|
|
reference.Url,
|
|
recordedAt,
|
|
new[] { ProvenanceFieldMasks.References })));
|
|
}
|
|
|
|
return references
|
|
.DistinctBy(static reference => reference.Url, StringComparer.Ordinal)
|
|
.OrderBy(static reference => reference.Url, StringComparer.Ordinal)
|
|
.ToArray();
|
|
}
|
|
|
|
private static IReadOnlyList<AffectedPackage> BuildPackages(CccsAdvisoryDto dto, DateTimeOffset recordedAt)
|
|
{
|
|
if (dto.Products.Count == 0)
|
|
{
|
|
return Array.Empty<AffectedPackage>();
|
|
}
|
|
|
|
var packages = new List<AffectedPackage>(dto.Products.Count);
|
|
foreach (var product in dto.Products)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(product))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var identifier = product.Trim();
|
|
var provenance = new AdvisoryProvenance(
|
|
CccsConnectorPlugin.SourceName,
|
|
"package",
|
|
identifier,
|
|
recordedAt,
|
|
new[] { ProvenanceFieldMasks.AffectedPackages });
|
|
|
|
packages.Add(new AffectedPackage(
|
|
AffectedPackageTypes.Vendor,
|
|
identifier,
|
|
platform: null,
|
|
versionRanges: Array.Empty<AffectedVersionRange>(),
|
|
statuses: Array.Empty<AffectedPackageStatus>(),
|
|
provenance: new[] { provenance },
|
|
normalizedVersions: Array.Empty<NormalizedVersionRule>()));
|
|
}
|
|
|
|
return packages.Count == 0
|
|
? Array.Empty<AffectedPackage>()
|
|
: packages
|
|
.DistinctBy(static package => package.Identifier, StringComparer.OrdinalIgnoreCase)
|
|
.OrderBy(static package => package.Identifier, StringComparer.OrdinalIgnoreCase)
|
|
.ToArray();
|
|
}
|
|
}
|