Files
git.stella-ops.org/src/Verifier/Program.cs
2026-02-01 21:37:40 +02:00

170 lines
5.1 KiB
C#

// -----------------------------------------------------------------------------
// Program.cs
// Sprint: SPRINT_20260121_036_BinaryIndex_golden_corpus_bundle_verification
// Task: GCB-003 - Implement standalone offline verifier
// Description: Entry point for standalone bundle verifier CLI
// -----------------------------------------------------------------------------
// Exit codes:
// 0: All verifications passed
// 1: One or more verifications failed
// 2: Invalid input or configuration error
using StellaOps.Verifier;
using System.CommandLine;
using System.CommandLine.Builder;
using System.CommandLine.Parsing;
var bundleOption = new Option<FileInfo>("--bundle", ["-b"])
{
Description = "Path to the evidence bundle to verify",
IsRequired = true
};
var trustedKeysOption = new Option<FileInfo?>("--trusted-keys", ["-k"])
{
Description = "Path to trusted public keys file"
};
var trustProfileOption = new Option<FileInfo?>("--trust-profile", ["-p"])
{
Description = "Path to trust profile JSON file"
};
var outputOption = new Option<FileInfo?>("--output", ["-o"])
{
Description = "Path to write verification report"
};
var formatOption = new Option<ReportFormat>("--format", ["-f"])
{
Description = "Report output format"
};
formatOption.SetDefaultValue(ReportFormat.Markdown);
var verifySignaturesOption = new Option<bool>("--verify-signatures")
{
Description = "Verify bundle manifest signatures"
};
verifySignaturesOption.SetDefaultValue(true);
var verifyTimestampsOption = new Option<bool>("--verify-timestamps")
{
Description = "Verify RFC 3161 timestamps"
};
verifyTimestampsOption.SetDefaultValue(true);
var verifyDigestsOption = new Option<bool>("--verify-digests")
{
Description = "Verify blob digests"
};
verifyDigestsOption.SetDefaultValue(true);
var verifyPairsOption = new Option<bool>("--verify-pairs")
{
Description = "Verify pair artifacts (SBOM, delta-sig)"
};
verifyPairsOption.SetDefaultValue(true);
var quietOption = new Option<bool>("--quiet", ["-q"])
{
Description = "Suppress output except for errors"
};
var verboseOption = new Option<bool>("--verbose", ["-v"])
{
Description = "Show detailed verification output"
};
var verifyCommand = new Command("verify", "Verify an evidence bundle")
{
bundleOption,
trustedKeysOption,
trustProfileOption,
outputOption,
formatOption,
verifySignaturesOption,
verifyTimestampsOption,
verifyDigestsOption,
verifyPairsOption,
quietOption,
verboseOption
};
verifyCommand.SetHandler(async (context) =>
{
var bundle = context.ParseResult.GetValueForOption(bundleOption)!;
var trustedKeys = context.ParseResult.GetValueForOption(trustedKeysOption);
var trustProfile = context.ParseResult.GetValueForOption(trustProfileOption);
var output = context.ParseResult.GetValueForOption(outputOption);
var format = context.ParseResult.GetValueForOption(formatOption);
var verifySignatures = context.ParseResult.GetValueForOption(verifySignaturesOption);
var verifyTimestamps = context.ParseResult.GetValueForOption(verifyTimestampsOption);
var verifyDigests = context.ParseResult.GetValueForOption(verifyDigestsOption);
var verifyPairs = context.ParseResult.GetValueForOption(verifyPairsOption);
var quiet = context.ParseResult.GetValueForOption(quietOption);
var verbose = context.ParseResult.GetValueForOption(verboseOption);
var options = new VerifierOptions
{
BundlePath = bundle.FullName,
TrustedKeysPath = trustedKeys?.FullName,
TrustProfilePath = trustProfile?.FullName,
OutputPath = output?.FullName,
OutputFormat = format,
VerifySignatures = verifySignatures,
VerifyTimestamps = verifyTimestamps,
VerifyDigests = verifyDigests,
VerifyPairs = verifyPairs,
Quiet = quiet,
Verbose = verbose
};
var verifier = new BundleVerifier();
var exitCode = await verifier.VerifyAsync(options, context.GetCancellationToken());
context.ExitCode = exitCode;
});
var infoCommand = new Command("info", "Display bundle information without verification")
{
bundleOption,
formatOption,
quietOption
};
infoCommand.SetHandler(async (context) =>
{
var bundle = context.ParseResult.GetValueForOption(bundleOption)!;
var format = context.ParseResult.GetValueForOption(formatOption);
var quiet = context.ParseResult.GetValueForOption(quietOption);
var verifier = new BundleVerifier();
var exitCode = await verifier.ShowInfoAsync(
bundle.FullName,
format,
quiet,
context.GetCancellationToken());
context.ExitCode = exitCode;
});
var rootCommand = new RootCommand("Stella Ops Bundle Verifier - Offline evidence bundle verification")
{
verifyCommand,
infoCommand
};
// Add version option
rootCommand.AddOption(new Option<bool>("--version", "Show version information"));
var parser = new CommandLineBuilder(rootCommand)
.UseDefaults()
.UseExceptionHandler((ex, context) =>
{
Console.Error.WriteLine($"Error: {ex.Message}");
context.ExitCode = 2;
})
.Build();
return await parser.InvokeAsync(args);