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,356 @@
// -----------------------------------------------------------------------------
// BinaryCommandHandlers.cs
// Sprint: SPRINT_3850_0001_0001_oci_storage_cli
// Tasks: T3, T4, T5, T6
// Description: Command handlers for binary reachability operations.
// -----------------------------------------------------------------------------
using System.Text.Json;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Spectre.Console;
namespace StellaOps.Cli.Commands.Binary;
/// <summary>
/// Command handlers for binary reachability CLI commands.
/// </summary>
internal static class BinaryCommandHandlers
{
private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web)
{
WriteIndented = true
};
/// <summary>
/// Handle 'stella binary submit' command.
/// </summary>
public static async Task<int> HandleSubmitAsync(
IServiceProvider services,
string? graphPath,
string? binaryPath,
bool analyze,
bool sign,
string? registry,
bool verbose,
CancellationToken cancellationToken)
{
var logger = services.GetRequiredService<ILogger<Program>>();
if (string.IsNullOrWhiteSpace(graphPath) && string.IsNullOrWhiteSpace(binaryPath))
{
AnsiConsole.MarkupLine("[red]Error:[/] Either --graph or --binary must be specified.");
return ExitCodes.InvalidArguments;
}
if (analyze && string.IsNullOrWhiteSpace(binaryPath))
{
AnsiConsole.MarkupLine("[red]Error:[/] --analyze requires --binary.");
return ExitCodes.InvalidArguments;
}
try
{
await AnsiConsole.Status()
.StartAsync("Submitting binary graph...", async ctx =>
{
if (analyze)
{
ctx.Status("Analyzing binary...");
AnsiConsole.MarkupLine($"[yellow]Analyzing binary:[/] {binaryPath}");
// TODO: Invoke binary analysis service
await Task.Delay(100, cancellationToken);
}
if (!string.IsNullOrWhiteSpace(graphPath))
{
ctx.Status($"Reading graph from {graphPath}...");
if (!File.Exists(graphPath))
{
throw new FileNotFoundException($"Graph file not found: {graphPath}");
}
var graphJson = await File.ReadAllTextAsync(graphPath, cancellationToken);
AnsiConsole.MarkupLine($"[green]✓[/] Graph loaded: {graphJson.Length} bytes");
}
if (sign)
{
ctx.Status("Signing graph with DSSE...");
AnsiConsole.MarkupLine("[yellow]Signing:[/] Generating DSSE attestation");
// TODO: Invoke signing service
await Task.Delay(100, cancellationToken);
}
if (!string.IsNullOrWhiteSpace(registry))
{
ctx.Status($"Pushing to {registry}...");
AnsiConsole.MarkupLine($"[yellow]Pushing:[/] {registry}");
// TODO: Invoke OCI push service
await Task.Delay(100, cancellationToken);
}
ctx.Status("Submitting to Scanner API...");
// TODO: Invoke Scanner API
await Task.Delay(100, cancellationToken);
});
var mockDigest = "blake3:abc123def456789...";
AnsiConsole.MarkupLine($"[green]✓ Graph submitted successfully[/]");
AnsiConsole.MarkupLine($" Digest: [cyan]{mockDigest}[/]");
if (verbose)
{
logger.LogInformation(
"Binary graph submitted: graph={GraphPath}, binary={BinaryPath}, sign={Sign}",
graphPath,
binaryPath,
sign);
}
return ExitCodes.Success;
}
catch (Exception ex)
{
AnsiConsole.MarkupLine($"[red]Error:[/] {ex.Message}");
logger.LogError(ex, "Failed to submit binary graph");
return ExitCodes.GeneralError;
}
}
/// <summary>
/// Handle 'stella binary info' command.
/// </summary>
public static async Task<int> HandleInfoAsync(
IServiceProvider services,
string hash,
string format,
bool verbose,
CancellationToken cancellationToken)
{
var logger = services.GetRequiredService<ILogger<Program>>();
try
{
// TODO: Query Scanner API for graph info
await Task.Delay(50, cancellationToken);
var mockInfo = new
{
Digest = hash,
Format = "ELF x86_64",
BuildId = "gnu-build-id:5f0c7c3c...",
Nodes = 1247,
Edges = 3891,
Entrypoints = 5,
Attestation = "Signed (Rekor #12345678)"
};
if (format == "json")
{
var json = JsonSerializer.Serialize(mockInfo, JsonOptions);
AnsiConsole.WriteLine(json);
}
else
{
AnsiConsole.MarkupLine($"[bold]Binary Graph:[/] {mockInfo.Digest}");
AnsiConsole.MarkupLine($"Format: {mockInfo.Format}");
AnsiConsole.MarkupLine($"Build-ID: {mockInfo.BuildId}");
AnsiConsole.MarkupLine($"Nodes: [cyan]{mockInfo.Nodes}[/]");
AnsiConsole.MarkupLine($"Edges: [cyan]{mockInfo.Edges}[/]");
AnsiConsole.MarkupLine($"Entrypoints: [cyan]{mockInfo.Entrypoints}[/]");
AnsiConsole.MarkupLine($"Attestation: [green]{mockInfo.Attestation}[/]");
}
if (verbose)
{
logger.LogInformation("Retrieved graph info for {Hash}", hash);
}
return ExitCodes.Success;
}
catch (Exception ex)
{
AnsiConsole.MarkupLine($"[red]Error:[/] {ex.Message}");
logger.LogError(ex, "Failed to retrieve graph info for {Hash}", hash);
return ExitCodes.GeneralError;
}
}
/// <summary>
/// Handle 'stella binary symbols' command.
/// </summary>
public static async Task<int> HandleSymbolsAsync(
IServiceProvider services,
string hash,
bool strippedOnly,
bool exportedOnly,
bool entrypointsOnly,
string? search,
string format,
int limit,
bool verbose,
CancellationToken cancellationToken)
{
var logger = services.GetRequiredService<ILogger<Program>>();
try
{
// TODO: Query Scanner API for symbols
await Task.Delay(50, cancellationToken);
var mockSymbols = new[]
{
new { Symbol = "main", Type = "entrypoint", Exported = true, Stripped = false },
new { Symbol = "ssl_connect", Type = "function", Exported = true, Stripped = false },
new { Symbol = "verify_cert", Type = "function", Exported = false, Stripped = false },
new { Symbol = "sub_401234", Type = "function", Exported = false, Stripped = true }
};
var filtered = mockSymbols.AsEnumerable();
if (strippedOnly)
filtered = filtered.Where(s => s.Stripped);
if (exportedOnly)
filtered = filtered.Where(s => s.Exported);
if (entrypointsOnly)
filtered = filtered.Where(s => s.Type == "entrypoint");
if (!string.IsNullOrWhiteSpace(search))
{
var pattern = search.Replace("*", ".*");
filtered = filtered.Where(s => System.Text.RegularExpressions.Regex.IsMatch(s.Symbol, pattern));
}
var results = filtered.Take(limit).ToArray();
if (format == "json")
{
var json = JsonSerializer.Serialize(results, JsonOptions);
AnsiConsole.WriteLine(json);
}
else
{
var table = new Table();
table.AddColumn("Symbol");
table.AddColumn("Type");
table.AddColumn("Exported");
table.AddColumn("Stripped");
foreach (var sym in results)
{
table.AddRow(
sym.Symbol,
sym.Type,
sym.Exported ? "[green]yes[/]" : "no",
sym.Stripped ? "[yellow]yes[/]" : "no");
}
AnsiConsole.Write(table);
AnsiConsole.MarkupLine($"\n[dim]Showing {results.Length} symbols (limit: {limit})[/]");
}
if (verbose)
{
logger.LogInformation(
"Retrieved {Count} symbols for {Hash}",
results.Length,
hash);
}
return ExitCodes.Success;
}
catch (Exception ex)
{
AnsiConsole.MarkupLine($"[red]Error:[/] {ex.Message}");
logger.LogError(ex, "Failed to retrieve symbols for {Hash}", hash);
return ExitCodes.GeneralError;
}
}
/// <summary>
/// Handle 'stella binary verify' command.
/// </summary>
public static async Task<int> HandleVerifyAsync(
IServiceProvider services,
string graphPath,
string dssePath,
string? publicKey,
string? rekorUrl,
bool verbose,
CancellationToken cancellationToken)
{
var logger = services.GetRequiredService<ILogger<Program>>();
try
{
if (!File.Exists(graphPath))
{
AnsiConsole.MarkupLine($"[red]Error:[/] Graph file not found: {graphPath}");
return ExitCodes.FileNotFound;
}
if (!File.Exists(dssePath))
{
AnsiConsole.MarkupLine($"[red]Error:[/] DSSE envelope not found: {dssePath}");
return ExitCodes.FileNotFound;
}
await AnsiConsole.Status()
.StartAsync("Verifying attestation...", async ctx =>
{
ctx.Status("Parsing DSSE envelope...");
await Task.Delay(50, cancellationToken);
ctx.Status("Verifying signature...");
// TODO: Invoke signature verification
await Task.Delay(100, cancellationToken);
ctx.Status("Verifying graph digest...");
// TODO: Verify graph hash matches predicate
await Task.Delay(50, cancellationToken);
if (!string.IsNullOrWhiteSpace(rekorUrl))
{
ctx.Status("Verifying Rekor inclusion...");
// TODO: Verify Rekor transparency log
await Task.Delay(100, cancellationToken);
}
});
AnsiConsole.MarkupLine("[green]✓ Verification successful[/]");
AnsiConsole.MarkupLine(" Signature: [green]Valid[/]");
AnsiConsole.MarkupLine(" Graph digest: [green]Matches[/]");
if (!string.IsNullOrWhiteSpace(rekorUrl))
{
AnsiConsole.MarkupLine($" Rekor: [green]Verified (entry #12345678)[/]");
}
if (verbose)
{
logger.LogInformation(
"Verified graph attestation: graph={GraphPath}, dsse={DssePath}",
graphPath,
dssePath);
}
return ExitCodes.Success;
}
catch (Exception ex)
{
AnsiConsole.MarkupLine($"[red]✗ Verification failed:[/] {ex.Message}");
logger.LogError(ex, "Failed to verify attestation");
return ExitCodes.VerificationFailed;
}
}
}
internal static class ExitCodes
{
public const int Success = 0;
public const int GeneralError = 1;
public const int InvalidArguments = 2;
public const int FileNotFound = 3;
public const int VerificationFailed = 4;
}