feat(scanner): Complete PoE implementation with Windows compatibility fix
- 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>
This commit is contained in:
789
docs/cli/architecture.md
Normal file
789
docs/cli/architecture.md
Normal file
@@ -0,0 +1,789 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user