use std::sync::Arc;
use async_trait::async_trait;
use futures_util::FutureExt;
mod mem_persistence;
#[cfg(feature = "debug")]
pub use mem_persistence::*;
mod azure_persistence;
#[cfg(feature = "azure")]
pub use azure_persistence::*;
mod aws_persistence;
mod custom_persistence;
pub use custom_persistence::*;
#[cfg(feature = "aws")]
pub use aws_persistence::*;
use crate::cache::DEKCache;
use crate::cmk::CMK;
use crate::error::generator::PersistError;
pub struct DEKPersistService {
cmk: Arc<CMK>,
persister: Arc<DEKPersister>,
cache: Option<Arc<DEKCache>>,
}
impl DEKPersistService {
pub fn new(persister: Arc<DEKPersister>, cmk: Arc<CMK>, cache: Option<Arc<DEKCache>>) -> Self {
Self {
persister,
cmk,
cache,
}
}
pub async fn save_dek(&self, context: String, dek: Vec<u8>) -> Result<Vec<u8>, PersistError> {
let encrypted_dek: Vec<u8> = self.cmk
.encrypt(dek.clone()).await
.map_err(|e| PersistError::CMKError(e))?;
let value = self.persister.persist(&encrypted_dek, context.clone()).await?;
if let Some(cache) = &self.cache {
let _ = cache.set(context, dek);
}
Ok(value)
}
pub async fn fetch_dek(&self, context: String) -> Result<Vec<u8>, PersistError> {
let cached_value = if let Some(cache) = &self.cache { cache.get(&context) } else { None };
let dek = match cached_value {
Some(value) => { value }
None => {
let dek = self.persister.fetch(context.clone()).await?;
let dek = self.cmk.decrypt(dek).await.map_err(|e| PersistError::CMKError(e))?;
if let Some(cache) = &self.cache {
let _ = cache.set(context, dek.clone());
}
dek
}
};
Ok(dek)
}
}
#[async_trait]
pub trait DEKPersisterTrait {
async fn fetch(&self, context: String) -> Result<Vec<u8>, PersistError>;
async fn persist(&self, dek: &Vec<u8>, context: String) -> Result<Vec<u8>, PersistError>;
}
pub enum DEKPersister {
#[cfg(feature = "debug")]
Mem(MemPersister),
#[cfg(feature = "azure")]
Azure(AzurePersister),
#[cfg(feature = "aws")]
AWS(AWSPersister),
Custom(CustomPersister),
}
impl DEKPersister {
pub async fn fetch(&self, context: String) -> Result<Vec<u8>, PersistError> {
(match self {
#[cfg(feature = "debug")]
DEKPersister::Mem(persister) => persister.fetch(context).boxed(),
#[cfg(feature = "azure")]
DEKPersister::Azure(persister) => persister.fetch(context).boxed(),
#[cfg(feature = "aws")]
DEKPersister::AWS(persister) => persister.fetch(context).boxed(),
DEKPersister::Custom(persister) => persister.fetch(context).boxed(),
}).await
}
pub async fn persist(&self, dek: &Vec<u8>, context: String) -> Result<Vec<u8>, PersistError> {
(match self {
#[cfg(feature = "debug")]
DEKPersister::Mem(persister) => persister.persist(dek, context).boxed(),
#[cfg(feature = "azure")]
DEKPersister::Azure(persister) => persister.persist(dek, context).boxed(),
#[cfg(feature = "aws")]
DEKPersister::AWS(persister) => persister.persist(dek, context).boxed(),
DEKPersister::Custom(persister) => persister.persist(dek, context).boxed(),
}).await
}
}