Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/holger

provenance/src/error.rs

//! Why a piece of provenance was refused. Every variant carries one frozen
//! `holger-provenance-<n>` code; [`ProvenanceError::code`] is an exhaustive match,
//! so a new refusal without a code does not compile.

use holger_errcode as ec;

/// A refusal, with the reason in words.
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum ProvenanceError {
    /// Nothing about these bytes was offered, and provenance is required.
    #[error("no provenance about these bytes was offered: {0}")]
    Missing(String),
    /// The statement or signature names other bytes.
    #[error("the attestation is about other bytes: {0}")]
    SubjectMismatch(String),
    /// A signature does not verify over the exact signed bytes.
    #[error("the signature does not verify: {0}")]
    SignatureInvalid(String),
    /// The signer is not an allowed key and does not chain to the pinned root.
    #[error("the signer is not trusted: {0}")]
    SignerUntrusted(String),
    /// The certificate's issuer and subject are not an allowed identity.
    #[error("the signing identity is not allowed: {0}")]
    IdentityMismatch(String),
    /// The SLSA builder is not allowed.
    #[error("the builder is not allowed: {0}")]
    BuilderNotAllowed(String),
    /// The SLSA build level is below the minimum.
    #[error("the SLSA build level is too low: {0}")]
    SlsaLevelTooLow(String),
    /// The transparency-log entry does not verify.
    #[error("the transparency-log entry does not verify: {0}")]
    TlogUnverified(String),
    /// The material cannot be read.
    #[error("the attestation material cannot be read: {0}")]
    Malformed(String),
    /// The trust root is missing or does not verify.
    #[error("the Sigstore trust root is not usable: {0}")]
    TrustRoot(String),
    /// The policy cannot mean what it says.
    #[error("the provenance policy is not valid: {0}")]
    PolicyInvalid(String),
    /// The certificate was not valid when the log saw the signature.
    #[error("the signing certificate was not valid at the signing time: {0}")]
    CertExpired(String),
    /// Nothing signed was offered, and a signature is required.
    #[error("nothing signed about these bytes was offered: {0}")]
    Unsigned(String),
}

impl ProvenanceError {
    /// The frozen code for this refusal.
    pub fn code(&self) -> &'static ec::ErrCode {
        match self {
            ProvenanceError::Missing(_) => &ec::PROVENANCE_MISSING,
            ProvenanceError::SubjectMismatch(_) => &ec::PROVENANCE_SUBJECT_MISMATCH,
            ProvenanceError::SignatureInvalid(_) => &ec::PROVENANCE_SIGNATURE_INVALID,
            ProvenanceError::SignerUntrusted(_) => &ec::PROVENANCE_SIGNER_UNTRUSTED,
            ProvenanceError::IdentityMismatch(_) => &ec::PROVENANCE_IDENTITY_MISMATCH,
            ProvenanceError::BuilderNotAllowed(_) => &ec::PROVENANCE_BUILDER_NOT_ALLOWED,
            ProvenanceError::SlsaLevelTooLow(_) => &ec::PROVENANCE_SLSA_LEVEL_TOO_LOW,
            ProvenanceError::TlogUnverified(_) => &ec::PROVENANCE_TLOG_UNVERIFIED,
            ProvenanceError::Malformed(_) => &ec::PROVENANCE_MALFORMED,
            ProvenanceError::TrustRoot(_) => &ec::PROVENANCE_TRUST_ROOT,
            ProvenanceError::PolicyInvalid(_) => &ec::PROVENANCE_POLICY_INVALID,
            ProvenanceError::CertExpired(_) => &ec::PROVENANCE_CERT_EXPIRED,
            ProvenanceError::Unsigned(_) => &ec::PROVENANCE_UNSIGNED,
        }
    }

    /// `[holger-provenance-<n>] <sentence>`, the shape every Holger subsystem emits.
    pub fn tagged(&self) -> String {
        self.code().tag(self)
    }

    /// The bare wire code, `holger-provenance-<n>`.
    pub fn code_str(&self) -> &'static str {
        self.code().code
    }
}

/// Shorthand.
pub type Result<T> = std::result::Result<T, ProvenanceError>;