Some checks failed
Lighthouse CI / Lighthouse Audit (push) Waiting to run
Lighthouse CI / Axe Accessibility Audit (push) Waiting to run
Manifest Integrity / Validate Schema Integrity (push) Waiting to run
Manifest Integrity / Validate Contract Documents (push) Waiting to run
Manifest Integrity / Validate Pack Fixtures (push) Waiting to run
Manifest Integrity / Audit SHA256SUMS Files (push) Waiting to run
Manifest Integrity / Verify Merkle Roots (push) Waiting to run
Policy Lint & Smoke / policy-lint (push) Waiting to run
Policy Simulation / policy-simulate (push) Waiting to run
Docs CI / lint-and-preview (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Findings Ledger CI / build-test (push) Has been cancelled
Findings Ledger CI / migration-validation (push) Has been cancelled
Findings Ledger CI / generate-manifest (push) Has been cancelled
- Implemented tests for Cryptographic Failures (A02) to ensure proper handling of sensitive data, secure algorithms, and key management. - Added tests for Security Misconfiguration (A05) to validate production configurations, security headers, CORS settings, and feature management. - Developed tests for Authentication Failures (A07) to enforce strong password policies, rate limiting, session management, and MFA support. - Created tests for Software and Data Integrity Failures (A08) to verify artifact signatures, SBOM integrity, attestation chains, and feed updates.
200 lines
6.0 KiB
C#
200 lines
6.0 KiB
C#
// =============================================================================
|
|
// IAttestationParser.cs
|
|
// Attestation parsing abstraction for DSSE/in-toto attestations
|
|
// Part of Step 2: Evidence Collection (Task T6)
|
|
// =============================================================================
|
|
|
|
namespace StellaOps.AirGap.Importer.Reconciliation.Parsers;
|
|
|
|
/// <summary>
|
|
/// Interface for parsing DSSE-wrapped in-toto attestations.
|
|
/// </summary>
|
|
public interface IAttestationParser
|
|
{
|
|
/// <summary>
|
|
/// Parses a DSSE envelope from the given file path.
|
|
/// </summary>
|
|
/// <param name="filePath">Path to the attestation file.</param>
|
|
/// <param name="cancellationToken">Cancellation token.</param>
|
|
/// <returns>Parsed attestation result.</returns>
|
|
Task<AttestationParseResult> ParseAsync(string filePath, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Parses a DSSE envelope from a stream.
|
|
/// </summary>
|
|
/// <param name="stream">Stream containing the attestation content.</param>
|
|
/// <param name="cancellationToken">Cancellation token.</param>
|
|
/// <returns>Parsed attestation result.</returns>
|
|
Task<AttestationParseResult> ParseAsync(Stream stream, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Detects if a file is a DSSE attestation.
|
|
/// </summary>
|
|
/// <param name="filePath">Path to the file.</param>
|
|
/// <returns>True if the file appears to be a DSSE attestation.</returns>
|
|
bool IsAttestation(string filePath);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Result of parsing an attestation document.
|
|
/// </summary>
|
|
public sealed record AttestationParseResult
|
|
{
|
|
/// <summary>
|
|
/// Whether parsing was successful.
|
|
/// </summary>
|
|
public bool IsSuccess { get; init; }
|
|
|
|
/// <summary>
|
|
/// Error message if parsing failed.
|
|
/// </summary>
|
|
public string? ErrorMessage { get; init; }
|
|
|
|
/// <summary>
|
|
/// The parsed DSSE envelope.
|
|
/// </summary>
|
|
public DsseEnvelope? Envelope { get; init; }
|
|
|
|
/// <summary>
|
|
/// The parsed in-toto statement (payload).
|
|
/// </summary>
|
|
public InTotoStatement? Statement { get; init; }
|
|
|
|
/// <summary>
|
|
/// Creates a successful parse result.
|
|
/// </summary>
|
|
public static AttestationParseResult Success(DsseEnvelope envelope, InTotoStatement statement)
|
|
{
|
|
return new AttestationParseResult
|
|
{
|
|
IsSuccess = true,
|
|
Envelope = envelope,
|
|
Statement = statement
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a failed parse result.
|
|
/// </summary>
|
|
public static AttestationParseResult Failure(string errorMessage)
|
|
{
|
|
return new AttestationParseResult
|
|
{
|
|
IsSuccess = false,
|
|
ErrorMessage = errorMessage
|
|
};
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents a DSSE (Dead Simple Signing Envelope).
|
|
/// </summary>
|
|
public sealed record DsseEnvelope
|
|
{
|
|
/// <summary>
|
|
/// Payload type (typically "application/vnd.in-toto+json").
|
|
/// </summary>
|
|
public required string PayloadType { get; init; }
|
|
|
|
/// <summary>
|
|
/// Base64-encoded payload.
|
|
/// </summary>
|
|
public required string Payload { get; init; }
|
|
|
|
/// <summary>
|
|
/// Signatures on the envelope.
|
|
/// </summary>
|
|
public IReadOnlyList<DsseSignature> Signatures { get; init; } = [];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents a signature in a DSSE envelope.
|
|
/// </summary>
|
|
public sealed record DsseSignature
|
|
{
|
|
/// <summary>
|
|
/// Key identifier (e.g., key ID or certificate fingerprint).
|
|
/// </summary>
|
|
public string? KeyId { get; init; }
|
|
|
|
/// <summary>
|
|
/// Base64-encoded signature.
|
|
/// </summary>
|
|
public required string Sig { get; init; }
|
|
|
|
/// <summary>
|
|
/// Certificate chain (if present).
|
|
/// </summary>
|
|
public string? Cert { get; init; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents an in-toto statement (attestation payload).
|
|
/// </summary>
|
|
public sealed record InTotoStatement
|
|
{
|
|
/// <summary>
|
|
/// Statement type (typically "https://in-toto.io/Statement/v1").
|
|
/// </summary>
|
|
public required string Type { get; init; }
|
|
|
|
/// <summary>
|
|
/// Predicate type URI (e.g., "https://slsa.dev/provenance/v1").
|
|
/// </summary>
|
|
public required string PredicateType { get; init; }
|
|
|
|
/// <summary>
|
|
/// Subjects (artifacts) this statement applies to.
|
|
/// </summary>
|
|
public IReadOnlyList<InTotoSubject> Subjects { get; init; } = [];
|
|
|
|
/// <summary>
|
|
/// Raw predicate JSON for further processing.
|
|
/// </summary>
|
|
public string? PredicateJson { get; init; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents a subject in an in-toto statement.
|
|
/// </summary>
|
|
public sealed record InTotoSubject
|
|
{
|
|
/// <summary>
|
|
/// Subject name (typically a file path or artifact reference).
|
|
/// </summary>
|
|
public string? Name { get; init; }
|
|
|
|
/// <summary>
|
|
/// Subject digests (algorithm -> hash).
|
|
/// </summary>
|
|
public IReadOnlyDictionary<string, string> Digest { get; init; } = new Dictionary<string, string>();
|
|
|
|
/// <summary>
|
|
/// Gets the normalized SHA-256 digest if available.
|
|
/// </summary>
|
|
public string? GetSha256Digest()
|
|
{
|
|
if (Digest.TryGetValue("sha256", out var hash))
|
|
{
|
|
return "sha256:" + hash.ToLowerInvariant();
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Well-known predicate types for attestations.
|
|
/// </summary>
|
|
public static class PredicateTypes
|
|
{
|
|
public const string SlsaProvenanceV1 = "https://slsa.dev/provenance/v1";
|
|
public const string SlsaProvenanceV02 = "https://slsa.dev/provenance/v0.2";
|
|
public const string InTotoLink = "https://in-toto.io/Link/v1";
|
|
public const string Spdx = "https://spdx.dev/Document";
|
|
public const string CycloneDx = "https://cyclonedx.org/bom";
|
|
public const string OpenVex = "https://openvex.dev/ns/v0.2.0";
|
|
public const string Csaf = "https://docs.oasis-open.org/csaf/csaf/v2.0";
|
|
public const string ScorecardV2 = "https://ossf.github.io/scorecard/v2";
|
|
public const string VulnerabilityReport = "https://cosign.sigstore.dev/attestation/vuln/v1";
|
|
}
|