- Fix namespace conflicts (Subgraph → PoESubgraph) - Add hash sanitization for Windows filesystem (colon → underscore) - Update all test mocks to use It.IsAny<>() - Add direct orchestrator unit tests - All 8 PoE tests now passing (100% success rate) - Complete SPRINT_3500_0001_0001 documentation Fixes compilation errors and Windows filesystem compatibility issues. Tests: 8/8 passing Files: 8 modified, 1 new test, 1 completion report 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
790 lines
23 KiB
Markdown
790 lines
23 KiB
Markdown
# stella CLI - Plugin Architecture
|
|
|
|
**Sprint:** SPRINT_4100_0006_0006 - CLI Documentation Overhaul
|
|
|
|
## Overview
|
|
|
|
The `stella` CLI is built with a plugin architecture that enables conditional compilation of regional cryptographic providers (GOST, eIDAS, SM) while maintaining a unified command interface. This design supports compliance with export control regulations and cryptographic standards across different jurisdictions.
|
|
|
|
**Key Design Goals:**
|
|
1. **Conditional Compilation**: Include only authorized crypto providers per distribution
|
|
2. **Plugin Isolation**: Crypto providers as self-contained, testable modules
|
|
3. **Dependency Injection**: Runtime service resolution for providers
|
|
4. **Configuration-driven**: Profile-based provider selection
|
|
5. **Extensibility**: Easy addition of new providers without core CLI changes
|
|
|
|
---
|
|
|
|
## Architecture Layers
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ stella CLI │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ Command Groups │
|
|
│ ├─ scan, aoc, symbols, crypto, admin, ... │
|
|
│ └─ System.CommandLine 2.0 routing │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ Plugin System │
|
|
│ ├─ ICryptoProvider interface │
|
|
│ ├─ Plugin discovery (build-time + runtime) │
|
|
│ └─ DependencyInjection (Microsoft.Extensions.DI) │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ Crypto Plugins (Conditional) │
|
|
│ ├─ Default (.NET Crypto, BouncyCastle) [ALL] │
|
|
│ ├─ GOST (CryptoPro, OpenSSL-GOST, PKCS#11) [RUSSIA] │
|
|
│ ├─ eIDAS (TSP Client, Local Signer) [EU] │
|
|
│ └─ SM (GmSSL, SM Remote CSP) [CHINA] │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ Backend Integration │
|
|
│ ├─ Authority (OAuth2 + DPoP) │
|
|
│ ├─ Scanner, Concelier, Policy, ... │
|
|
│ └─ HTTP clients with retry policies │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Build-time Plugin Selection
|
|
|
|
### Conditional Compilation Workflow
|
|
|
|
```mermaid
|
|
graph TD
|
|
A[MSBuild Start] --> B{Check Build Flags}
|
|
B -->|StellaOpsEnableGOST=true| C[Include GOST Plugin]
|
|
B -->|StellaOpsEnableEIDAS=true| D[Include eIDAS Plugin]
|
|
B -->|StellaOpsEnableSM=true| E[Include SM Plugin]
|
|
B -->|No flags| F[Include Default Only]
|
|
|
|
C --> G[Set STELLAOPS_ENABLE_GOST]
|
|
D --> H[Set STELLAOPS_ENABLE_EIDAS]
|
|
E --> I[Set STELLAOPS_ENABLE_SM]
|
|
|
|
G --> J[Compile with Plugin]
|
|
H --> J
|
|
I --> J
|
|
F --> J
|
|
|
|
J --> K[Link Plugin Assembly]
|
|
K --> L[Final Binary]
|
|
```
|
|
|
|
### Project Structure
|
|
|
|
```
|
|
src/Cli/
|
|
├── StellaOps.Cli/
|
|
│ ├── Program.cs # Entry point, DI setup
|
|
│ ├── Commands/
|
|
│ │ ├── CommandFactory.cs # Command routing
|
|
│ │ ├── Crypto/CryptoCommandGroup.cs # Crypto commands
|
|
│ │ ├── Admin/AdminCommandGroup.cs # Admin commands
|
|
│ │ └── ...
|
|
│ └── StellaOps.Cli.csproj # Conditional <ProjectReference>
|
|
│
|
|
├── StellaOps.Cli.Crypto/
|
|
│ ├── ICryptoProvider.cs # Plugin interface
|
|
│ ├── ICryptoProviderDiagnostics.cs # Diagnostics interface
|
|
│ └── Models/ # Shared models
|
|
│
|
|
├── StellaOps.Cli.Crypto.Default/ # Always included
|
|
│ ├── DotNetCryptoProvider.cs # .NET crypto
|
|
│ ├── BouncyCastleCryptoProvider.cs # BouncyCastle
|
|
│ └── ServiceCollectionExtensions.cs # DI registration
|
|
│
|
|
├── StellaOps.Cli.Crypto.Gost/ # Conditional (Russia)
|
|
│ ├── GostCryptoProvider.cs # GOST implementation
|
|
│ ├── CryptoProAdapter.cs # CryptoPro CSP adapter
|
|
│ ├── OpenSslGostAdapter.cs # OpenSSL-GOST adapter
|
|
│ └── ServiceCollectionExtensions.cs
|
|
│
|
|
├── StellaOps.Cli.Crypto.Eidas/ # Conditional (EU)
|
|
│ ├── EidasCryptoProvider.cs # eIDAS implementation
|
|
│ ├── TspClientAdapter.cs # TSP remote signing
|
|
│ └── ServiceCollectionExtensions.cs
|
|
│
|
|
└── StellaOps.Cli.Crypto.Sm/ # Conditional (China)
|
|
├── SmCryptoProvider.cs # SM implementation
|
|
├── GmSslAdapter.cs # GmSSL adapter
|
|
└── ServiceCollectionExtensions.cs
|
|
```
|
|
|
|
### StellaOps.Cli.csproj (Conditional References)
|
|
|
|
```xml
|
|
<Project Sdk="Microsoft.NET.Sdk">
|
|
<PropertyGroup>
|
|
<TargetFramework>net10.0</TargetFramework>
|
|
<OutputType>Exe</OutputType>
|
|
</PropertyGroup>
|
|
|
|
<!-- Always include default crypto -->
|
|
<ItemGroup>
|
|
<ProjectReference Include="..\StellaOps.Cli.Crypto\StellaOps.Cli.Crypto.csproj" />
|
|
<ProjectReference Include="..\StellaOps.Cli.Crypto.Default\StellaOps.Cli.Crypto.Default.csproj" />
|
|
</ItemGroup>
|
|
|
|
<!-- GOST plugin (Russia distribution) -->
|
|
<ItemGroup Condition="'$(StellaOpsEnableGOST)' == 'true'">
|
|
<ProjectReference Include="..\StellaOps.Cli.Crypto.Gost\StellaOps.Cli.Crypto.Gost.csproj" />
|
|
<DefineConstants>$(DefineConstants);STELLAOPS_ENABLE_GOST</DefineConstants>
|
|
</ItemGroup>
|
|
|
|
<!-- eIDAS plugin (EU distribution) -->
|
|
<ItemGroup Condition="'$(StellaOpsEnableEIDAS)' == 'true'">
|
|
<ProjectReference Include="..\StellaOps.Cli.Crypto.Eidas\StellaOps.Cli.Crypto.Eidas.csproj" />
|
|
<DefineConstants>$(DefineConstants);STELLAOPS_ENABLE_EIDAS</DefineConstants>
|
|
</ItemGroup>
|
|
|
|
<!-- SM plugin (China distribution) -->
|
|
<ItemGroup Condition="'$(StellaOpsEnableSM)' == 'true'">
|
|
<ProjectReference Include="..\StellaOps.Cli.Crypto.Sm\StellaOps.Cli.Crypto.Sm.csproj" />
|
|
<DefineConstants>$(DefineConstants);STELLAOPS_ENABLE_SM</DefineConstants>
|
|
</ItemGroup>
|
|
</Project>
|
|
```
|
|
|
|
### Build Commands
|
|
|
|
```bash
|
|
# International distribution (default, no flags)
|
|
dotnet publish src/Cli/StellaOps.Cli --configuration Release --runtime linux-x64
|
|
|
|
# Russia distribution (GOST enabled)
|
|
dotnet publish src/Cli/StellaOps.Cli \
|
|
--configuration Release \
|
|
--runtime linux-x64 \
|
|
-p:StellaOpsEnableGOST=true
|
|
|
|
# EU distribution (eIDAS enabled)
|
|
dotnet publish src/Cli/StellaOps.Cli \
|
|
--configuration Release \
|
|
--runtime linux-x64 \
|
|
-p:StellaOpsEnableEIDAS=true
|
|
|
|
# China distribution (SM enabled)
|
|
dotnet publish src/Cli/StellaOps.Cli \
|
|
--configuration Release \
|
|
--runtime linux-x64 \
|
|
-p:StellaOpsEnableSM=true
|
|
```
|
|
|
|
---
|
|
|
|
## Runtime Plugin Discovery
|
|
|
|
### Program.cs - DI Registration
|
|
|
|
```csharp
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using StellaOps.Cli.Crypto;
|
|
using StellaOps.Cli.Crypto.Default;
|
|
|
|
#if STELLAOPS_ENABLE_GOST
|
|
using StellaOps.Cli.Crypto.Gost;
|
|
#endif
|
|
|
|
#if STELLAOPS_ENABLE_EIDAS
|
|
using StellaOps.Cli.Crypto.Eidas;
|
|
#endif
|
|
|
|
#if STELLAOPS_ENABLE_SM
|
|
using StellaOps.Cli.Crypto.Sm;
|
|
#endif
|
|
|
|
namespace StellaOps.Cli;
|
|
|
|
public class Program
|
|
{
|
|
public static async Task<int> Main(string[] args)
|
|
{
|
|
// Build configuration
|
|
var configuration = new ConfigurationBuilder()
|
|
.SetBasePath(Directory.GetCurrentDirectory())
|
|
.AddJsonFile("appsettings.json", optional: true)
|
|
.AddYamlFile("appsettings.yaml", optional: true)
|
|
.AddYamlFile(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".stellaops", "config.yaml"), optional: true)
|
|
.AddEnvironmentVariables("STELLAOPS_")
|
|
.Build();
|
|
|
|
// Setup DI container
|
|
var services = new ServiceCollection();
|
|
|
|
// Register configuration
|
|
services.AddSingleton<IConfiguration>(configuration);
|
|
|
|
// Register HTTP clients
|
|
services.AddHttpClient("StellaOpsBackend", client =>
|
|
{
|
|
var baseUrl = configuration["StellaOps:Backend:BaseUrl"];
|
|
if (!string.IsNullOrEmpty(baseUrl))
|
|
client.BaseAddress = new Uri(baseUrl);
|
|
});
|
|
|
|
// Register default crypto providers (always available)
|
|
services.AddDefaultCryptoProviders(configuration);
|
|
|
|
// Register regional crypto providers (conditional compilation)
|
|
#if STELLAOPS_ENABLE_GOST
|
|
services.AddGostCryptoProviders(configuration);
|
|
#endif
|
|
|
|
#if STELLAOPS_ENABLE_EIDAS
|
|
services.AddEidasCryptoProviders(configuration);
|
|
#endif
|
|
|
|
#if STELLAOPS_ENABLE_SM
|
|
services.AddSmCryptoProviders(configuration);
|
|
#endif
|
|
|
|
// Build service provider
|
|
var serviceProvider = services.BuildServiceProvider();
|
|
|
|
// Create root command and run
|
|
var rootCommand = CommandFactory.CreateRootCommand(serviceProvider);
|
|
return await rootCommand.InvokeAsync(args);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Plugin Discovery Flow
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant Build as MSBuild
|
|
participant CLI as stella CLI
|
|
participant DI as DI Container
|
|
participant Plugin as Crypto Plugin
|
|
participant User as User Command
|
|
|
|
Build->>Build: Check StellaOpsEnableGOST=true
|
|
Build->>Build: Include GOST plugin <ProjectReference>
|
|
Build->>Build: Set DefineConstants=STELLAOPS_ENABLE_GOST
|
|
Build->>CLI: Compile with GOST plugin
|
|
|
|
User->>CLI: stella crypto sign --provider gost
|
|
CLI->>CLI: Program.cs startup
|
|
CLI->>CLI: Check #if STELLAOPS_ENABLE_GOST
|
|
CLI->>DI: services.AddGostCryptoProviders()
|
|
DI->>Plugin: Register GostCryptoProvider as ICryptoProvider
|
|
Plugin->>DI: Provider registered
|
|
|
|
CLI->>DI: Resolve ICryptoProvider (name="gost")
|
|
DI->>Plugin: Return GostCryptoProvider instance
|
|
Plugin->>CLI: Execute sign operation
|
|
CLI->>User: Signature created
|
|
```
|
|
|
|
---
|
|
|
|
## Plugin Interfaces
|
|
|
|
### ICryptoProvider
|
|
|
|
The core interface all crypto providers must implement:
|
|
|
|
```csharp
|
|
namespace StellaOps.Cli.Crypto;
|
|
|
|
public interface ICryptoProvider
|
|
{
|
|
/// <summary>
|
|
/// Unique provider name (e.g., "gost", "eidas", "sm")
|
|
/// </summary>
|
|
string Name { get; }
|
|
|
|
/// <summary>
|
|
/// Supported algorithms (e.g., "GOST12-256", "ECDSA-P256")
|
|
/// </summary>
|
|
string[] SupportedAlgorithms { get; }
|
|
|
|
/// <summary>
|
|
/// Sign data with specified algorithm and key
|
|
/// </summary>
|
|
Task<byte[]> SignAsync(
|
|
byte[] data,
|
|
string algorithm,
|
|
CryptoKeyReference keyRef,
|
|
CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Verify signature
|
|
/// </summary>
|
|
Task<bool> VerifyAsync(
|
|
byte[] data,
|
|
byte[] signature,
|
|
string algorithm,
|
|
CryptoKeyReference keyRef,
|
|
CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// List available keys
|
|
/// </summary>
|
|
Task<IReadOnlyList<CryptoKeyInfo>> ListKeysAsync(
|
|
CancellationToken cancellationToken = default);
|
|
}
|
|
```
|
|
|
|
### ICryptoProviderDiagnostics
|
|
|
|
Optional interface for provider diagnostics:
|
|
|
|
```csharp
|
|
namespace StellaOps.Cli.Crypto;
|
|
|
|
public interface ICryptoProviderDiagnostics
|
|
{
|
|
/// <summary>
|
|
/// Run provider self-test
|
|
/// </summary>
|
|
Task<ProviderHealthCheck> HealthCheckAsync(CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Get provider version and capabilities
|
|
/// </summary>
|
|
ProviderInfo GetInfo();
|
|
}
|
|
|
|
public sealed record ProviderHealthCheck
|
|
{
|
|
public required string ProviderName { get; init; }
|
|
public required bool IsHealthy { get; init; }
|
|
public required string[] Checks { get; init; }
|
|
public string? ErrorMessage { get; init; }
|
|
}
|
|
|
|
public sealed record ProviderInfo
|
|
{
|
|
public required string Name { get; init; }
|
|
public required string Version { get; init; }
|
|
public required string[] Capabilities { get; init; }
|
|
public required string[] SupportedAlgorithms { get; init; }
|
|
}
|
|
```
|
|
|
|
### CryptoKeyReference
|
|
|
|
Represents a reference to a cryptographic key:
|
|
|
|
```csharp
|
|
namespace StellaOps.Cli.Crypto;
|
|
|
|
public sealed record CryptoKeyReference
|
|
{
|
|
/// <summary>
|
|
/// Key identifier (e.g., "prod-key-2024", file path, HSM slot)
|
|
/// </summary>
|
|
public required string KeyId { get; init; }
|
|
|
|
/// <summary>
|
|
/// Key source: "file", "hsm", "kms", "csp"
|
|
/// </summary>
|
|
public required string Source { get; init; }
|
|
|
|
/// <summary>
|
|
/// Additional parameters (e.g., HSM PIN, KMS region)
|
|
/// </summary>
|
|
public IReadOnlyDictionary<string, string>? Parameters { get; init; }
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Configuration
|
|
|
|
### Profile-based Provider Selection
|
|
|
|
```yaml
|
|
StellaOps:
|
|
Crypto:
|
|
# Default provider (when --provider not specified)
|
|
DefaultProvider: "default"
|
|
|
|
# Crypto profiles for easy switching
|
|
Profiles:
|
|
- name: "default-signing"
|
|
provider: "default"
|
|
algorithm: "ECDSA-P256"
|
|
keyId: "default-key"
|
|
|
|
- name: "gost-signing"
|
|
provider: "gost"
|
|
algorithm: "GOST12-256"
|
|
keyId: "gost-key-2024"
|
|
|
|
- name: "eidas-qes"
|
|
provider: "eidas"
|
|
algorithm: "ECDSA-P256-QES"
|
|
keyId: "eidas-qes-key"
|
|
|
|
# Provider-specific configuration
|
|
Providers:
|
|
Gost:
|
|
CryptoProCsp:
|
|
Enabled: true
|
|
ContainerName: "StellaOps-GOST-2024"
|
|
|
|
OpenSslGost:
|
|
Enabled: false
|
|
EnginePath: "/usr/lib/engines/gost.so"
|
|
|
|
Eidas:
|
|
TspClient:
|
|
Enabled: true
|
|
TspUrl: "https://tsp.example.eu/api/v1/sign"
|
|
ApiKey: "${EIDAS_TSP_API_KEY}"
|
|
|
|
Sm:
|
|
GmSsl:
|
|
Enabled: true
|
|
LibraryPath: "/usr/lib/libgmssl.so"
|
|
```
|
|
|
|
### Usage with Profiles
|
|
|
|
```bash
|
|
# Use default profile
|
|
stella crypto sign --file document.pdf
|
|
|
|
# Use specific profile
|
|
stella crypto sign --profile gost-signing --file document.pdf
|
|
|
|
# Override provider explicitly
|
|
stella crypto sign --provider gost --algorithm GOST12-256 --key-id key1 --file document.pdf
|
|
```
|
|
|
|
---
|
|
|
|
## Distribution Matrix
|
|
|
|
| Distribution | Default | GOST | eIDAS | SM |
|
|
|--------------|---------|------|-------|-----|
|
|
| **stella-international** | ✅ | ❌ | ❌ | ❌ |
|
|
| **stella-russia** | ✅ | ✅ | ❌ | ❌ |
|
|
| **stella-eu** | ✅ | ❌ | ✅ | ❌ |
|
|
| **stella-china** | ✅ | ❌ | ❌ | ✅ |
|
|
|
|
**Verification:**
|
|
```bash
|
|
# Check available providers
|
|
stella crypto providers
|
|
|
|
# Output (International):
|
|
# Available Crypto Providers:
|
|
# - default (.NET Crypto, BouncyCastle)
|
|
|
|
# Output (Russia):
|
|
# Available Crypto Providers:
|
|
# - default (.NET Crypto, BouncyCastle)
|
|
# - gost (GOST R 34.10-2012, GOST R 34.11-2012)
|
|
```
|
|
|
|
---
|
|
|
|
## Creating Custom Plugins
|
|
|
|
### 1. Create Plugin Project
|
|
|
|
```bash
|
|
dotnet new classlib -n StellaOps.Cli.Crypto.MyCustom
|
|
cd StellaOps.Cli.Crypto.MyCustom
|
|
|
|
# Add reference to interface project
|
|
dotnet add reference ../StellaOps.Cli.Crypto/StellaOps.Cli.Crypto.csproj
|
|
```
|
|
|
|
### 2. Implement ICryptoProvider
|
|
|
|
```csharp
|
|
using StellaOps.Cli.Crypto;
|
|
|
|
namespace StellaOps.Cli.Crypto.MyCustom;
|
|
|
|
public class MyCustomCryptoProvider : ICryptoProvider, ICryptoProviderDiagnostics
|
|
{
|
|
private readonly MyCustomCryptoOptions _options;
|
|
|
|
public MyCustomCryptoProvider(IOptions<MyCustomCryptoOptions> options)
|
|
{
|
|
_options = options.Value;
|
|
}
|
|
|
|
public string Name => "mycustom";
|
|
|
|
public string[] SupportedAlgorithms => new[] { "MYCUSTOM-ALG1", "MYCUSTOM-ALG2" };
|
|
|
|
public async Task<byte[]> SignAsync(
|
|
byte[] data,
|
|
string algorithm,
|
|
CryptoKeyReference keyRef,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
// Implementation
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public async Task<bool> VerifyAsync(
|
|
byte[] data,
|
|
byte[] signature,
|
|
string algorithm,
|
|
CryptoKeyReference keyRef,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
// Implementation
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public async Task<IReadOnlyList<CryptoKeyInfo>> ListKeysAsync(
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
// Implementation
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public async Task<ProviderHealthCheck> HealthCheckAsync(
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
return new ProviderHealthCheck
|
|
{
|
|
ProviderName = Name,
|
|
IsHealthy = true,
|
|
Checks = new[] { "Library loaded", "Keys accessible" }
|
|
};
|
|
}
|
|
|
|
public ProviderInfo GetInfo()
|
|
{
|
|
return new ProviderInfo
|
|
{
|
|
Name = Name,
|
|
Version = "1.0.0",
|
|
Capabilities = new[] { "sign", "verify" },
|
|
SupportedAlgorithms = SupportedAlgorithms
|
|
};
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3. Create DI Extension
|
|
|
|
```csharp
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
namespace StellaOps.Cli.Crypto.MyCustom;
|
|
|
|
public static class ServiceCollectionExtensions
|
|
{
|
|
public static IServiceCollection AddMyCustomCryptoProviders(
|
|
this IServiceCollection services,
|
|
IConfiguration configuration)
|
|
{
|
|
// Register provider
|
|
services.AddSingleton<ICryptoProvider, MyCustomCryptoProvider>();
|
|
|
|
// Bind configuration
|
|
services.Configure<MyCustomCryptoOptions>(
|
|
configuration.GetSection("StellaOps:Crypto:Providers:MyCustom"));
|
|
|
|
return services;
|
|
}
|
|
}
|
|
```
|
|
|
|
### 4. Update StellaOps.Cli.csproj
|
|
|
|
```xml
|
|
<!-- MyCustom plugin (custom distribution) -->
|
|
<ItemGroup Condition="'$(StellaOpsEnableMyCustom)' == 'true'">
|
|
<ProjectReference Include="..\StellaOps.Cli.Crypto.MyCustom\StellaOps.Cli.Crypto.MyCustom.csproj" />
|
|
<DefineConstants>$(DefineConstants);STELLAOPS_ENABLE_MYCUSTOM</DefineConstants>
|
|
</ItemGroup>
|
|
```
|
|
|
|
### 5. Update Program.cs
|
|
|
|
```csharp
|
|
#if STELLAOPS_ENABLE_MYCUSTOM
|
|
using StellaOps.Cli.Crypto.MyCustom;
|
|
#endif
|
|
|
|
// In Main():
|
|
#if STELLAOPS_ENABLE_MYCUSTOM
|
|
services.AddMyCustomCryptoProviders(configuration);
|
|
#endif
|
|
```
|
|
|
|
### 6. Build Custom Distribution
|
|
|
|
```bash
|
|
dotnet publish src/Cli/StellaOps.Cli \
|
|
--configuration Release \
|
|
--runtime linux-x64 \
|
|
-p:StellaOpsEnableMyCustom=true
|
|
```
|
|
|
|
---
|
|
|
|
## Command Routing
|
|
|
|
### System.CommandLine 2.0 Integration
|
|
|
|
```csharp
|
|
// CommandFactory.cs
|
|
using System.CommandLine;
|
|
|
|
public static class CommandFactory
|
|
{
|
|
public static Command CreateRootCommand(IServiceProvider services)
|
|
{
|
|
var root = new Command("stella", "StellaOps unified CLI");
|
|
|
|
// Add command groups
|
|
root.Add(BuildScanCommand(services));
|
|
root.Add(BuildCryptoCommand(services));
|
|
root.Add(BuildAdminCommand(services));
|
|
root.Add(BuildAuthCommand(services));
|
|
// ... more commands
|
|
|
|
return root;
|
|
}
|
|
|
|
private static Command BuildCryptoCommand(IServiceProvider services)
|
|
{
|
|
var crypto = new Command("crypto", "Cryptographic operations");
|
|
|
|
// crypto providers
|
|
var providers = new Command("providers", "List available crypto providers");
|
|
providers.SetAction(async (parseResult, ct) =>
|
|
{
|
|
var cryptoProviders = services.GetServices<ICryptoProvider>();
|
|
foreach (var provider in cryptoProviders)
|
|
{
|
|
Console.WriteLine($"- {provider.Name}: {string.Join(", ", provider.SupportedAlgorithms)}");
|
|
}
|
|
return 0;
|
|
});
|
|
crypto.Add(providers);
|
|
|
|
// crypto sign
|
|
var sign = new Command("sign", "Sign file");
|
|
// ... add options and handler
|
|
crypto.Add(sign);
|
|
|
|
return crypto;
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Testing
|
|
|
|
### Unit Tests
|
|
|
|
```csharp
|
|
using StellaOps.Cli.Crypto;
|
|
using StellaOps.Cli.Crypto.Gost;
|
|
using Xunit;
|
|
|
|
public class GostCryptoProviderTests
|
|
{
|
|
[Fact]
|
|
public void Name_ReturnsGost()
|
|
{
|
|
var provider = new GostCryptoProvider(Options.Create(new GostCryptoOptions()));
|
|
Assert.Equal("gost", provider.Name);
|
|
}
|
|
|
|
[Fact]
|
|
public void SupportedAlgorithms_IncludesGost12_256()
|
|
{
|
|
var provider = new GostCryptoProvider(Options.Create(new GostCryptoOptions()));
|
|
Assert.Contains("GOST12-256", provider.SupportedAlgorithms);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SignAsync_ProducesSignature()
|
|
{
|
|
var provider = new GostCryptoProvider(Options.Create(new GostCryptoOptions()));
|
|
var data = "test"u8.ToArray();
|
|
var keyRef = new CryptoKeyReference { KeyId = "test-key", Source = "file" };
|
|
|
|
var signature = await provider.SignAsync(data, "GOST12-256", keyRef);
|
|
|
|
Assert.NotNull(signature);
|
|
Assert.NotEmpty(signature);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Integration Tests
|
|
|
|
```csharp
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Xunit;
|
|
|
|
public class CryptoPluginIntegrationTests
|
|
{
|
|
[Fact]
|
|
public void ServiceProvider_ResolvesAllProviders()
|
|
{
|
|
var services = new ServiceCollection();
|
|
var configuration = new ConfigurationBuilder().Build();
|
|
|
|
services.AddDefaultCryptoProviders(configuration);
|
|
#if STELLAOPS_ENABLE_GOST
|
|
services.AddGostCryptoProviders(configuration);
|
|
#endif
|
|
|
|
var serviceProvider = services.BuildServiceProvider();
|
|
var providers = serviceProvider.GetServices<ICryptoProvider>().ToList();
|
|
|
|
Assert.NotEmpty(providers);
|
|
Assert.Contains(providers, p => p.Name == "default");
|
|
#if STELLAOPS_ENABLE_GOST
|
|
Assert.Contains(providers, p => p.Name == "gost");
|
|
#endif
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Packaging
|
|
|
|
### NuGet Package Structure
|
|
|
|
```
|
|
StellaOps.Cli (metapackage)
|
|
├── StellaOps.Cli.Crypto (interfaces)
|
|
├── StellaOps.Cli.Crypto.Default (always included)
|
|
├── StellaOps.Cli.Crypto.Gost (optional)
|
|
├── StellaOps.Cli.Crypto.Eidas (optional)
|
|
└── StellaOps.Cli.Crypto.Sm (optional)
|
|
```
|
|
|
|
### Distribution Artifacts
|
|
|
|
```
|
|
releases/
|
|
├── stella-international-linux-x64.tar.gz
|
|
├── stella-russia-linux-x64.tar.gz
|
|
├── stella-eu-linux-x64.tar.gz
|
|
└── stella-china-linux-x64.tar.gz
|
|
```
|
|
|
|
Each artifact contains only the authorized crypto providers for that region.
|
|
|
|
---
|
|
|
|
## See Also
|
|
|
|
- [Command Reference](command-reference.md) - Complete command documentation
|
|
- [Crypto Plugin Development](crypto-plugins.md) - Detailed plugin development guide
|
|
- [Compliance Guide](compliance-guide.md) - Regional compliance requirements
|
|
- [Distribution Matrix](distribution-matrix.md) - Build and distribution guide
|
|
- [Troubleshooting](troubleshooting.md) - Common plugin issues
|