feat(kms): Implement file-backed key management commands and handlers
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

- Added `kms export` and `kms import` commands to manage file-backed signing keys.
- Implemented `HandleKmsExportAsync` and `HandleKmsImportAsync` methods in CommandHandlers for exporting and importing key material.
- Introduced KmsPassphrasePrompt for secure passphrase input.
- Updated CLI architecture documentation to include new KMS commands.
- Enhanced unit tests for KMS export and import functionalities.
- Updated project references to include StellaOps.Cryptography.Kms library.
- Marked KMS interface implementation and CLI support tasks as DONE in the task board.
This commit is contained in:
master
2025-10-30 14:41:48 +02:00
parent a3822c88cd
commit 240e8ff25d
13 changed files with 697 additions and 107 deletions

View File

@@ -38,6 +38,7 @@ internal static class CommandFactory
root.Add(BuildPolicyCommand(services, options, verboseOption, cancellationToken));
root.Add(BuildFindingsCommand(services, verboseOption, cancellationToken));
root.Add(BuildConfigCommand(options));
root.Add(BuildKmsCommand(services, verboseOption, cancellationToken));
root.Add(BuildVulnCommand(services, verboseOption, cancellationToken));
var pluginLogger = loggerFactory.CreateLogger<CliCommandModuleLoader>();
@@ -92,9 +93,9 @@ internal static class CommandFactory
return scanner;
}
private static Command BuildScanCommand(IServiceProvider services, StellaOpsCliOptions options, Option<bool> verboseOption, CancellationToken cancellationToken)
{
var scan = new Command("scan", "Execute scanners and manage scan outputs.");
private static Command BuildScanCommand(IServiceProvider services, StellaOpsCliOptions options, Option<bool> verboseOption, CancellationToken cancellationToken)
{
var scan = new Command("scan", "Execute scanners and manage scan outputs.");
var run = new Command("run", "Execute a scanner bundle with the configured runner.");
var runnerOption = new Option<string>("--runner")
@@ -148,10 +149,126 @@ internal static class CommandFactory
});
scan.Add(run);
scan.Add(upload);
return scan;
}
scan.Add(upload);
return scan;
}
private static Command BuildKmsCommand(IServiceProvider services, Option<bool> verboseOption, CancellationToken cancellationToken)
{
var kms = new Command("kms", "Manage file-backed signing keys.");
var export = new Command("export", "Export key material to a portable bundle.");
var exportRootOption = new Option<string>("--root")
{
Description = "Root directory containing file-based KMS material."
};
var exportKeyOption = new Option<string>("--key-id")
{
Description = "Logical KMS key identifier to export.",
Required = true
};
var exportVersionOption = new Option<string?>("--version")
{
Description = "Key version identifier to export (defaults to active version)."
};
var exportOutputOption = new Option<string>("--output")
{
Description = "Destination file path for exported key material.",
Required = true
};
var exportForceOption = new Option<bool>("--force")
{
Description = "Overwrite the destination file if it already exists."
};
var exportPassphraseOption = new Option<string?>("--passphrase")
{
Description = "File KMS passphrase (falls back to STELLAOPS_KMS_PASSPHRASE or interactive prompt)."
};
export.Add(exportRootOption);
export.Add(exportKeyOption);
export.Add(exportVersionOption);
export.Add(exportOutputOption);
export.Add(exportForceOption);
export.Add(exportPassphraseOption);
export.SetAction((parseResult, _) =>
{
var root = parseResult.GetValue(exportRootOption);
var keyId = parseResult.GetValue(exportKeyOption) ?? string.Empty;
var versionId = parseResult.GetValue(exportVersionOption);
var output = parseResult.GetValue(exportOutputOption) ?? string.Empty;
var force = parseResult.GetValue(exportForceOption);
var passphrase = parseResult.GetValue(exportPassphraseOption);
var verbose = parseResult.GetValue(verboseOption);
return CommandHandlers.HandleKmsExportAsync(
services,
root,
keyId,
versionId,
output,
force,
passphrase,
verbose,
cancellationToken);
});
var import = new Command("import", "Import key material from a bundle.");
var importRootOption = new Option<string>("--root")
{
Description = "Root directory containing file-based KMS material."
};
var importKeyOption = new Option<string>("--key-id")
{
Description = "Logical KMS key identifier to import into.",
Required = true
};
var importInputOption = new Option<string>("--input")
{
Description = "Path to exported key material JSON.",
Required = true
};
var importVersionOption = new Option<string?>("--version")
{
Description = "Override the imported version identifier."
};
var importPassphraseOption = new Option<string?>("--passphrase")
{
Description = "File KMS passphrase (falls back to STELLAOPS_KMS_PASSPHRASE or interactive prompt)."
};
import.Add(importRootOption);
import.Add(importKeyOption);
import.Add(importInputOption);
import.Add(importVersionOption);
import.Add(importPassphraseOption);
import.SetAction((parseResult, _) =>
{
var root = parseResult.GetValue(importRootOption);
var keyId = parseResult.GetValue(importKeyOption) ?? string.Empty;
var input = parseResult.GetValue(importInputOption) ?? string.Empty;
var versionOverride = parseResult.GetValue(importVersionOption);
var passphrase = parseResult.GetValue(importPassphraseOption);
var verbose = parseResult.GetValue(verboseOption);
return CommandHandlers.HandleKmsImportAsync(
services,
root,
keyId,
input,
versionOverride,
passphrase,
verbose,
cancellationToken);
});
kms.Add(export);
kms.Add(import);
return kms;
}
private static Command BuildDatabaseCommand(IServiceProvider services, Option<bool> verboseOption, CancellationToken cancellationToken)
{
var db = new Command("db", "Trigger Concelier database operations via backend jobs.");