feat(crypto): Complete Phase 2 - Configuration-driven crypto architecture with 100% compliance
## Summary
This commit completes Phase 2 of the configuration-driven crypto architecture, achieving
100% crypto compliance by eliminating all hardcoded cryptographic implementations.
## Key Changes
### Phase 1: Plugin Loader Infrastructure
- **Plugin Discovery System**: Created StellaOps.Cryptography.PluginLoader with manifest-based loading
- **Configuration Model**: Added CryptoPluginConfiguration with regional profiles support
- **Dependency Injection**: Extended DI to support plugin-based crypto provider registration
- **Regional Configs**: Created appsettings.crypto.{international,russia,eu,china}.yaml
- **CI Workflow**: Added .gitea/workflows/crypto-compliance.yml for audit enforcement
### Phase 2: Code Refactoring
- **API Extension**: Added ICryptoProvider.CreateEphemeralVerifier for verification-only scenarios
- **Plugin Implementation**: Created OfflineVerificationCryptoProvider with ephemeral verifier support
- Supports ES256/384/512, RS256/384/512, PS256/384/512
- SubjectPublicKeyInfo (SPKI) public key format
- **100% Compliance**: Refactored DsseVerifier to remove all BouncyCastle cryptographic usage
- **Unit Tests**: Created OfflineVerificationProviderTests with 39 passing tests
- **Documentation**: Created comprehensive security guide at docs/security/offline-verification-crypto-provider.md
- **Audit Infrastructure**: Created scripts/audit-crypto-usage.ps1 for static analysis
### Testing Infrastructure (TestKit)
- **Determinism Gate**: Created DeterminismGate for reproducibility validation
- **Test Fixtures**: Added PostgresFixture and ValkeyFixture using Testcontainers
- **Traits System**: Implemented test lane attributes for parallel CI execution
- **JSON Assertions**: Added CanonicalJsonAssert for deterministic JSON comparisons
- **Test Lanes**: Created test-lanes.yml workflow for parallel test execution
### Documentation
- **Architecture**: Created CRYPTO_CONFIGURATION_DRIVEN_ARCHITECTURE.md master plan
- **Sprint Tracking**: Created SPRINT_1000_0007_0002_crypto_refactoring.md (COMPLETE)
- **API Documentation**: Updated docs2/cli/crypto-plugins.md and crypto.md
- **Testing Strategy**: Created testing strategy documents in docs/implplan/SPRINT_5100_0007_*
## Compliance & Testing
- ✅ Zero direct System.Security.Cryptography usage in production code
- ✅ All crypto operations go through ICryptoProvider abstraction
- ✅ 39/39 unit tests passing for OfflineVerificationCryptoProvider
- ✅ Build successful (AirGap, Crypto plugin, DI infrastructure)
- ✅ Audit script validates crypto boundaries
## Files Modified
**Core Crypto Infrastructure:**
- src/__Libraries/StellaOps.Cryptography/CryptoProvider.cs (API extension)
- src/__Libraries/StellaOps.Cryptography/CryptoSigningKey.cs (verification-only constructor)
- src/__Libraries/StellaOps.Cryptography/EcdsaSigner.cs (fixed ephemeral verifier)
**Plugin Implementation:**
- src/__Libraries/StellaOps.Cryptography.Plugin.OfflineVerification/ (new)
- src/__Libraries/StellaOps.Cryptography.PluginLoader/ (new)
**Production Code Refactoring:**
- src/AirGap/StellaOps.AirGap.Importer/Validation/DsseVerifier.cs (100% compliant)
**Tests:**
- src/__Libraries/__Tests/StellaOps.Cryptography.Plugin.OfflineVerification.Tests/ (new, 39 tests)
- src/__Libraries/__Tests/StellaOps.Cryptography.PluginLoader.Tests/ (new)
**Configuration:**
- etc/crypto-plugins-manifest.json (plugin registry)
- etc/appsettings.crypto.*.yaml (regional profiles)
**Documentation:**
- docs/security/offline-verification-crypto-provider.md (600+ lines)
- docs/implplan/CRYPTO_CONFIGURATION_DRIVEN_ARCHITECTURE.md (master plan)
- docs/implplan/SPRINT_1000_0007_0002_crypto_refactoring.md (Phase 2 complete)
## Next Steps
Phase 3: Docker & CI/CD Integration
- Create multi-stage Dockerfiles with all plugins
- Build regional Docker Compose files
- Implement runtime configuration selection
- Add deployment validation scripts
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,342 @@
|
||||
# Verdict Attestation Implementation Status
|
||||
|
||||
**Sprint**: SPRINT_3000_0100_0001 - Signed Delta-Verdicts
|
||||
**Status**: Phase 1 Complete (Policy Engine + Evidence Locker), Phase 2 Blocked
|
||||
**Last Updated**: 2025-12-23
|
||||
|
||||
## Completed Work
|
||||
|
||||
### 1. Policy Engine - Verdict Predicate & Attestation Service ✅
|
||||
|
||||
**Location**: `src/Policy/StellaOps.Policy.Engine/Attestation/`
|
||||
|
||||
#### Files Created:
|
||||
|
||||
1. **VerdictPredicate.cs** - Core predicate models
|
||||
- `VerdictPredicate` - Main predicate structure matching JSON schema
|
||||
- `VerdictInfo` - Verdict details (status/severity/score)
|
||||
- `VerdictRuleExecution` - Rule chain execution trace
|
||||
- `VerdictEvidence` - Evidence references (advisories, VEX, SBOM)
|
||||
- `VerdictVexImpact` - VEX impact assessment
|
||||
- `VerdictReachability` - Call graph reachability data
|
||||
- Uses canonical JSON serialization with lexicographic key ordering
|
||||
|
||||
2. **VerdictPredicateBuilder.cs** - Predicate assembly service
|
||||
- `Build(PolicyExplainTrace)` - Converts existing trace to attestation predicate
|
||||
- `Serialize(VerdictPredicate)` - Canonical JSON with sorted keys
|
||||
- `ComputeDeterminismHash(VerdictPredicate)` - SHA256 over sorted evidence + verdict
|
||||
- Maps all existing Policy Engine trace data to new attestation format
|
||||
|
||||
3. **IVerdictAttestationService.cs** - Service interface
|
||||
- `AttestVerdictAsync(trace)` - Orchestrates attestation creation
|
||||
- `VerdictAttestationRequest` - Request DTO with predicate, subject, metadata
|
||||
- `VerdictAttestationResult` - Response DTO with verdict ID and URI
|
||||
|
||||
4. **VerdictAttestationService.cs** - Service implementation
|
||||
- Feature-flagged via `VerdictAttestationOptions.Enabled`
|
||||
- Calls `VerdictPredicateBuilder` to create predicate
|
||||
- Calls `HttpAttestorClient` to request signing
|
||||
- Returns verdict ID for downstream tracking
|
||||
|
||||
5. **HttpAttestorClient.cs** - HTTP client for Attestor service
|
||||
- `POST /internal/api/v1/attestations/verdict`
|
||||
- Sends predicate JSON + subject descriptor
|
||||
- Receives signed attestation metadata
|
||||
|
||||
**Design Decisions**:
|
||||
- Predicate strictly matches `stellaops-policy-verdict.v1.schema.json`
|
||||
- Determinism hash uses sorted evidence digests + verdict triple
|
||||
- Offline-first: no hard dependencies on external services
|
||||
- Feature flag allows gradual rollout
|
||||
|
||||
### 2. Evidence Locker - Verdict Storage & API ✅
|
||||
|
||||
**Location**: `src/EvidenceLocker/StellaOps.EvidenceLocker/`
|
||||
|
||||
#### Files Created:
|
||||
|
||||
1. **Migrations/001_CreateVerdictAttestations.sql**
|
||||
- Table: `evidence_locker.verdict_attestations`
|
||||
- Columns: verdict_id (PK), tenant_id, run_id, finding_id, policy metadata, verdict triple, envelope (JSONB), digests, rekor_log_index, timestamps
|
||||
- Indexes: run_id, finding_id, tenant+evaluated_at
|
||||
- CHECK constraint on verdict_status enum
|
||||
- Audit trigger: `audit_verdict_attestations_changes`
|
||||
|
||||
2. **Storage/IVerdictRepository.cs** - Repository interface
|
||||
- `StoreVerdictAsync(record)` - Upsert verdict attestation
|
||||
- `GetVerdictAsync(verdictId)` - Retrieve full record with envelope
|
||||
- `ListVerdictsForRunAsync(runId, options)` - Query verdicts by run with filtering
|
||||
- `ListVerdictsAsync(tenantId, options)` - Query verdicts by tenant
|
||||
- `CountVerdictsForRunAsync(runId, options)` - Pagination count
|
||||
- Records: `VerdictAttestationRecord`, `VerdictAttestationSummary`, `VerdictListOptions`
|
||||
|
||||
3. **Storage/PostgresVerdictRepository.cs** - PostgreSQL implementation
|
||||
- Uses Npgsql + Dapper for data access
|
||||
- JSONB storage for DSSE envelope with GIN index
|
||||
- ON CONFLICT handling for idempotent upserts
|
||||
- Filtering by status/severity with pagination
|
||||
- Tenant isolation via WHERE clauses
|
||||
|
||||
4. **Api/VerdictContracts.cs** - API response DTOs
|
||||
- `GetVerdictResponse` - Full verdict with envelope
|
||||
- `ListVerdictsResponse` - Paged list of summaries
|
||||
- `VerdictSummary` - Lightweight verdict metadata
|
||||
- `VerifyVerdictResponse` - Signature verification results
|
||||
- `SignatureVerification`, `RekorVerification` - Crypto details
|
||||
- JSON serialization with snake_case naming
|
||||
|
||||
5. **Api/VerdictEndpoints.cs** - Minimal API endpoints
|
||||
- `GET /api/v1/verdicts/{verdictId}` - Retrieve verdict
|
||||
- `GET /api/v1/runs/{runId}/verdicts` - List verdicts for run
|
||||
- `POST /api/v1/verdicts/{verdictId}/verify` - Verify signature (TODO: implementation)
|
||||
- Structured logging for all operations
|
||||
- Error handling with problem details
|
||||
|
||||
6. **StellaOps.EvidenceLocker.csproj** - Project file
|
||||
- Dependencies: Npgsql 9.0.3, Dapper 2.1.35, OpenTelemetry, Serilog
|
||||
- Project references: Scheduler.Models, Policy.Engine, Configuration, DependencyInjection, Auth, Telemetry
|
||||
|
||||
#### Integration Points:
|
||||
|
||||
1. **DI Registration** - Updated `EvidenceLockerInfrastructureServiceCollectionExtensions.cs`
|
||||
- Registered `IVerdictRepository` → `PostgresVerdictRepository`
|
||||
- Connection string from `EvidenceLockerOptions.Database.ConnectionString`
|
||||
|
||||
2. **WebService Wiring** - Updated `StellaOps.EvidenceLocker.WebService/Program.cs`
|
||||
- Added `using StellaOps.EvidenceLocker.Api`
|
||||
- Called `app.MapVerdictEndpoints()` before `app.Run()`
|
||||
|
||||
3. **Project References** - Updated `.csproj` files
|
||||
- `WebService.csproj` → references `StellaOps.EvidenceLocker.csproj`
|
||||
- `Infrastructure.csproj` → references `StellaOps.EvidenceLocker.csproj`
|
||||
- Fixed package versions: Npgsql 9.0.3, Dapper 2.1.35
|
||||
|
||||
**Design Decisions**:
|
||||
- PostgreSQL JSONB for envelope storage (queryable + compact)
|
||||
- Separate verdict fields for efficient indexing without JSON extraction
|
||||
- Determinism hash stored for replay verification
|
||||
- Optional Rekor log index for transparency
|
||||
- Repository pattern for testability
|
||||
- Minimal APIs for lightweight endpoints
|
||||
|
||||
## Blocked Work
|
||||
|
||||
### 3. Attestor - VerdictAttestationHandler ⚠️ BLOCKED
|
||||
|
||||
**Blocking Issue**: Pre-existing build errors in Attestor dependencies:
|
||||
- `StellaOps.Replay.Core`: Missing YamlDotNet assembly reference
|
||||
- `StellaOps.Attestor.ProofChain`: Missing Envelope namespace, ILogger references
|
||||
|
||||
**Planned Implementation** (when unblocked):
|
||||
|
||||
**Location**: `src/Attestor/StellaOps.Attestor/StellaOps.Attestor.WebService/`
|
||||
|
||||
#### Planned Files:
|
||||
|
||||
1. **Handlers/VerdictAttestationHandler.cs**
|
||||
```csharp
|
||||
public class VerdictAttestationHandler
|
||||
{
|
||||
private readonly IAttestationSigningService _signingService;
|
||||
private readonly IVerdictRepository _verdictRepository;
|
||||
private readonly ITransparencyWitnessClient _transparencyClient;
|
||||
|
||||
public async Task<VerdictAttestationResponse> HandleAsync(
|
||||
VerdictAttestationRequest request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. Validate predicate schema
|
||||
// 2. Create AttestationSignRequest with predicate payload
|
||||
// 3. Sign with IAttestationSigningService
|
||||
// 4. Extract DSSE envelope from result
|
||||
// 5. Store in Evidence Locker via IVerdictRepository
|
||||
// 6. Optional: Submit to Rekor via ITransparencyWitnessClient
|
||||
// 7. Return verdict ID + attestation URI
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. **Endpoints** - Add to WebService Program.cs
|
||||
- `POST /internal/api/v1/attestations/verdict` - Create verdict attestation
|
||||
- Accepts predicate JSON + subject descriptor
|
||||
- Returns verdict ID + DSSE envelope URI
|
||||
|
||||
3. **DI Registration**
|
||||
- Register `VerdictAttestationHandler` as scoped service
|
||||
- Wire up dependencies: signing, storage, transparency
|
||||
|
||||
**Dependencies**:
|
||||
- ✅ `IAttestationSigningService` - Existing
|
||||
- ✅ `ITransparencyWitnessClient` - Existing
|
||||
- ✅ `IVerdictRepository` - Implemented (Evidence Locker)
|
||||
- ❌ Build environment - **BLOCKED**
|
||||
|
||||
## Pending Work
|
||||
|
||||
### 4. Policy Engine Integration ⏸️
|
||||
|
||||
**Task**: Wire Policy Engine to call VerdictAttestationService after verdict evaluation
|
||||
|
||||
**Location**: `src/Policy/StellaOps.Policy.Engine/Evaluation/PolicyEvaluator.cs` (or similar)
|
||||
|
||||
**Changes Needed**:
|
||||
1. Inject `IVerdictAttestationService` into evaluator
|
||||
2. After successful policy evaluation, call `AttestVerdictAsync(trace)`
|
||||
3. Store returned verdict ID in evaluation metadata
|
||||
4. Ensure async context properly propagated
|
||||
|
||||
**Depends On**: Task 3 (Attestor Handler) completion
|
||||
|
||||
### 5. Unit Tests ⏸️
|
||||
|
||||
**Location**: `src/Policy/StellaOps.Policy.Engine/__Tests/`
|
||||
|
||||
**Files to Create**:
|
||||
|
||||
1. **VerdictPredicateBuilderTests.cs**
|
||||
- Test: Schema validation (predicate matches JSON schema)
|
||||
- Test: Determinism hash stability (same input → same hash)
|
||||
- Test: Rule chain mapping accuracy
|
||||
- Test: Evidence digest computation
|
||||
- Test: VEX impact extraction
|
||||
- Test: Reachability data mapping
|
||||
- Test: Canonical JSON serialization (key ordering)
|
||||
|
||||
2. **VerdictAttestationServiceTests.cs**
|
||||
- Test: Feature flag disabled (returns null)
|
||||
- Test: Successful attestation flow
|
||||
- Test: HTTP client failure handling
|
||||
- Test: Predicate serialization errors
|
||||
|
||||
3. **Integration Test**
|
||||
- Test: End-to-end policy run → verdict attestation → storage → retrieval
|
||||
- Test: Deterministic replay (same inputs → same determinism hash)
|
||||
- Test: Signature verification
|
||||
|
||||
**Depends On**: Task 3, 4 completion
|
||||
|
||||
### 6. CLI Commands ⏸️
|
||||
|
||||
**Location**: `src/Cli/StellaOps.Cli/Commands/`
|
||||
|
||||
**Commands to Add**:
|
||||
|
||||
1. `stella verdict get <verdict-id>` - Retrieve verdict attestation
|
||||
2. `stella verdict verify <verdict-id>` - Verify signature
|
||||
3. `stella verdict list --run <run-id>` - List verdicts for run
|
||||
4. `stella verdict download <verdict-id> --output <path>` - Download DSSE bundle
|
||||
|
||||
**Depends On**: Task 3, 4, 5 completion
|
||||
|
||||
## Architecture Summary
|
||||
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ Policy Engine │
|
||||
│ - Evaluates │
|
||||
│ - Generates │
|
||||
│ Trace │
|
||||
└────────┬────────┘
|
||||
│ PolicyExplainTrace
|
||||
▼
|
||||
┌────────────────────────────┐
|
||||
│ VerdictPredicateBuilder │
|
||||
│ - Converts Trace │
|
||||
│ - Computes Determinism │
|
||||
│ - Serializes Canonical │
|
||||
└────────┬───────────────────┘
|
||||
│ VerdictPredicate
|
||||
▼
|
||||
┌─────────────────────────────────┐
|
||||
│ VerdictAttestationService │
|
||||
│ - Orchestrates Signing │
|
||||
│ - Calls Attestor │
|
||||
└────────┬────────────────────────┘
|
||||
│ HTTP POST /internal/api/v1/attestations/verdict
|
||||
▼
|
||||
┌────────────────────────────────────┐
|
||||
│ Attestor │ ⚠️ BLOCKED
|
||||
│ - VerdictAttestationHandler │
|
||||
│ - IAttestationSigningService │
|
||||
│ - Creates DSSE Envelope │
|
||||
└────────┬───────────────────────────┘
|
||||
│ VerdictAttestationRecord
|
||||
▼
|
||||
┌──────────────────────────────────┐
|
||||
│ Evidence Locker │ ✅ COMPLETE
|
||||
│ - PostgresVerdictRepository │
|
||||
│ - Stores Attestations │
|
||||
│ - Provides Query API │
|
||||
└──────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
### Immediate Actions Required:
|
||||
|
||||
1. **Fix Attestor Build Errors** (Infrastructure team)
|
||||
- Add missing YamlDotNet package reference to Replay.Core
|
||||
- Fix ProofChain namespace/using issues
|
||||
- Verify all Attestor dependencies compile
|
||||
|
||||
2. **Implement VerdictAttestationHandler** (This sprint)
|
||||
- Create handler class in Attestor.WebService
|
||||
- Wire up signing service, storage, transparency
|
||||
- Add endpoint to Program.cs
|
||||
- Test end-to-end flow
|
||||
|
||||
3. **Integrate Policy Engine** (This sprint)
|
||||
- Inject attestation service into evaluator
|
||||
- Call after successful verdicts
|
||||
- Store verdict IDs
|
||||
|
||||
4. **Write Unit Tests** (This sprint)
|
||||
- VerdictPredicateBuilder schema/determinism tests
|
||||
- Service integration tests
|
||||
- End-to-end replay tests
|
||||
|
||||
5. **CLI Commands** (Next sprint)
|
||||
- verdict get/verify/list/download
|
||||
- Interactive verification UI
|
||||
|
||||
### Success Criteria:
|
||||
|
||||
- [ ] Policy runs generate cryptographically-signed verdict attestations
|
||||
- [ ] Verdicts stored in Evidence Locker with DSSE envelopes
|
||||
- [ ] Determinism hashes enable bit-for-bit replay verification
|
||||
- [ ] Optional Rekor anchoring for public auditability
|
||||
- [ ] CLI commands for verdict inspection and verification
|
||||
- [ ] Unit test coverage >80% for new code
|
||||
- [ ] Integration tests validate end-to-end flow
|
||||
|
||||
## Technical Debt
|
||||
|
||||
1. **EvidenceLockerDataSource Integration**
|
||||
- Current: PostgresVerdictRepository uses connection string directly
|
||||
- Future: Migrate to use EvidenceLockerDataSource.OpenConnectionAsync()
|
||||
- Benefit: Unified session management, tenant scoping
|
||||
|
||||
2. **Signature Verification Placeholder**
|
||||
- Current: `VerdictEndpoints.VerifyVerdictAsync` returns placeholder response
|
||||
- Future: Implement actual DSSE signature verification
|
||||
- Dependency: Integrate with Attestor verification service
|
||||
|
||||
3. **Pre-existing Attestor Errors**
|
||||
- EvidencePortableBundleService.cs static field access errors
|
||||
- Blocking unrelated to verdict attestation work
|
||||
- Needs separate investigation
|
||||
|
||||
## Resources
|
||||
|
||||
- **JSON Schema**: `docs/schemas/stellaops-policy-verdict.v1.schema.json`
|
||||
- **Documentation**: `docs/policy/verdict-attestations.md`
|
||||
- **Sprint Plan**: `docs/implplan/SPRINT_3000_0100_0001_signed_verdicts.md`
|
||||
- **Evidence Pack Sprint**: `docs/implplan/SPRINT_3000_0100_0002_evidence_packs.md`
|
||||
|
||||
---
|
||||
|
||||
**Status Legend**:
|
||||
- ✅ Complete
|
||||
- ⚠️ Blocked
|
||||
- ⏸️ Pending (blocked by dependencies)
|
||||
- 🔄 In Progress
|
||||
Reference in New Issue
Block a user