Refactor code structure for improved readability and maintainability; optimize performance in key functions.

This commit is contained in:
master
2025-12-22 19:06:31 +02:00
parent dfaa2079aa
commit 4602ccc3a3
1444 changed files with 109919 additions and 8058 deletions

View File

@@ -0,0 +1,110 @@
using Microsoft.Extensions.Logging;
using StellaOps.Cli.Services;
using StellaOps.Cli.Services.Models;
namespace StellaOps.Cli.Tests.Services;
public sealed class ImageAttestationVerifierTests
{
[Fact]
public async Task VerifyAsync_MissingAttestation_Strict_ReturnsFail()
{
using var loggerFactory = LoggerFactory.Create(builder => builder.SetMinimumLevel(LogLevel.None));
var registry = new StubRegistryClient("sha256:deadbeef", new OciReferrersResponse());
var policy = new TrustPolicyContext();
var verifier = new ImageAttestationVerifier(
registry,
new StubTrustPolicyLoader(policy),
new StubDsseVerifier(),
loggerFactory.CreateLogger<ImageAttestationVerifier>());
var result = await verifier.VerifyAsync(new ImageVerificationRequest
{
Reference = "registry.example.com/app@sha256:deadbeef",
RequiredTypes = new[] { "sbom" },
Strict = true
});
Assert.False(result.IsValid);
Assert.Single(result.Attestations);
Assert.Equal(AttestationStatus.Missing, result.Attestations[0].Status);
Assert.Contains("sbom", result.MissingTypes);
}
[Fact]
public async Task VerifyAsync_MissingAttestation_NotStrict_Passes()
{
using var loggerFactory = LoggerFactory.Create(builder => builder.SetMinimumLevel(LogLevel.None));
var registry = new StubRegistryClient("sha256:deadbeef", new OciReferrersResponse());
var policy = new TrustPolicyContext();
var verifier = new ImageAttestationVerifier(
registry,
new StubTrustPolicyLoader(policy),
new StubDsseVerifier(),
loggerFactory.CreateLogger<ImageAttestationVerifier>());
var result = await verifier.VerifyAsync(new ImageVerificationRequest
{
Reference = "registry.example.com/app@sha256:deadbeef",
RequiredTypes = new[] { "sbom" },
Strict = false
});
Assert.True(result.IsValid);
Assert.Single(result.Attestations);
Assert.Equal(AttestationStatus.Missing, result.Attestations[0].Status);
}
private sealed class StubRegistryClient : IOciRegistryClient
{
private readonly string _digest;
private readonly OciReferrersResponse _referrers;
public StubRegistryClient(string digest, OciReferrersResponse referrers)
{
_digest = digest;
_referrers = referrers;
}
public Task<string> ResolveDigestAsync(OciImageReference reference, CancellationToken cancellationToken = default)
=> Task.FromResult(_digest);
public Task<OciReferrersResponse> ListReferrersAsync(OciImageReference reference, string digest, CancellationToken cancellationToken = default)
=> Task.FromResult(_referrers);
public Task<OciManifest> GetManifestAsync(OciImageReference reference, string digest, CancellationToken cancellationToken = default)
=> Task.FromResult(new OciManifest());
public Task<byte[]> GetBlobAsync(OciImageReference reference, string digest, CancellationToken cancellationToken = default)
=> Task.FromResult(Array.Empty<byte>());
}
private sealed class StubTrustPolicyLoader : ITrustPolicyLoader
{
private readonly TrustPolicyContext _context;
public StubTrustPolicyLoader(TrustPolicyContext context)
{
_context = context;
}
public Task<TrustPolicyContext> LoadAsync(string path, CancellationToken cancellationToken = default)
=> Task.FromResult(_context);
}
private sealed class StubDsseVerifier : IDsseSignatureVerifier
{
public DsseSignatureVerificationResult Verify(
string payloadType,
string payloadBase64,
IReadOnlyList<DsseSignatureInput> signatures,
TrustPolicyContext policy)
{
return new DsseSignatureVerificationResult
{
IsValid = true,
KeyId = signatures.Count > 0 ? signatures[0].KeyId : null
};
}
}
}

View File

@@ -0,0 +1,72 @@
using System.Security.Cryptography;
using System.Text;
using Microsoft.Extensions.Logging;
using StellaOps.Cli.Services;
namespace StellaOps.Cli.Tests.Services;
public sealed class TrustPolicyLoaderTests
{
[Fact]
public async Task LoadAsync_ParsesYamlAndKeys()
{
var tempDir = Path.Combine(Path.GetTempPath(), $"stellaops-trust-{Guid.NewGuid():N}");
Directory.CreateDirectory(tempDir);
try
{
var keyPath = Path.Combine(tempDir, "test-key.pem");
File.WriteAllText(keyPath, GenerateRsaPublicKeyPem());
var policyPath = Path.Combine(tempDir, "trust-policy.yaml");
var yaml = $@"
version: ""1""
attestations:
sbom:
required: true
signers:
- identity: ""builder@example.com""
defaults:
requireRekor: true
maxAge: ""168h""
keys:
- id: ""builder-key""
path: ""{Path.GetFileName(keyPath)}""
algorithm: ""rsa-pss-sha256""
";
File.WriteAllText(policyPath, yaml.Trim(), Encoding.UTF8);
using var loggerFactory = LoggerFactory.Create(builder => builder.SetMinimumLevel(LogLevel.None));
var loader = new TrustPolicyLoader(loggerFactory.CreateLogger<TrustPolicyLoader>());
var context = await loader.LoadAsync(policyPath, CancellationToken.None);
Assert.True(context.RequireRekor);
Assert.Equal(TimeSpan.FromHours(168), context.MaxAge);
Assert.Single(context.Keys);
Assert.Equal("builder-key", context.Keys[0].KeyId);
Assert.NotEmpty(context.Keys[0].Fingerprint);
}
finally
{
Directory.Delete(tempDir, recursive: true);
}
}
private static string GenerateRsaPublicKeyPem()
{
using var rsa = RSA.Create(2048);
var publicKey = rsa.ExportSubjectPublicKeyInfo();
var base64 = Convert.ToBase64String(publicKey);
var sb = new StringBuilder();
sb.AppendLine("-----BEGIN PUBLIC KEY-----");
for (var i = 0; i < base64.Length; i += 64)
{
var chunk = base64.Substring(i, Math.Min(64, base64.Length - i));
sb.AppendLine(chunk);
}
sb.AppendLine("-----END PUBLIC KEY-----");
return sb.ToString();
}
}