save progress

This commit is contained in:
StellaOps Bot
2026-01-03 11:02:24 +02:00
parent ca578801fd
commit 83c37243e0
446 changed files with 22798 additions and 4031 deletions

View File

@@ -5447,6 +5447,11 @@ internal static class CommandFactory
var ociVerify = BuildOciVerifyCommand(services, verboseOption, cancellationToken);
attest.Add(ociVerify); // stella attest oci-verify --image ...
// Sprint: SPRINT_20260102_002_BE_intoto_link_generation (IT-023)
// in-toto link creation
var link = BuildInTotoLinkCommand(services, verboseOption, cancellationToken);
attest.Add(link); // stella attest link --step ...
return attest;
}
@@ -5687,6 +5692,134 @@ internal static class CommandFactory
return ociVerify;
}
/// <summary>
/// Builds 'attest link' subcommand for creating in-toto link attestations.
/// Sprint: SPRINT_20260102_002_BE_intoto_link_generation (IT-023)
/// </summary>
private static Command BuildInTotoLinkCommand(
IServiceProvider services,
Option<bool> verboseOption,
CancellationToken cancellationToken)
{
// Step name (required)
var stepNameOption = new Option<string>("--step", new[] { "-s" })
{
Description = "Name of the supply chain step (e.g., 'scan', 'build', 'sign')",
Required = true
};
// Materials (inputs)
var materialsOption = new Option<string[]?>("--material", new[] { "-m" })
{
Description = "Material (input) in format 'uri' or 'uri=sha256:digest'. Can be specified multiple times.",
AllowMultipleArgumentsPerToken = true
};
// Products (outputs)
var productsOption = new Option<string[]?>("--product", new[] { "-p" })
{
Description = "Product (output) in format 'uri' or 'uri=sha256:digest'. Can be specified multiple times.",
AllowMultipleArgumentsPerToken = true
};
// Command
var commandOption = new Option<string[]?>("--command", new[] { "-c" })
{
Description = "Command that was executed. Can be specified multiple times for each arg.",
AllowMultipleArgumentsPerToken = true
};
// Return value
var returnValueOption = new Option<int?>("--return-value", new[] { "-r" })
{
Description = "Return value of the command (exit code). Default: 0"
};
// Environment variables to capture
var envOption = new Option<string[]?>("--env", new[] { "-e" })
{
Description = "Environment variable to include in format 'NAME=value'. Can be specified multiple times.",
AllowMultipleArgumentsPerToken = true
};
// Signing options
var keyOption = new Option<string?>("--key", new[] { "-k" })
{
Description = "Key identifier or path for signing"
};
var keylessOption = new Option<bool>("--keyless")
{
Description = "Use keyless (OIDC) signing via Sigstore Fulcio"
};
var rekorOption = new Option<bool>("--rekor")
{
Description = "Submit link to Rekor transparency log"
};
// Output options
var outputOption = new Option<string?>("--output", new[] { "-o" })
{
Description = "Output path for the signed in-toto link envelope"
};
var formatOption = new Option<string?>("--format", new[] { "-f" })
{
Description = "Output format: dsse (default), json (link only), sigstore-bundle"
};
var link = new Command("link", "Create a signed in-toto link attestation for a supply chain step")
{
stepNameOption,
materialsOption,
productsOption,
commandOption,
returnValueOption,
envOption,
keyOption,
keylessOption,
rekorOption,
outputOption,
formatOption,
verboseOption
};
link.SetAction(async (parseResult, ct) =>
{
var stepName = parseResult.GetValue(stepNameOption) ?? string.Empty;
var materials = parseResult.GetValue(materialsOption) ?? Array.Empty<string>();
var products = parseResult.GetValue(productsOption) ?? Array.Empty<string>();
var command = parseResult.GetValue(commandOption) ?? Array.Empty<string>();
var returnValue = parseResult.GetValue(returnValueOption) ?? 0;
var env = parseResult.GetValue(envOption) ?? Array.Empty<string>();
var keyId = parseResult.GetValue(keyOption);
var keyless = parseResult.GetValue(keylessOption);
var useRekor = parseResult.GetValue(rekorOption);
var output = parseResult.GetValue(outputOption);
var format = parseResult.GetValue(formatOption) ?? "dsse";
var verbose = parseResult.GetValue(verboseOption);
return await CommandHandlers.HandleAttestLinkAsync(
services,
stepName,
materials,
products,
command,
returnValue,
env,
keyId,
keyless,
useRekor,
output,
format,
verbose,
cancellationToken);
});
return link;
}
private static Command BuildRiskProfileCommand(Option<bool> verboseOption, CancellationToken cancellationToken)
{
_ = cancellationToken;