feat(eidas): Implement eIDAS Crypto Plugin with dependency injection and signing capabilities
- Added ServiceCollectionExtensions for eIDAS crypto providers. - Implemented EidasCryptoProvider for handling eIDAS-compliant signatures. - Created LocalEidasProvider for local signing using PKCS#12 keystores. - Defined SignatureLevel and SignatureFormat enums for eIDAS compliance. - Developed TrustServiceProviderClient for remote signing via TSP. - Added configuration support for eIDAS options in the project file. - Implemented unit tests for SM2 compliance and crypto operations. - Introduced dependency injection extensions for SM software and remote plugins.
This commit is contained in:
@@ -0,0 +1,170 @@
|
||||
namespace StellaOps.Scanner.ProofIntegration;
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StellaOps.Attestor.ProofChain.Generators;
|
||||
using StellaOps.Attestor.ProofChain.Models;
|
||||
using StellaOps.Attestor.ProofChain.Statements;
|
||||
using StellaOps.Concelier.ProofService;
|
||||
|
||||
/// <summary>
|
||||
/// Generates VEX verdicts with cryptographic proof references.
|
||||
/// Integrates Scanner vulnerability detection with proof-driven backport detection.
|
||||
/// </summary>
|
||||
public sealed class ProofAwareVexGenerator
|
||||
{
|
||||
private readonly ILogger<ProofAwareVexGenerator> _logger;
|
||||
private readonly BackportProofService _proofService;
|
||||
|
||||
public ProofAwareVexGenerator(
|
||||
ILogger<ProofAwareVexGenerator> logger,
|
||||
BackportProofService proofService)
|
||||
{
|
||||
_logger = logger;
|
||||
_proofService = proofService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate VEX verdict with proof for a vulnerability finding.
|
||||
/// </summary>
|
||||
/// <param name="finding">Vulnerability finding from scanner</param>
|
||||
/// <param name="sbomEntryId">SBOM entry ID for the component</param>
|
||||
/// <param name="policyVersion">Policy version used for decisioning</param>
|
||||
/// <param name="cancellationToken">Cancellation token</param>
|
||||
/// <returns>VEX verdict statement with embedded proof reference</returns>
|
||||
public async Task<VexVerdictWithProof> GenerateVexWithProofAsync(
|
||||
VulnerabilityFinding finding,
|
||||
string sbomEntryId,
|
||||
string policyVersion,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"Generating proof-carrying VEX verdict for {CveId} in {Package}",
|
||||
finding.CveId, finding.PackagePurl);
|
||||
|
||||
// Step 1: Generate cryptographic proof using four-tier detection
|
||||
var proof = await _proofService.GenerateProofAsync(
|
||||
finding.CveId,
|
||||
finding.PackagePurl,
|
||||
cancellationToken);
|
||||
|
||||
if (proof == null)
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"No proof generated for {CveId} in {Package}, using fallback verdict",
|
||||
finding.CveId, finding.PackagePurl);
|
||||
|
||||
// Fallback: Generate VEX without proof
|
||||
return GenerateFallbackVex(finding, sbomEntryId, policyVersion);
|
||||
}
|
||||
|
||||
_logger.LogInformation(
|
||||
"Generated proof {ProofId} with confidence {Confidence:P0} for {CveId}",
|
||||
proof.ProofId, proof.Confidence, finding.CveId);
|
||||
|
||||
// Step 2: Generate VEX verdict with proof reference
|
||||
var reasoningId = GenerateReasoningId(finding, proof);
|
||||
var (statement, proofPayload) = VexProofIntegrator.GenerateWithProofMetadata(
|
||||
proof,
|
||||
sbomEntryId,
|
||||
policyVersion,
|
||||
reasoningId);
|
||||
|
||||
return new VexVerdictWithProof
|
||||
{
|
||||
Statement = statement,
|
||||
ProofPayload = proofPayload,
|
||||
Proof = proof,
|
||||
GeneratedAt = DateTimeOffset.UtcNow
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate VEX verdicts for multiple findings in batch.
|
||||
/// </summary>
|
||||
public async Task<IReadOnlyList<VexVerdictWithProof>> GenerateBatchVexWithProofAsync(
|
||||
IEnumerable<VulnerabilityFinding> findings,
|
||||
string policyVersion,
|
||||
Func<VulnerabilityFinding, string> sbomEntryIdResolver,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var tasks = findings.Select(finding =>
|
||||
{
|
||||
var sbomEntryId = sbomEntryIdResolver(finding);
|
||||
return GenerateVexWithProofAsync(finding, sbomEntryId, policyVersion, cancellationToken);
|
||||
});
|
||||
|
||||
var results = await Task.WhenAll(tasks);
|
||||
return results.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve existing proof for a CVE + package combination.
|
||||
/// Useful for audit replay and verification.
|
||||
/// </summary>
|
||||
public async Task<ProofBlob?> RetrieveProofAsync(
|
||||
string cveId,
|
||||
string packagePurl,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await _proofService.GenerateProofAsync(cveId, packagePurl, cancellationToken);
|
||||
}
|
||||
|
||||
private VexVerdictWithProof GenerateFallbackVex(
|
||||
VulnerabilityFinding finding,
|
||||
string sbomEntryId,
|
||||
string policyVersion)
|
||||
{
|
||||
// Generate basic VEX without proof
|
||||
// This is used when no evidence is available (e.g., newly disclosed CVE)
|
||||
|
||||
var unknownProof = BackportProofGenerator.Unknown(
|
||||
finding.CveId,
|
||||
finding.PackagePurl,
|
||||
"no_evidence_available",
|
||||
Array.Empty<ProofEvidence>());
|
||||
|
||||
var reasoningId = $"reasoning:{finding.CveId}:{finding.PackagePurl}";
|
||||
var (statement, proofPayload) = VexProofIntegrator.GenerateWithProofMetadata(
|
||||
unknownProof,
|
||||
sbomEntryId,
|
||||
policyVersion,
|
||||
reasoningId);
|
||||
|
||||
return new VexVerdictWithProof
|
||||
{
|
||||
Statement = statement,
|
||||
ProofPayload = proofPayload,
|
||||
Proof = unknownProof,
|
||||
GeneratedAt = DateTimeOffset.UtcNow
|
||||
};
|
||||
}
|
||||
|
||||
private string GenerateReasoningId(VulnerabilityFinding finding, ProofBlob proof)
|
||||
{
|
||||
// Reasoning ID format: reasoning:{cve}:{method}:{snapshot}
|
||||
return $"reasoning:{finding.CveId}:{proof.Method}:{proof.SnapshotId}";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Vulnerability finding from scanner.
|
||||
/// </summary>
|
||||
public sealed record VulnerabilityFinding
|
||||
{
|
||||
public required string CveId { get; init; }
|
||||
public required string PackagePurl { get; init; }
|
||||
public required string PackageName { get; init; }
|
||||
public required string PackageVersion { get; init; }
|
||||
public required string Severity { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// VEX verdict with associated proof.
|
||||
/// </summary>
|
||||
public sealed record VexVerdictWithProof
|
||||
{
|
||||
public required VexVerdictStatement Statement { get; init; }
|
||||
public required VexVerdictProofPayload ProofPayload { get; init; }
|
||||
public required ProofBlob Proof { get; init; }
|
||||
public required DateTimeOffset GeneratedAt { get; init; }
|
||||
}
|
||||
Reference in New Issue
Block a user