147 lines
4.4 KiB
C#
147 lines
4.4 KiB
C#
using System.IO;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Logging;
|
|
using Spectre.Console;
|
|
using Spectre.Console.Testing;
|
|
using StellaOps.Cli.Commands;
|
|
using StellaOps.Cli.Configuration;
|
|
using StellaOps.Cli.Services;
|
|
using StellaOps.Cli.Services.Models;
|
|
|
|
namespace StellaOps.Cli.Tests.Commands;
|
|
|
|
public sealed class VerifyImageHandlerTests
|
|
{
|
|
[Fact]
|
|
public void ParseImageReference_WithDigest_Parses()
|
|
{
|
|
var (registry, repository, digest) = CommandHandlers.ParseImageReference("gcr.io/myproject/myapp@sha256:abc123");
|
|
|
|
Assert.Equal("gcr.io", registry);
|
|
Assert.Equal("myproject/myapp", repository);
|
|
Assert.Equal("sha256:abc123", digest);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task HandleVerifyImageAsync_ValidResult_ReturnsZero()
|
|
{
|
|
var result = new ImageVerificationResult
|
|
{
|
|
ImageReference = "registry.example.com/app@sha256:deadbeef",
|
|
ImageDigest = "sha256:deadbeef",
|
|
VerifiedAt = DateTimeOffset.UtcNow,
|
|
IsValid = true
|
|
};
|
|
|
|
var provider = BuildServices(new StubVerifier(result));
|
|
var originalExit = Environment.ExitCode;
|
|
|
|
try
|
|
{
|
|
await CaptureConsoleAsync(async _ =>
|
|
{
|
|
var exitCode = await CommandHandlers.HandleVerifyImageAsync(
|
|
provider,
|
|
"registry.example.com/app@sha256:deadbeef",
|
|
new[] { "sbom" },
|
|
trustPolicy: null,
|
|
output: "json",
|
|
strict: false,
|
|
verbose: false,
|
|
cancellationToken: CancellationToken.None);
|
|
|
|
Assert.Equal(0, exitCode);
|
|
});
|
|
|
|
Assert.Equal(0, Environment.ExitCode);
|
|
}
|
|
finally
|
|
{
|
|
Environment.ExitCode = originalExit;
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public async Task HandleVerifyImageAsync_InvalidResult_ReturnsOne()
|
|
{
|
|
var result = new ImageVerificationResult
|
|
{
|
|
ImageReference = "registry.example.com/app@sha256:deadbeef",
|
|
ImageDigest = "sha256:deadbeef",
|
|
VerifiedAt = DateTimeOffset.UtcNow,
|
|
IsValid = false
|
|
};
|
|
|
|
var provider = BuildServices(new StubVerifier(result));
|
|
var originalExit = Environment.ExitCode;
|
|
|
|
try
|
|
{
|
|
await CaptureConsoleAsync(async _ =>
|
|
{
|
|
var exitCode = await CommandHandlers.HandleVerifyImageAsync(
|
|
provider,
|
|
"registry.example.com/app@sha256:deadbeef",
|
|
new[] { "sbom" },
|
|
trustPolicy: null,
|
|
output: "json",
|
|
strict: true,
|
|
verbose: false,
|
|
cancellationToken: CancellationToken.None);
|
|
|
|
Assert.Equal(1, exitCode);
|
|
});
|
|
|
|
Assert.Equal(1, Environment.ExitCode);
|
|
}
|
|
finally
|
|
{
|
|
Environment.ExitCode = originalExit;
|
|
}
|
|
}
|
|
|
|
private static ServiceProvider BuildServices(IImageAttestationVerifier verifier)
|
|
{
|
|
var services = new ServiceCollection();
|
|
services.AddLogging(builder => builder.SetMinimumLevel(LogLevel.None));
|
|
services.AddSingleton(new StellaOpsCliOptions());
|
|
services.AddSingleton(verifier);
|
|
return services.BuildServiceProvider();
|
|
}
|
|
|
|
private static async Task CaptureConsoleAsync(Func<TestConsole, Task> action)
|
|
{
|
|
var testConsole = new TestConsole();
|
|
var originalConsole = AnsiConsole.Console;
|
|
var originalOut = Console.Out;
|
|
using var writer = new StringWriter();
|
|
|
|
try
|
|
{
|
|
AnsiConsole.Console = testConsole;
|
|
Console.SetOut(writer);
|
|
await action(testConsole).ConfigureAwait(false);
|
|
}
|
|
finally
|
|
{
|
|
AnsiConsole.Console = originalConsole;
|
|
Console.SetOut(originalOut);
|
|
}
|
|
}
|
|
|
|
private sealed class StubVerifier : IImageAttestationVerifier
|
|
{
|
|
private readonly ImageVerificationResult _result;
|
|
|
|
public StubVerifier(ImageVerificationResult result)
|
|
{
|
|
_result = result;
|
|
}
|
|
|
|
public Task<ImageVerificationResult> VerifyAsync(ImageVerificationRequest request, CancellationToken cancellationToken = default)
|
|
=> Task.FromResult(_result);
|
|
}
|
|
}
|