kms-aead 0.25.0

KMS/AEAD envelope encryption for GCP/AWS KMS and Ring AEAD encryption
Documentation
use rsb_derive::Builder;
use std::error::Error;
use std::fmt::Display;
use std::fmt::Formatter;
use std::time::SystemTimeError;

pub type BoxedError = Box<dyn std::error::Error + Send + Sync>;

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

#[derive(Debug)]
pub enum KmsAeadError {
    SystemError(KmsAeadSystemError),
    NetworkError(KmsAeadNetworkError),
    EncryptionError(KmsAeadEncryptionError),
}

impl Display for KmsAeadError {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        match *self {
            KmsAeadError::SystemError(ref err) => err.fmt(f),
            KmsAeadError::NetworkError(ref err) => err.fmt(f),
            KmsAeadError::EncryptionError(ref err) => err.fmt(f),
        }
    }
}

impl std::error::Error for KmsAeadError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match *self {
            KmsAeadError::SystemError(ref err) => Some(err),
            KmsAeadError::NetworkError(ref err) => Some(err),
            KmsAeadError::EncryptionError(ref err) => Some(err),
        }
    }
}

#[derive(Debug, Eq, PartialEq, Clone, Builder)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct KmsAeadErrorPublicGenericDetails {
    pub code: String,
}

#[derive(Debug, Builder)]
pub struct KmsAeadSystemError {
    pub public: KmsAeadErrorPublicGenericDetails,
    pub message: String,
    pub root_cause: Option<BoxedError>,
}

impl Display for KmsAeadSystemError {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(
            f,
            "KmsAead system/internal error: {:?} / {}",
            self.public, self.message
        )
    }
}

impl std::error::Error for KmsAeadSystemError {}

#[derive(Debug, Eq, PartialEq, Clone, Builder)]
pub struct KmsAeadNetworkError {
    pub public: KmsAeadErrorPublicGenericDetails,
    pub message: String,
}

impl Display for KmsAeadNetworkError {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(f, "Network error: {:?} / {}", self.public, self.message)
    }
}

impl std::error::Error for KmsAeadNetworkError {}

#[derive(Debug, Builder)]
pub struct KmsAeadEncryptionError {
    pub public: KmsAeadErrorPublicGenericDetails,
    pub message: String,
    pub root_cause: Option<BoxedError>,
}

impl KmsAeadEncryptionError {
    pub fn create(code: &str, message: &str) -> KmsAeadError {
        KmsAeadError::EncryptionError(KmsAeadEncryptionError::new(
            KmsAeadErrorPublicGenericDetails::new(code.to_string()),
            message.to_string(),
        ))
    }
}

impl Display for KmsAeadEncryptionError {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(
            f,
            "KmsAead encryption error: {:?} / {}",
            self.public, self.message
        )
    }
}

impl std::error::Error for KmsAeadEncryptionError {}

impl From<SystemTimeError> for KmsAeadError {
    fn from(e: SystemTimeError) -> Self {
        KmsAeadError::SystemError(
            KmsAeadSystemError::new(
                KmsAeadErrorPublicGenericDetails::new("SYSTEM_TIME_ERROR".to_string()),
                format!("System time error: {e}"),
            )
            .with_root_cause(Box::new(e)),
        )
    }
}

#[cfg(feature = "gcp")]
impl From<gcloud_sdk::error::Error> for KmsAeadError {
    fn from(e: gcloud_sdk::error::Error) -> Self {
        KmsAeadError::SystemError(
            KmsAeadSystemError::new(
                KmsAeadErrorPublicGenericDetails::new(format!("{:?}", e.kind())),
                format!("GCloud system error: {e}"),
            )
            .with_root_cause(Box::new(e)),
        )
    }
}

#[cfg(feature = "gcp")]
impl From<gcloud_sdk::tonic::Status> for KmsAeadError {
    fn from(status: gcloud_sdk::tonic::Status) -> Self {
        KmsAeadError::NetworkError(KmsAeadNetworkError::new(
            KmsAeadErrorPublicGenericDetails::new(format!("{:?}", status.code())),
            format!("{status}"),
        ))
    }
}

#[cfg(feature = "aws")]
impl<E: Display + Error + Sync + Send + 'static, R: std::fmt::Debug + Sync + Send + 'static>
    From<aws_sdk_kms::error::SdkError<E, R>> for KmsAeadError
{
    fn from(e: aws_sdk_kms::error::SdkError<E, R>) -> Self {
        KmsAeadError::EncryptionError(
            KmsAeadEncryptionError::new(
                KmsAeadErrorPublicGenericDetails::new(format!("{e}")),
                format!("AWS KMS error: {e}"),
            )
            .with_root_cause(Box::new(e)),
        )
    }
}