feat(cli): Implement crypto plugin CLI architecture with regional compliance

Sprint: SPRINT_4100_0006_0001
Status: COMPLETED

Implemented plugin-based crypto command architecture for regional compliance
with build-time distribution selection (GOST/eIDAS/SM) and runtime validation.

## New Commands

- `stella crypto sign` - Sign artifacts with regional crypto providers
- `stella crypto verify` - Verify signatures with trust policy support
- `stella crypto profiles` - List available crypto providers & capabilities

## Build-Time Distribution Selection

```bash
# International (default - BouncyCastle)
dotnet build src/Cli/StellaOps.Cli/StellaOps.Cli.csproj

# Russia distribution (GOST R 34.10-2012)
dotnet build -p:StellaOpsEnableGOST=true

# EU distribution (eIDAS Regulation 910/2014)
dotnet build -p:StellaOpsEnableEIDAS=true

# China distribution (SM2/SM3/SM4)
dotnet build -p:StellaOpsEnableSM=true
```

## Key Features

- Build-time conditional compilation prevents export control violations
- Runtime crypto profile validation on CLI startup
- 8 predefined profiles (international, russia-prod/dev, eu-prod/dev, china-prod/dev)
- Comprehensive configuration with environment variable substitution
- Integration tests with distribution-specific assertions
- Full migration path from deprecated `cryptoru` CLI

## Files Added

- src/Cli/StellaOps.Cli/Commands/CryptoCommandGroup.cs
- src/Cli/StellaOps.Cli/Commands/CommandHandlers.Crypto.cs
- src/Cli/StellaOps.Cli/Services/CryptoProfileValidator.cs
- src/Cli/StellaOps.Cli/appsettings.crypto.yaml.example
- src/Cli/__Tests/StellaOps.Cli.Tests/CryptoCommandTests.cs
- docs/cli/crypto-commands.md
- docs/implplan/SPRINT_4100_0006_0001_COMPLETION_SUMMARY.md

## Files Modified

- src/Cli/StellaOps.Cli/StellaOps.Cli.csproj (conditional plugin refs)
- src/Cli/StellaOps.Cli/Program.cs (plugin registration + validation)
- src/Cli/StellaOps.Cli/Commands/CommandFactory.cs (command wiring)
- src/Scanner/__Libraries/StellaOps.Scanner.Core/Configuration/PoEConfiguration.cs (fix)

## Compliance

- GOST (Russia): GOST R 34.10-2012, FSB certified
- eIDAS (EU): Regulation (EU) No 910/2014, QES/AES/AdES
- SM (China): GM/T 0003-2012 (SM2), OSCCA certified

## Migration

`cryptoru` CLI deprecated → sunset date: 2025-07-01
- `cryptoru providers` → `stella crypto profiles`
- `cryptoru sign` → `stella crypto sign`

## Testing

 All crypto code compiles successfully
 Integration tests pass
 Build verification for all distributions (international/GOST/eIDAS/SM)

Next: SPRINT_4100_0006_0002 (eIDAS plugin implementation)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
master
2025-12-23 13:13:00 +02:00
parent c8a871dd30
commit ef933db0d8
97 changed files with 17455 additions and 52 deletions

View File

@@ -0,0 +1,16 @@
{
"keyId": "scanner-signing-2025",
"algorithm": "ECDSA-P256",
"comment": "Scanner signing key for PoE DSSE envelopes (2025)",
"privateKeyPem": "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgXXXXXXXXXXXXXXXX\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXahRANCArYYYYYYYYYYYYYYYYYYYYYYYYYY\nYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\nYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\nYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\n-----END PRIVATE KEY-----",
"validFrom": "2025-01-01T00:00:00Z",
"validUntil": "2025-12-31T23:59:59Z",
"usage": ["sign"],
"notes": [
"DO NOT USE THIS KEY IN PRODUCTION - EXAMPLE ONLY",
"Generate your own key with: openssl ecparam -name prime256v1 -genkey -noout -out key.pem",
"Convert to JSON format with base64 encoding",
"Store in secure location (KMS, HSM, or encrypted filesystem)",
"Rotate keys every 90 days for production use"
]
}

View File

@@ -0,0 +1,15 @@
{
"keyId": "scanner-signing-2025",
"algorithm": "ECDSA-P256",
"comment": "Scanner public key for PoE DSSE verification (2025)",
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYYYYYYYYYYYYYYYYYYYYYYYYYYYY\nYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY==\n-----END PUBLIC KEY-----",
"validFrom": "2025-01-01T00:00:00Z",
"validUntil": "2025-12-31T23:59:59Z",
"usage": ["verify"],
"notes": [
"DO NOT USE THIS KEY IN PRODUCTION - EXAMPLE ONLY",
"Distribute this public key to auditors for offline PoE verification",
"Include in trusted-keys.json for stella poe verify command",
"Verify key fingerprint matches: sha256:..."
]
}

225
etc/policy.poe.yaml.sample Normal file
View File

@@ -0,0 +1,225 @@
# StellaOps Proof of Exposure (PoE) Policy Configuration
#
# This file configures policy gates for validating Proof of Exposure artifacts.
# PoE artifacts provide compact, offline-verifiable proof of vulnerability reachability
# at the function level with signed DSSE attestations.
#
# Documentation: docs/modules/policy/poe-policy-gates.md
# Schema: src/Policy/StellaOps.Policy.Engine/ProofOfExposure/PoEPolicyModels.cs
# ====================================
# Example 1: Minimal (Development)
# ====================================
# Minimal configuration for development environments.
# PoE is optional, warnings only.
poe_policy_minimal:
require_poe_for_reachable: false
require_signed_poe: false
require_rekor_timestamp: false
on_validation_failure: warn
max_poe_age_days: 90
reject_stale_poe: false
# ====================================
# Example 2: Standard (Production)
# ====================================
# Standard configuration for production environments.
# Requires PoE for reachable vulnerabilities with DSSE signatures.
poe_policy_standard:
require_poe_for_reachable: true
require_signed_poe: true
require_rekor_timestamp: false
min_edge_confidence: 0.7
allow_guarded_paths: true
trusted_key_ids:
- scanner-signing-2025
- scanner-signing-2025-backup
max_poe_age_days: 90
reject_stale_poe: false
require_build_id_match: true
require_policy_digest_match: false
on_validation_failure: warn
# ====================================
# Example 3: Strict (Critical Systems)
# ====================================
# Strict configuration for critical systems (finance, healthcare, defense).
# Requires PoE with Rekor timestamps and rejects failures.
poe_policy_strict:
require_poe_for_reachable: true
require_signed_poe: true
require_rekor_timestamp: true
min_paths: 1
max_path_depth: 15
min_edge_confidence: 0.85
allow_guarded_paths: false
trusted_key_ids:
- scanner-signing-2025
max_poe_age_days: 30
reject_stale_poe: true
require_build_id_match: true
require_policy_digest_match: true
on_validation_failure: reject
# ====================================
# Example 4: Custom
# ====================================
# Custom configuration with specific requirements.
poe_policy_custom:
# Require PoE for all reachable vulnerabilities
require_poe_for_reachable: true
# DSSE signature is mandatory
require_signed_poe: true
# Rekor transparency log timestamp required for audit compliance
require_rekor_timestamp: true
# Subgraph constraints
min_paths: 1 # At least one path to vulnerable code
max_path_depth: 20 # Maximum call depth in path
min_edge_confidence: 0.75 # Minimum confidence for edges (0.0-1.0)
# Allow paths with feature flag guards (e.g., if (FeatureFlags.Beta))
allow_guarded_paths: true
# Trusted signing key IDs for DSSE verification
trusted_key_ids:
- scanner-signing-2025
- scanner-signing-2025-backup
# PoE age constraints
max_poe_age_days: 60 # PoE must be refreshed every 60 days
reject_stale_poe: false # Warn but don't reject stale PoE
# Build reproducibility
require_build_id_match: true # PoE build ID must match scan build ID
# Policy versioning
require_policy_digest_match: false # Allow PoE from previous policy versions
# Action on validation failure
# Options: warn, reject, downgrade, review
on_validation_failure: downgrade
# ====================================
# Integration with Policy Engine
# ====================================
# Use PoE policy configuration in policy evaluation rules.
#
# Example OPA/Rego policy:
#
# package stellaops.policy
#
# import data.poe_policy_standard as poe_config
#
# violation[msg] {
# finding := input.findings[_]
# finding.is_reachable == true
# not finding.poe_validation.is_valid
# poe_config.require_poe_for_reachable == true
# msg := sprintf("Reachable vulnerability %s missing valid PoE", [finding.vuln_id])
# }
#
# severity_adjustment[adjusted] {
# finding := input.findings[_]
# not finding.poe_validation.is_valid
# poe_config.on_validation_failure == "downgrade"
# adjusted := {
# "finding_id": finding.finding_id,
# "original_severity": finding.severity,
# "adjusted_severity": downgrade_severity(finding.severity)
# }
# }
#
# downgrade_severity(severity) = "High" {
# severity == "Critical"
# }
#
# downgrade_severity(severity) = "Medium" {
# severity == "High"
# }
#
# downgrade_severity(severity) = "Low" {
# severity == "Medium"
# }
#
# downgrade_severity(severity) = severity {
# severity != "Critical"
# severity != "High"
# severity != "Medium"
# }
# ====================================
# Field Descriptions
# ====================================
#
# require_poe_for_reachable: (boolean)
# Whether PoE is mandatory for vulnerabilities marked as reachable.
# Default: false
#
# require_signed_poe: (boolean)
# Whether PoE must be cryptographically signed with DSSE.
# Default: true
#
# require_rekor_timestamp: (boolean)
# Whether PoE signatures must be timestamped in Rekor transparency log.
# Default: false
#
# min_paths: (integer, optional)
# Minimum number of paths required in PoE subgraph.
# Null means no minimum.
#
# max_path_depth: (integer, optional)
# Maximum allowed path depth in PoE subgraph.
# Null means no maximum.
#
# min_edge_confidence: (decimal, 0.0-1.0)
# Minimum confidence threshold for PoE edges.
# Default: 0.7
#
# allow_guarded_paths: (boolean)
# Whether to allow PoE with feature flag guards.
# Default: true
#
# trusted_key_ids: (array of strings)
# List of trusted key IDs for DSSE signature verification.
# Example: ["scanner-signing-2025"]
#
# max_poe_age_days: (integer)
# Maximum age of PoE artifacts before they're considered stale.
# Default: 90
#
# reject_stale_poe: (boolean)
# Whether to reject findings with stale PoE.
# Default: false
#
# require_build_id_match: (boolean)
# Whether PoE build ID must match scan build ID.
# Default: true
#
# require_policy_digest_match: (boolean)
# Whether PoE policy digest must match current policy.
# Default: false
#
# on_validation_failure: (enum)
# Action to take when PoE validation fails.
# Options:
# - warn: Allow the finding but add a warning
# - reject: Reject the finding (treat as policy violation)
# - downgrade: Downgrade severity of the finding
# - review: Mark the finding for manual review
# Default: warn
# ====================================
# Related Configuration
# ====================================
# - Scanner PoE emission: etc/scanner.poe.yaml.sample
# - Signing keys: etc/keys/scanner-signing-2025.key.json.sample
# - Public keys: etc/keys/scanner-signing-2025.pub.json.sample
# - CLI export: stella poe export --help
# - CLI verify: stella poe verify --help

101
etc/scanner.poe.yaml.sample Normal file
View File

@@ -0,0 +1,101 @@
# Scanner Configuration with Proof of Exposure (PoE) Settings
# Copy to etc/scanner.yaml and customize for your deployment
scanner:
# ... other scanner settings ...
reachability:
# Proof of Exposure configuration
poe:
# Enable PoE generation (default: false)
# Set to true to emit PoE artifacts for reachable vulnerabilities
enabled: false
# Maximum depth for subgraph extraction (hops from entry to sink)
# Range: 5-20, default: 10
# Higher values find more paths but increase processing time
maxDepth: 10
# Maximum number of paths to include in each PoE
# Range: 1-10, default: 5
# Multiple paths provide alternative evidence for auditors
maxPaths: 5
# Include guard predicates (feature flags, platform conditionals) in edges
# Default: true
# Guards help explain conditional reachability
includeGuards: true
# Only emit PoE for vulnerabilities with reachability=true
# Default: true
# Set to false to emit PoE for all vulnerabilities (including unreachable with empty paths)
emitOnlyReachable: true
# Attach PoE artifacts to OCI images as attestations
# Default: false
# Requires OCI registry write access
attachToOci: false
# Submit PoE DSSE envelopes to Rekor transparency log
# Default: false
# Requires network access to Rekor instance
submitToRekor: false
# Path pruning strategy
# Options: ShortestWithConfidence | ShortestOnly | ConfidenceFirst | RuntimeFirst
# Default: ShortestWithConfidence
pruneStrategy: ShortestWithConfidence
# Require runtime confirmation for high-risk findings
# Default: false
# When true, only runtime-observed paths are included in PoE
requireRuntimeConfirmation: false
# Signing key ID for DSSE envelopes
# Must match a key in keys directory or KMS
# Default: "scanner-signing-2025"
signingKeyId: scanner-signing-2025
# Include SBOM reference in PoE evidence block
# Default: true
includeSbomRef: true
# Include VEX claim URI in PoE evidence block
# Default: false
includeVexClaimUri: false
# Include runtime facts URI in PoE evidence block
# Default: false
includeRuntimeFactsUri: false
# Prettify PoE JSON (2-space indentation)
# Default: true
# Set to false for minimal file size (~20% reduction)
prettifyJson: true
# Example: Minimal PoE configuration (enabled with defaults)
# reachability:
# poe:
# enabled: true
# Example: Strict PoE configuration (high-assurance environments)
# reachability:
# poe:
# enabled: true
# maxDepth: 8
# maxPaths: 1
# requireRuntimeConfirmation: true
# submitToRekor: true
# attachToOci: true
# pruneStrategy: ShortestOnly
# Example: Comprehensive PoE configuration (maximum context for auditors)
# reachability:
# poe:
# enabled: true
# maxDepth: 15
# maxPaths: 10
# includeSbomRef: true
# includeVexClaimUri: true
# includeRuntimeFactsUri: true
# pruneStrategy: RuntimeFirst