Add unit tests for SBOM ingestion and transformation
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:
master
2025-11-04 07:49:39 +02:00
parent f72c5c513a
commit 2eb6852d34
491 changed files with 39445 additions and 3917 deletions

View File

@@ -1,5 +1,6 @@
using System.Collections.Concurrent;
using System.Security.Cryptography;
using System.Text;
using Microsoft.IdentityModel.Tokens;
using StellaOps.Cryptography;
@@ -84,28 +85,58 @@ public sealed class KmsCryptoProvider : ICryptoProvider
foreach (var registration in _registrations.Values)
{
var material = _kmsClient.ExportAsync(registration.KeyId, registration.VersionId).GetAwaiter().GetResult();
var parameters = new ECParameters
{
Curve = ECCurve.NamedCurves.nistP256,
D = material.D,
Q = new ECPoint
{
X = material.Qx,
Y = material.Qy,
},
};
var metadata = new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase)
{
[KmsMetadataKeys.Version] = material.VersionId
};
list.Add(new CryptoSigningKey(
new CryptoKeyReference(material.KeyId, Name),
material.Algorithm,
in parameters,
material.CreatedAt,
metadata: metadata));
var reference = new CryptoKeyReference(material.KeyId, Name);
CryptoSigningKey signingKey;
if (material.D.Length == 0)
{
// Remote KMS keys may withhold private scalars; represent them as raw keys using public coordinates.
var privateHandle = Encoding.UTF8.GetBytes(string.IsNullOrWhiteSpace(material.VersionId) ? material.KeyId : material.VersionId);
if (privateHandle.Length == 0)
{
privateHandle = material.Qx.Length > 0
? material.Qx
: material.Qy.Length > 0
? material.Qy
: throw new InvalidOperationException($"KMS key '{material.KeyId}' does not expose public coordinates.");
}
var publicKey = CombineCoordinates(material.Qx, material.Qy);
signingKey = new CryptoSigningKey(
reference,
material.Algorithm,
privateHandle,
material.CreatedAt,
metadata: metadata,
publicKey: publicKey);
}
else
{
var parameters = new ECParameters
{
Curve = ECCurve.NamedCurves.nistP256,
D = material.D,
Q = new ECPoint
{
X = material.Qx,
Y = material.Qy,
},
};
signingKey = new CryptoSigningKey(
reference,
material.Algorithm,
in parameters,
material.CreatedAt,
metadata: metadata);
}
list.Add(signingKey);
}
return list;
@@ -115,6 +146,27 @@ public sealed class KmsCryptoProvider : ICryptoProvider
{
public const string Version = "kms.version";
}
private static byte[] CombineCoordinates(byte[] qx, byte[] qy)
{
if (qx.Length == 0 && qy.Length == 0)
{
return Array.Empty<byte>();
}
var buffer = new byte[qx.Length + qy.Length];
if (qx.Length > 0)
{
Buffer.BlockCopy(qx, 0, buffer, 0, qx.Length);
}
if (qy.Length > 0)
{
Buffer.BlockCopy(qy, 0, buffer, qx.Length, qy.Length);
}
return buffer;
}
}
internal sealed record KmsSigningRegistration(string KeyId, string VersionId, string Algorithm);