audit work, fixed StellaOps.sln warnings/errors, fixed tests, sprints work, new advisories

This commit is contained in:
master
2026-01-07 18:49:59 +02:00
parent 04ec098046
commit 608a7f85c0
866 changed files with 56323 additions and 6231 deletions

View File

@@ -40,7 +40,29 @@ public sealed record SpdxCompositionOptions
public SpdxLicenseListVersion LicenseListVersion { get; init; } = SpdxLicenseListVersion.V3_21;
public ImmutableArray<string> ProfileConformance { get; init; } = ImmutableArray.Create("core", "software");
/// <summary>
/// Gets or sets the SPDX 3.0.1 profile type. Defaults to Software.
/// </summary>
public Spdx3ProfileType ProfileType { get; init; } = Spdx3ProfileType.Software;
/// <summary>
/// Gets or sets an explicit profile conformance override.
/// If not set (default or empty), the conformance is derived from ProfileType.
/// </summary>
public ImmutableArray<string> ProfileConformance { get; init; } = ImmutableArray<string>.Empty;
/// <summary>
/// Gets the effective profile conformance based on ProfileType if ProfileConformance is not explicitly set.
/// </summary>
public ImmutableArray<string> GetEffectiveProfileConformance()
{
if (!ProfileConformance.IsDefaultOrEmpty && ProfileConformance.Length > 0)
{
return ProfileConformance;
}
return ProfileType.GetProfileConformance().ToImmutableArray();
}
}
public sealed class SpdxComposer : ISpdxComposer
@@ -139,12 +161,12 @@ public sealed class SpdxComposer : ISpdxComposer
var packages = new List<SpdxPackage>();
var packageIdMap = new Dictionary<string, string>(StringComparer.Ordinal);
var rootPackage = BuildRootPackage(request.Image, idBuilder);
var rootPackage = BuildRootPackage(request.Image, idBuilder, options);
packages.Add(rootPackage);
foreach (var component in graph.Components)
{
var package = BuildComponentPackage(component, idBuilder, licenseList);
var package = BuildComponentPackage(component, idBuilder, licenseList, options);
packages.Add(package);
packageIdMap[component.Identity.Key] = package.SpdxId;
}
@@ -175,7 +197,7 @@ public sealed class SpdxComposer : ISpdxComposer
Sbom = sbom,
Elements = packages.Cast<SpdxElement>().ToImmutableArray(),
Relationships = relationships,
ProfileConformance = options.ProfileConformance
ProfileConformance = options.GetEffectiveProfileConformance()
};
}
@@ -261,17 +283,23 @@ public sealed class SpdxComposer : ISpdxComposer
.ToImmutableArray();
}
private static SpdxPackage BuildRootPackage(ImageArtifactDescriptor image, SpdxIdBuilder idBuilder)
private static SpdxPackage BuildRootPackage(
ImageArtifactDescriptor image,
SpdxIdBuilder idBuilder,
SpdxCompositionOptions options)
{
var digest = image.ImageDigest;
var digestParts = digest.Split(':', 2, StringSplitOptions.TrimEntries);
var digestValue = digestParts.Length == 2 ? digestParts[1] : digest;
var checksums = ImmutableArray.Create(new SpdxChecksum
{
Algorithm = digestParts.Length == 2 ? digestParts[0].ToUpperInvariant() : "SHA256",
Value = digestValue
});
// Lite profile omits checksums
var checksums = options.ProfileType.IncludeChecksums()
? ImmutableArray.Create(new SpdxChecksum
{
Algorithm = digestParts.Length == 2 ? digestParts[0].ToUpperInvariant() : "SHA256",
Value = digestValue
})
: ImmutableArray<SpdxChecksum>.Empty;
return new SpdxPackage
{
@@ -288,13 +316,17 @@ public sealed class SpdxComposer : ISpdxComposer
private static SpdxPackage BuildComponentPackage(
AggregatedComponent component,
SpdxIdBuilder idBuilder,
SpdxLicenseList licenseList)
SpdxLicenseList licenseList,
SpdxCompositionOptions options)
{
var packageUrl = !string.IsNullOrWhiteSpace(component.Identity.Purl)
? component.Identity.Purl
: (component.Identity.Key.StartsWith("pkg:", StringComparison.Ordinal) ? component.Identity.Key : null);
var declared = BuildLicenseExpression(component.Metadata?.Licenses, licenseList);
// Lite profile omits detailed licensing
var declared = options.ProfileType.IncludeDetailedLicensing()
? BuildLicenseExpression(component.Metadata?.Licenses, licenseList)
: null;
return new SpdxPackage
{

View File

@@ -0,0 +1,78 @@
// <copyright file="Spdx3ProfileType.cs" company="StellaOps">
// Copyright (c) StellaOps. Licensed under the AGPL-3.0-or-later.
// </copyright>
namespace StellaOps.Scanner.Emit.Spdx;
/// <summary>
/// SPDX 3.0.1 profile types for SBOM generation.
/// </summary>
public enum Spdx3ProfileType
{
/// <summary>
/// Full Software profile with all available fields.
/// Includes detailed licensing, checksums, external refs, etc.
/// </summary>
Software,
/// <summary>
/// Lite profile with minimal required fields.
/// Optimized for CI/CD and performance-sensitive use cases.
/// Includes: spdxId, name, packageVersion, packageUrl or downloadLocation.
/// </summary>
Lite,
/// <summary>
/// Build profile with provenance and build environment data.
/// Suitable for attestation integration.
/// </summary>
Build,
/// <summary>
/// Security profile with vulnerability and VEX data.
/// Suitable for security analysis and VexLens integration.
/// </summary>
Security
}
/// <summary>
/// Extension methods for <see cref="Spdx3ProfileType"/>.
/// </summary>
public static class Spdx3ProfileTypeExtensions
{
/// <summary>
/// Gets the profile conformance URIs for this profile type.
/// </summary>
public static string[] GetProfileConformance(this Spdx3ProfileType profileType) => profileType switch
{
Spdx3ProfileType.Software => ["core", "software"],
Spdx3ProfileType.Lite => ["core", "software", "lite"],
Spdx3ProfileType.Build => ["core", "software", "build"],
Spdx3ProfileType.Security => ["core", "software", "security"],
_ => ["core", "software"]
};
/// <summary>
/// Returns true if this profile should include detailed licensing.
/// </summary>
public static bool IncludeDetailedLicensing(this Spdx3ProfileType profileType) =>
profileType is Spdx3ProfileType.Software;
/// <summary>
/// Returns true if this profile should include checksums.
/// </summary>
public static bool IncludeChecksums(this Spdx3ProfileType profileType) =>
profileType is Spdx3ProfileType.Software or Spdx3ProfileType.Build or Spdx3ProfileType.Security;
/// <summary>
/// Returns true if this profile should include external references.
/// </summary>
public static bool IncludeExternalRefs(this Spdx3ProfileType profileType) =>
profileType is not Spdx3ProfileType.Lite;
/// <summary>
/// Returns true if this profile should include annotations and comments.
/// </summary>
public static bool IncludeAnnotations(this Spdx3ProfileType profileType) =>
profileType is Spdx3ProfileType.Software;
}