Add unit tests for SBOM ingestion and transformation
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- Implement `SbomIngestServiceCollectionExtensionsTests` to verify the SBOM ingestion pipeline exports snapshots correctly. - Create `SbomIngestTransformerTests` to ensure the transformation produces expected nodes and edges, including deduplication of license nodes and normalization of timestamps. - Add `SbomSnapshotExporterTests` to test the export functionality for manifest, adjacency, nodes, and edges. - Introduce `VexOverlayTransformerTests` to validate the transformation of VEX nodes and edges. - Set up project file for the test project with necessary dependencies and configurations. - Include JSON fixture files for testing purposes.
This commit is contained in:
231
src/Graph/StellaOps.Graph.Indexer/Ingestion/Sbom/SbomSnapshot.cs
Normal file
231
src/Graph/StellaOps.Graph.Indexer/Ingestion/Sbom/SbomSnapshot.cs
Normal file
@@ -0,0 +1,231 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StellaOps.Graph.Indexer.Ingestion.Sbom;
|
||||
|
||||
public sealed class SbomSnapshot
|
||||
{
|
||||
[JsonPropertyName("tenant")]
|
||||
public string Tenant { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("source")]
|
||||
public string Source { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("artifactDigest")]
|
||||
public string ArtifactDigest { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("sbomDigest")]
|
||||
public string SbomDigest { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("collectedAt")]
|
||||
public DateTimeOffset CollectedAt { get; init; } = DateTimeOffset.UnixEpoch;
|
||||
|
||||
[JsonPropertyName("eventOffset")]
|
||||
public long EventOffset { get; init; }
|
||||
|
||||
[JsonPropertyName("artifact")]
|
||||
public SbomArtifactMetadata Artifact { get; init; } = new();
|
||||
|
||||
[JsonPropertyName("build")]
|
||||
public SbomBuildMetadata Build { get; init; } = new();
|
||||
|
||||
[JsonPropertyName("components")]
|
||||
public IReadOnlyList<SbomComponent> Components { get; init; } = Array.Empty<SbomComponent>();
|
||||
|
||||
[JsonPropertyName("baseArtifacts")]
|
||||
public IReadOnlyList<SbomBaseArtifact> BaseArtifacts { get; init; } = Array.Empty<SbomBaseArtifact>();
|
||||
}
|
||||
|
||||
public sealed class SbomArtifactMetadata
|
||||
{
|
||||
[JsonPropertyName("displayName")]
|
||||
public string DisplayName { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("environment")]
|
||||
public string Environment { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("labels")]
|
||||
public IReadOnlyList<string> Labels { get; init; } = Array.Empty<string>();
|
||||
|
||||
[JsonPropertyName("originRegistry")]
|
||||
public string OriginRegistry { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("supplyChainStage")]
|
||||
public string SupplyChainStage { get; init; } = string.Empty;
|
||||
}
|
||||
|
||||
public sealed class SbomBuildMetadata
|
||||
{
|
||||
[JsonPropertyName("builderId")]
|
||||
public string BuilderId { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("buildType")]
|
||||
public string BuildType { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("attestationDigest")]
|
||||
public string AttestationDigest { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("source")]
|
||||
public string Source { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("collectedAt")]
|
||||
public DateTimeOffset CollectedAt { get; init; } = DateTimeOffset.UnixEpoch;
|
||||
|
||||
[JsonPropertyName("eventOffset")]
|
||||
public long EventOffset { get; init; }
|
||||
}
|
||||
|
||||
public sealed class SbomComponent
|
||||
{
|
||||
[JsonPropertyName("purl")]
|
||||
public string Purl { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("version")]
|
||||
public string Version { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("ecosystem")]
|
||||
public string Ecosystem { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("scope")]
|
||||
public string Scope { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("license")]
|
||||
public SbomLicense License { get; init; } = new();
|
||||
|
||||
[JsonPropertyName("usage")]
|
||||
public string Usage { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("detectedBy")]
|
||||
public string DetectedBy { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("layerDigest")]
|
||||
public string LayerDigest { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("evidenceDigest")]
|
||||
public string EvidenceDigest { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("collectedAt")]
|
||||
public DateTimeOffset CollectedAt { get; init; } = DateTimeOffset.UnixEpoch;
|
||||
|
||||
[JsonPropertyName("eventOffset")]
|
||||
public long EventOffset { get; init; }
|
||||
|
||||
[JsonPropertyName("source")]
|
||||
public string Source { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("files")]
|
||||
public IReadOnlyList<SbomComponentFile> Files { get; init; } = Array.Empty<SbomComponentFile>();
|
||||
|
||||
[JsonPropertyName("dependencies")]
|
||||
public IReadOnlyList<SbomDependency> Dependencies { get; init; } = Array.Empty<SbomDependency>();
|
||||
|
||||
[JsonPropertyName("sourceType")]
|
||||
public string SourceType { get; init; } = "inventory";
|
||||
}
|
||||
|
||||
public sealed class SbomLicense
|
||||
{
|
||||
[JsonPropertyName("spdx")]
|
||||
public string Spdx { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("classification")]
|
||||
public string Classification { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("noticeUri")]
|
||||
public string? NoticeUri { get; init; }
|
||||
|
||||
[JsonPropertyName("sourceDigest")]
|
||||
public string SourceDigest { get; init; } = string.Empty;
|
||||
}
|
||||
|
||||
public sealed class SbomComponentFile
|
||||
{
|
||||
[JsonPropertyName("path")]
|
||||
public string Path { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("contentSha256")]
|
||||
public string ContentSha256 { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("languageHint")]
|
||||
public string LanguageHint { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("sizeBytes")]
|
||||
public long SizeBytes { get; init; }
|
||||
|
||||
[JsonPropertyName("scope")]
|
||||
public string Scope { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("detectedBy")]
|
||||
public string DetectedBy { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("evidenceDigest")]
|
||||
public string EvidenceDigest { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("collectedAt")]
|
||||
public DateTimeOffset CollectedAt { get; init; } = DateTimeOffset.UnixEpoch;
|
||||
|
||||
[JsonPropertyName("eventOffset")]
|
||||
public long EventOffset { get; init; }
|
||||
|
||||
[JsonPropertyName("source")]
|
||||
public string Source { get; init; } = string.Empty;
|
||||
}
|
||||
|
||||
public sealed class SbomDependency
|
||||
{
|
||||
[JsonPropertyName("purl")]
|
||||
public string Purl { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("version")]
|
||||
public string Version { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("relationship")]
|
||||
public string Relationship { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("evidenceDigest")]
|
||||
public string EvidenceDigest { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("collectedAt")]
|
||||
public DateTimeOffset CollectedAt { get; init; } = DateTimeOffset.UnixEpoch;
|
||||
|
||||
[JsonPropertyName("eventOffset")]
|
||||
public long EventOffset { get; init; }
|
||||
|
||||
[JsonPropertyName("source")]
|
||||
public string Source { get; init; } = string.Empty;
|
||||
}
|
||||
|
||||
public sealed class SbomBaseArtifact
|
||||
{
|
||||
[JsonPropertyName("artifactDigest")]
|
||||
public string ArtifactDigest { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("sbomDigest")]
|
||||
public string SbomDigest { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("displayName")]
|
||||
public string DisplayName { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("environment")]
|
||||
public string Environment { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("labels")]
|
||||
public IReadOnlyList<string> Labels { get; init; } = Array.Empty<string>();
|
||||
|
||||
[JsonPropertyName("originRegistry")]
|
||||
public string OriginRegistry { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("supplyChainStage")]
|
||||
public string SupplyChainStage { get; init; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("collectedAt")]
|
||||
public DateTimeOffset CollectedAt { get; init; } = DateTimeOffset.UnixEpoch;
|
||||
|
||||
[JsonPropertyName("eventOffset")]
|
||||
public long EventOffset { get; init; }
|
||||
|
||||
[JsonPropertyName("source")]
|
||||
public string Source { get; init; } = string.Empty;
|
||||
}
|
||||
Reference in New Issue
Block a user